#ifndef TRIANGLE_HXX
#define TRIANGLE_HXX

#include "Primitive.hxx"
#include "Shader.hxx"
#include "Box.hxx"

using namespace std;

class Triangle : public Primitive
{
	Vec3f a, b, c, edge1, edge2, normal, min, max;
	Box   box;
public:
	Triangle(Vec3f a, Vec3f b, Vec3f c, Shader *shader)
		: Primitive(shader),a(a),b(b),c(c)
	{
		// Precomputation general
		edge1 = b - a;
		edge2 = c - a;

		// Precomputation normal
		normal = Cross(edge1, edge2);
		Normalize(normal);

		// Precomputation bounds
		box.Extend(a);
		box.Extend(b);
		box.Extend(c);
	};

	virtual ~Triangle(){};

	virtual bool Intersect(Ray &ray)
	{
		const Vec3f pvec = ray.dir^edge2;

		const float det = Dot(edge1, pvec);
		if (fabs(det) < Epsilon)
			return false;

		const float inv_det = 1.0f / det;

		const Vec3f tvec = ray.org - a;
		float lambda = Dot(tvec, pvec);
		lambda *= inv_det;

		if (lambda < 0.0f || lambda > 1.0f)
			return false;

		const Vec3f qvec = tvec^edge1;
		float mue = Dot(ray.dir, qvec);
		mue *= inv_det;

		if (mue < 0.0f || mue + lambda > 1.0f)
			return false;

		float f = Dot(edge2, qvec);
		f *= inv_det;
		if (ray.t <= f || f <  1E-4  )
			return false;

		ray.u = lambda;
		ray.v = mue;

		ray.t   = f;
		ray.hit = this;

		return true;
	};

	virtual Vec3f GetNormal(Ray &ray)
	{
		return normal;
	};

	virtual Box CalcBounds()
	{
		return box;
	}
};

#endif
