#ifndef BOX_HXX
#define BOX_HXX

#include "Ray.hxx"

class Box
{
public:
	Vec3f min,max;

	Box() 
	{ 
		Clear();
	};

	inline void Extend(Vec3f a)
	{
		min.SetMin(a);
		max.SetMax(a);
	}

	inline void Extend(Box box)
	{
		Extend(box.min);
		Extend(box.max);
	}

	inline void Clear()
	{
		min = Vec3f(Infinity);
		max = Vec3f(-Infinity);
	}


	std::pair<float, float> Intersect(const Ray &ray)
	{
		float low  = Epsilon,
		      high = Infinity,
		      t1,t2,
		      invRayDir;

		// Doing the slabs algorithm
		invRayDir = 1 / ray.dir.x;
		t1        = (min.x - ray.org.x) * invRayDir;
		t2        = (max.x - ray.org.x) * invRayDir;
		if (invRayDir > 0)
		{
		  if (t1 > low) low   = t1;
		  if (t2 < high) high = t2;
		}
		else 
		{
		  if (t2 > low) low   = t2;
		  if (t1 < high) high = t1;
		}

		invRayDir = 1 / ray.dir.y;
		t1        = (min.y - ray.org.y) * invRayDir;
		t2        = (max.y - ray.org.y) * invRayDir;
		if (invRayDir > 0)
		{
		  if (t1 > low) low   = t1;
		  if (t2 < high) high = t2;
		}
		else
		{
		  if (t2 > low) low   = t2;
		  if (t1 < high) high = t1;
		}

		invRayDir = 1 / ray.dir.z;
		t1        = (min.z - ray.org.z) * invRayDir;
		t2        = (max.z - ray.org.z) * invRayDir;
		if (invRayDir > 0)
		{
		  if (t1 > low) low   = t1;
		  if (t2 < high) high = t2;
		}
		else
		{
		  if (t2 > low) low   = t2;
		  if (t1 < high) high = t1;
		}

		if (low > high)
			return std::make_pair(FLT_MAX, -FLT_MAX);
		else
			return std::make_pair(low,     high);
	}
};

#endif
