
#include <pointsgraph.h>
#include <zero.h>

bool pointsgraph::isinside=true;

pointsgraph::pointsgraph() : 
  screen(0.0,0.0,1.0,1.0), 
  world(-1.0,-1.0,1.0,1.0),
  clipwindow(false)
{
}

pointsgraph::pointsgraph
(
  windowscaleD2 const & screen_,
  windowscaleD2 const & world_,
  boolc clipwindow_
)  
  : screen(screen_), world(world_), 
  clipwindow(clipwindow_)
{
}


void pointsgraph::draw()
{
  glBegin(GL_POINTS);

  uint imax=pts.size();

//assert(clipwindow==false);
  if (clipwindow==false)
  {
    for (uint i=0; i<imax; ++i)
    {
      double x = pts[i].x;
      double y = pts[i].y;
cout << SHOW(x) << " " << SHOW(y) << endl;
      if (isinside)
        { asserteval(world.convertfrom(x,y,screen)); }  // Coordinates outside window
      else
        world.convertfrom(x,y,screen); 
      glVertex2d(x,y);
      //glVertex3d(x,y,0.0);
    }
  }
  else
  {
    for (uint i=0; i<imax; ++i)
    {
      double x = pts[i].x;
      double y = pts[i].y;
      world.convertfrom(x,y,screen);
      if (world.isinside(x,y)==false)
        continue;

      glVertex2d(x,y);
    }
  }

  glEnd();
}

void pointsgraph::screen_rescaley()
{
  if (pts.empty())
    return;

  double & ymin(screen.ymin);
  double & ymax(screen.ymax);
  double & xmin(screen.xmin);
  double & xmax(screen.xmax);

  ymin = ymax = pts[0].y;

  uint imax=pts.size();
  double y;
  for (uint i=1; i<imax; ++i)
  {
    // Only consider points in current domain.
    if (pts[i].x<xmin)
      continue;
    if (pts[i].x>xmax)
      continue;

    y = pts[i].y;
    if(y<ymin)
      ymin=y;
    if(y>ymax)
      ymax=y;
  }  
  screen.update();
}

void pointsgraph::update()
{
  screen.update();
  world.update();
}

void pointsgraph::domain(doublec x0, doublec x1)
{
  assert( x0<=x1 );
  screen.xmin=x0;
  screen.xmax=x1;
  screen.update();
}

pointsgraph_axes_circle::pointsgraph_axes_circle()
{
  quadric.radius = 0.02;
  quadric.slices=20;
  quadric.loops=6;

  disablelighting=true;

  xaxiscolor = gobjglColor3d(0.0,.62,.33);
  yaxiscolor = gobjglColor3d(0.05,.12,.83);

  graphics = new gobjContainer();
}

pointsgraph_axes_circle::~pointsgraph_axes_circle()
{
  delete graphics;
  graphics=0;
}

void pointsgraph_axes_circle::update()
{
  assert(graphics);

  graphics->nuke();

  push(new gobjglPushAttrib(GL_CURRENT_BIT));
  push(new gobjglPushAttrib(GL_LIGHTING_BIT));
  if (disablelighting)
    push(new gobjglDisable(GL_LIGHTING));

  push(new gobjglColor3d(xaxiscolor));
  for (uint i=0; i<xaxis.size(); ++i)
  {
    push(new
      gobjMySphereDraw(point3<double>(origin.x+xaxis[i],origin.y,origin.z),&quadric));
  }

  push(new gobjglColor3d(yaxiscolor));
  for (uint i=0; i<yaxis.size(); ++i)
  {
    push(new
      gobjMySphereDraw(point3<double>(origin.x,origin.y+yaxis[i],origin.z),&quadric));
  }

  push(new gobjglPopAttrib());
  push(new gobjglPopAttrib());
}

void pointsgraph_axes_circle::draw()
{
  assert(graphics);
  graphics->draw();
}
  
void pointsgraph_axes_circle::push(gobj* g)
{
  assert(graphics);
  graphics->push(g);
}

pointsgraphtime::pointsgraphtime(uintc N_)
{
  N = N_;

  assert(N!=1);
  assert(N!=0);

  dx = (double)1.0/(N-1);
}

void pointsgraphtime::push_front(double yval)
{
assert(false); // TODO write this function.
  for (uint i=0; i<N; ++i)
    { pts[i].x += dx; }

  pts.push_front( point2<double>(0,yval) );

  if (pts.size()==N)
  {
    pts.pop_back();
    return;
  }

  assert(pts.size()<N);
}

void pointsgraphtime::push_back(double yval)
{
  uint imax=pts.size();
  for (uint i=0; i<imax; ++i)
    { pts[i].x -= dx; }

  if (imax==N)
    pts.pop_front();

  pts.push_back( point2<double>(1.0,yval) );

  assert(pts.size()<=N);
}





