#ifdef _WINDOWS
#include <windows.h>
#endif
#include "assert.h"
#include "box.h"

#include "jllib_include.h" // for MIN(a,b) and MAX(a,b)

#include "globals.h"
#include "ray.h"


Box::Box() {

	_x1 = _y1 = _z1 = -1;
	_x2 = _y2 = _z2 = 1;
	_bounds.Set (_x1, _x2, _y1, _y2, _z1, _z2);
}

Box::Box(real x1, real y1, real z1, real x2, real y2, real z2) {

	_x1 = x1;
	_y1 = y1;
	_z1 = z1;
	_x2 = x2;
	_y2 = y2;
	_z2 = z2;
	_bounds.Set (_x1, _x2, _y1, _y2, _z1, _z2);
}

Box::~Box() {
}

Box& Box::CopyFrom(const Box &B) {

	Prim::CopyFrom(B);

	_x1 = B._x1;
	_y1 = B._y1;
	_z1 = B._z1;
	_x2 = B._x2;
	_y2 = B._y2;
	_z2 = B._z2;

	_bounds.Set (_x1, _x2, _y1, _y2, _z1, _z2);
	return *this;
}

/*
ostream& operator<<(ostream &co, const Box &B) {

	return co;
}

istream& operator>>(istream &ci, Box &B) {

	return ci;
}
*/

static inline void _jl_Sort(real &a, real &b) {

	if (a>b) {
		real c = a;
		a = b;
		b = c;
	}
}

//XXX todo
void Box::IntersectCertain(const Ray &ray, Hit &hit) {
Intersect (ray, hit);
}

void Box::Intersect(const Ray &ray, Hit &hit) { 

  real hitt;

  int face, dir;
  int wherehit;
  
  wherehit = _bounds.Intersect (ray, hitt, face, dir);

  //  if (hitt < 0)
  //    hit.num_bbox_quick_rejects++;

  hit.num_box_intersections++;

  if (hitt < 0) //did quick reject!
    return;

  if (wherehit)
    hit.num_intersect_successes++;

  if (wherehit && (hit.t > hitt))
	{
	  hit.t = hitt;
	  hit.obj = this;
	  hit.texcalced = 1;
	  hit.normalcalced = 1;
	  //if wherehit == 1, we hit coming in
	  //if ==2, we hit going out. great!

	  hit.normal.Set (0, 0,0);
	  hit.normal[face] = (ray.Direction(face) >= 0) ? -1 : 1;

	  Vec4 pt = ray.R() + ray.D() * hitt;
	  if ( face == 0) 
	    {
	      hit.texs = (pt.z() - _z1);
	      hit.text = (pt.y() - _y1);
	    }
	  else if ( face == 1) 
	    {
	      hit.texs = (pt.x() - _x1);
	      hit.text = (pt.z() - _z1);
	    }
	  else if ( face == 2) 
	    {
	      hit.texs = (pt.x() - _x1);
	      hit.text = (pt.y() - _y1);
	    }
	  else
	    {
	      cerr << "pt of intersection was " << pt << ", not quite close enough to " << bbox() << endl;
	      cerr << "pt.y is " << pt.y() << ", _y2 is " << _y2 << endl;
	    }
	}
}



int Box::IntersectLinespace(const Ray&, const Ray&,
							const Ray&, const Ray&,
							const Vec4&, const Vec4&,
							const Vec4&, const Vec4&) {

	// implement this

	return NO_INTERSECTION;
}

void Box::calcST (const Vec4 &pt, real &s, real &t) const
{
  if ( equal (pt.x(), _x1) || equal (pt.x(), _x2) )
    {
      s = (pt.z() - _z1);
      t = (pt.y() - _y1);
    }
  else if ( equal (pt.y(), _y1) || equal (pt.y(), _y2) )
    {
      s = (pt.x() - _x1);
      t = (pt.z() - _z1);
    }
  else 
    {
      assert ( equal (pt.z(), _z1) || equal (pt.z(), _z2) );
      s = (pt.x() - _x1);
      t = (pt.y() - _y1);
    }
}

