/* Triangle.h
 *
 * Interface definition for the Triangle class, which stores triangle data and
 * can detect path intersection (collision).
 */

#ifndef TRIANGLE_H_INCLUDED
#define TRIANGLE_H_INCLUDED 1

#include "Obstruction.h"
#include "Vertex.h"
#include <vector>
#include <iostream>
#include <cassert>

#define NUM_OF_COLORS 4 // ambient, diffuse, specular, emissive (in order)

/*
 * We defined our normal to point out clockwise. However,
 * the standard is to point out counter-clockwise. If vertConv
 * is defined, we perform this conversion while the vertices 
 * are being read in.
 */
#define vertConv

class Triangle : public Obstruction
{
private:
	// Member Variables
	Vertex* v1_; // Three vertices representing the normal (umnodified) position
	Vertex* v2_;
	Vertex* v3_;
	Tuple sv1_; // Three tuples representing the standardized position
	Tuple sv2_;
	Tuple sv3_;
	Tuple normal_;
	Tuplex rotation_;
	bool isHole_;

	// Bizzare Triangles
	static bool crazyTris_;
	static double shrinkFactor_; 
	static const double MAX_SHRINKFACTOR;
	static const double MIN_SHRINKFACTOR;
	static const double DEF_SHRINKFACTOR;

	// Color Variables
	std::vector<Tuple> colors_; // ambient, diffuse, specular, emissive (in order)
	static const Tuple DEF_COLOR; // default color
	static const float SHININESS;

	// Averages position of all vertices
	const Tuple avgPos() const;

public:
	// Constructors/Destructor
	Triangle(Vertex* v1, Vertex* v2, Vertex* v3);
	virtual ~Triangle();

	// Member Functions
	virtual void			draw(bool light) const;	// Draw the triangle
	virtual const double	pathIntersect(	// Check if path hits triangle
		const Path& path,
		double radius) const;
	virtual const Tuple		calcNormal(		// Find normal relative to some pos
		const Tuple& point) const;

	// Color Functions
	const Tuple ambient () const {assert(colors_.size() == NUM_OF_COLORS); return colors_[0];}
	const Tuple diffuse () const {assert(colors_.size() == NUM_OF_COLORS); return colors_[1];}
	const Tuple specular() const {assert(colors_.size() == NUM_OF_COLORS); return colors_[2];}
	const Tuple emissive() const {assert(colors_.size() == NUM_OF_COLORS); return colors_[3];}
	
	void setColors(const std::vector<Tuple>& colors); 
	void setAmbient (const Tuple& color) {assert(colors_.size() == NUM_OF_COLORS); colors_[0] = color;}
	void setDiffuse (const Tuple& color) {assert(colors_.size() == NUM_OF_COLORS); colors_[1] = color;}
	void setSpecular(const Tuple& color) {assert(colors_.size() == NUM_OF_COLORS); colors_[2] = color;}
	void setEmissive(const Tuple& color) {assert(colors_.size() == NUM_OF_COLORS); colors_[3] = color;}

	// Utilities
	virtual const bool isHole() const {return isHole_;}
	void setIsHole(bool isHole) {isHole_ = isHole;}

	void print() { std::cout << v1_->v() << " " << v2_->v() << " " << v3_->v() << std::endl; }

	// Resize triangles
	static void toggleCrazyTris();
	static void setCrazyTris();
	static void unsetCrazyTris();
	static void setShrinkFactor(double shrinkFactor = DEF_SHRINKFACTOR);
	static void shrink();
	static void enlarge();
};



#endif // TRIANGLE_H_INCLUDED
