#include "kdtreelog.h"
#include "logentry.h"
#include <GL/gl.h>
#include "bounds3d.h"
#include <stdio.h>
#include <iostream.h>
#include "kdtreeintersectvis.h"
#include "prim.h"

KDTreeIntersectVis::KDTreeIntersectVis (const Vis *parent, const LogEntry *someevent) : Vis (parent, someevent) {
  strcpy (_type, "KDTreeIntersect");

  _start = VisManager::FindVisStart (this, someevent);
}

void
KDTreeIntersectVis::Display(const LogEntry* upto) const {
  KDTreeIntersect_Start_Entry *s = (KDTreeIntersect_Start_Entry*)_start->_data;
  // draw start node in hilited wireframe
  glColor3f(1.0,0.6,0.0);  // orange
  s->_start->_bounds.drawWireFrame();

  // variables for start point box of ray
  Bounds3d ptbox;
  Vec4 dim;
  float mindim;

  float m; // multiple for _D when determining 2nd pt along ray
  switch (upto->_event)
    {
    case KDTreeIntersect_Start: // if start entry
      glEnable (GL_BLEND);
      glDisable (GL_DEPTH_TEST);
      glBlendFunc (GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT);
      glBlendColorEXT (0, 0, 0, .5);

      glColor3f(0.0,1.0,0.0); // green

      // draw box around start point of ray for orientation
      ptbox.IncludePoint (s->_R);
      dim = s->_start->_bounds[1] - s->_start->_bounds[0];
      mindim = MAXFLOAT;
      if (dim[0] < mindim && dim[0] != 0.) mindim = dim[0];
      if (dim[1] < mindim && dim[1] != 0.) mindim = dim[1];
      if (dim[2] < mindim && dim[2] != 0.) mindim = dim[2];
      mindim *= .06;
      ptbox[1] += Vec4 (mindim, mindim, mindim);
      ptbox[0] -= Vec4 (mindim, mindim, mindim);
      ptbox.drawFilled ();

      // draw ray
      glBegin(GL_LINES);
      // from start vertex
      glVertex3f( s->_R[0], s->_R[1], s->_R[2] );
      // to multiple of direction vector
      m = 15.0;
      glVertex3f( (s->_R[0] + m*(s->_D[0])),
		  (s->_R[1] + m*(s->_D[1])),
		  (s->_R[2] + m*(s->_D[2])) );
      glEnd();
      glDisable (GL_BLEND);
      break;
    case KDTreeIntersect_End: // if end entry
      KDTreeIntersect_End_Entry *d = (KDTreeIntersect_End_Entry*)upto->_data;
      glColor3f(0.0,1.0,0.0); // green
      
      glEnable (GL_BLEND);
      glDisable (GL_DEPTH_TEST);
      glBlendFunc (GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT);
      glBlendColorEXT (0, 0, 0, .5);

      // draw box around start point of ray for orientation
      ptbox.IncludePoint (s->_R);
      dim = s->_start->_bounds[1] - s->_start->_bounds[0];
      mindim = MAXFLOAT;
      if (dim[0] < mindim && dim[0] != 0.) mindim = dim[0];
      if (dim[1] < mindim && dim[1] != 0.) mindim = dim[1];
      if (dim[2] < mindim && dim[2] != 0.) mindim = dim[2];
      mindim *= .06;
      ptbox[1] += Vec4 (mindim, mindim, mindim);
      ptbox[0] -= Vec4 (mindim, mindim, mindim);
      ptbox.drawFilled ();
      
      //the ray turns red when it hits something.
      if (d->_why == GotHit)
	glColor3f (1., 0., 0.);
      // draw ray from start to intersect point
      glBegin(GL_LINES);
      // from start vertex (given in the start entry)
      glVertex3f( s->_R[0], s->_R[1], s->_R[2] );
      // to intersect pt using t from Hit structure as multiple for dir vec
      m = d->_hit.t;
      glVertex3fv((s->_R + (d->_hit.t * s->_D)).ArrayForGL());
      glEnd();
      
      void DrawCross (const Vec4 &center, float e);
      glColor3f (1., 0., 0.);
      DrawCross ((s->_R + (d->_hit.t * s->_D)), .5);
      // if hit found, draw hit object
      if (d->_why == GotHit)
	d->_hit.obj->Draw();
      glDisable (GL_BLEND);
      break;
    }
}

char * KDTreeIntersectVis::StatusLine (const LogEntry *ours) const {
  char *scratch;
switch (ours->_event)
    {
    case KDTreeIntersect_Start:
      KDTreeIntersect_Start_Entry *s = (KDTreeIntersect_Start_Entry *)(ours->_data);
      scratch = new char [100];
      if (s->_start)
	sprintf (scratch, "finding a ray intersection via the k-d tree");
      else {
	sprintf (scratch, "if we're not given a start cell, find one: if ray starts within the k-d tree bounding box, point locate its cell otherwise intersect the ray with the k-d tree's bbox and point locate on the intersection point.");
      }
      return scratch;
    case KDTreeIntersect_End:
      KDTreeIntersect_End_Entry *d = (KDTreeIntersect_End_Entry *)(ours->_data);
      scratch = new char [100];
      sprintf (scratch, "Checked the ray against all the objects in the cell.");
      if (d->_why == GotHit)
	sprintf (scratch, "A hit was found.");
      else {
	if (d->_why == RanOut)
	  sprintf (scratch, "Ran out of next cells...no intersection found.");
	else
	  sprintf (scratch, "GivenHitBetter...what does this mean?");
      }
      return scratch;
    default:
      cerr << "unknown event " << ours->_name << " for kdtreeintersect.statusline" << endl;
      return newStr(ours->_name);
    }
}

