#include <cassert>
#include <vector>
using namespace std;


#include <commandline.h>
#include <gobj.h>
#include <graphmisc.h>
#include <point.h>
#include <random.h>
#include <triangles3Tdisplay.h>
#include <triangles3Tdisplaytest.h>
#include <triangles3Tdisplaymulticolored.h>
#include <zpr.h>


triangles3Tdisplaytest::triangles3Tdisplaytest()
  : xGraphics(true)
{
}

void triangles3Tdisplaytest::pipe01
(
  uintc n,
  vector<point3<uint> > & tri,
  vector<point3<double> > & pts
)
{
  uint pts0 = pts.size();
  doublec pi(3.141592654);

  assert(n>1);
  double angle = pi*2.0/ (double)n;

  for (uint i=0; i<n; ++i)
  {
    pts.push_back
    ( 
      point3<double>
      ( 
        cos(angle*(double)i), 
        0.0,
        sin(angle*(double)i) 
      )
    );
  }

  for (uint i=0; i<n; ++i)
  {
    pts.push_back
    ( 
      point3<double>( pts[pts0+i].x, 1.0, pts[pts0+i].z)
    );
  }

  for (uint i=1; i<n; ++i)
    tri.push_back( point3<uint>(pts0+i-1, pts0+i-1+n, pts0+i) );
  tri.push_back( point3<uint>(pts0+n-1, pts0+n-1+n, pts0) );

  for (uint i=1; i<n; ++i)
    tri.push_back( point3<uint>(pts0+i-1+n, pts0+i+n, pts0+i) );
  tri.push_back( point3<uint>(pts0+n-1+n, pts0+n, pts0) );
}



void triangles3Tdisplaytest::display01()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  gobj::global->draw();

  glerrordisplay();
  
  glutSwapBuffers();
}

void triangles3Tdisplaytest::keyboard01(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 27:
      exit(0);
      break;
  }
}

void triangles3Tdisplaytest::test01(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(triangles3Tdisplaytest::display01);
  glutKeyboardFunc(triangles3Tdisplaytest::keyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);


  xGraphics.set();

  vector< point3<double> > pts;
  vector< point3<uint> > tri;

  commandline cmd(argc,argv);
  uint n(80);
  cmd.mapvar(n,"n");

  pipe01(n,tri,pts);

  //gobjpush(new gobjglColor3ub(184,134,11) );
  gobjpush(new gobjglColor3ub(119,136,153) );

  triangles3Tdisplay<GLfloat,double> * tridisp =
    new triangles3Tdisplay<GLfloat,double>(tri.size(), & tri[0], & pts[0]);
  gobjpush(tridisp);

  cout << print(pts.begin(),pts.end(),"\n") << endl;
  //cout << printvecfunc(& pts[0],pts.size(),"\n") << endl;
  //cout << printvecfunc(tridisp->vi,tridisp->visize,"\n") << endl;

  //triangles3Tdisplay<> tridisp(tri.size(), & tri[0], & pts[0] );
  //gobjpush(&tridisp);



  /** Mouse interaction. */
  zpr zz;
  glutMainLoop();
}



void triangles3Tdisplaytest::pipe02
(
  uintc n,
  vector<point3<uint> > & tri,
  vector<point3<double> > & pts,
  vector<point3<double> > & normals
)
{
  uint pts0 = pts.size();
  doublec pi(3.141592654);

  assert(n>1);
  double angle = pi*2.0/ (double)n;

  for (uint i=0; i<n; ++i)
  {
    pts.push_back
    ( 
      point3<double>
      ( 
        cos(angle*(double)i), 
        0.0,
        sin(angle*(double)i) 
      )
    );
    normals.push_back( pts[pts0+i] );
  }

  for (uint i=0; i<n; ++i)
  {
    pts.push_back
    ( 
      point3<double>( pts[pts0+i].x, 1.0, pts[pts0+i].z)
    );
    normals.push_back( pts[pts0+i] );
  }

  for (uint i=1; i<n; ++i)
    tri.push_back( point3<uint>(pts0+i-1, pts0+i-1+n, pts0+i) );
  tri.push_back( point3<uint>(pts0+n-1, pts0+n-1+n, pts0) );

  for (uint i=1; i<n; ++i)
    tri.push_back( point3<uint>(pts0+i-1+n, pts0+i+n, pts0+i) );
  tri.push_back( point3<uint>(pts0+n-1+n, pts0+n, pts0) );
}




void triangles3Tdisplaytest::test02(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(triangles3Tdisplaytest::display01);
  glutKeyboardFunc(triangles3Tdisplaytest::keyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);


  xGraphics.set();

  vector< point3<double> > pts;
  vector< point3<uint> > tri;
  vector< point3<double> > normals;

  commandline cmd(argc,argv);
  uint n(80);
  cmd.mapvar(n,"n");

  pipe02(n,tri,pts,normals);

  gobjpush(new gobjglColor3ub(119,136,153) );
  triangles3TdisplayN<GLfloat,double> * tridisp =
    new triangles3TdisplayN<GLfloat,double>(tri.size(), & tri[0], & pts[0], & normals[0]);
  gobjpush(tridisp);

/*
  triangles3fdisplayN<> * tridisp =
    new triangles3fdisplayN<>(tri.size(), & tri[0], & pts[0], & normals[0]);
  gobjpush(tridisp);
*/

/*
  cout << printvecfunc(& pts[0],pts.size(),"\n") << endl;
  //cout << printvecfunc(tridisp->vi,tridisp->visize,"\n") << endl;

  //triangles3fdisplay<> tridisp(tri.size(), & tri[0], & pts[0] );
  //gobjpush(&tridisp);
*/

  /** Mouse interaction. */
  zpr zz;
  glutMainLoop();
}




void triangles3Tdisplaytest::test03(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(triangles3Tdisplaytest::display01);
  glutKeyboardFunc(triangles3Tdisplaytest::keyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);


  xGraphics.set();

  vector< point3<double> > pts;
  vector< point3<uint> > tri;
  vector< point3<double> > normals;
  vector< point3<double> > colors;

  commandline cmd(argc,argv);
  uint n(80);
  cmd.mapvar(n,"n");

  pipe02(n,tri,pts,normals);

  random11<double> r;
  for (uint i=0; i<pts.size(); ++i)
    colors.push_back( point3<double>(r(),r(),r()) );

  //gobjpush(new gobjglColor3ub(119,136,153) );
  triangles3TdisplayNC<GLfloat,double,double> * tridisp =
    new triangles3TdisplayNC<GLfloat,double,double>
      (tri.size(), & tri[0], & pts[0], & normals[0], & colors[0]);
  gobjpush(tridisp);  

  /** Mouse interaction. */
  zpr zz;
  glutMainLoop();
}


void triangles3Tdisplaytest::test04(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(triangles3Tdisplaytest::display01);
  glutKeyboardFunc(triangles3Tdisplaytest::keyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);


  xGraphics.set();

  vector< point3<double> > pts;
  vector< point3<uint> > tri;
  vector< point3<double> > normals;
  vector< point3<double> > colors;

  commandline cmd(argc,argv);
  uint n(80);
  cmd.mapvar(n,"n");

  pipe02(n,tri,pts,normals);

  random11<double> r;
  for (uint i=0; i<tri.size(); ++i)
    colors.push_back( point3<double>(r(),r(),r()) );

  triangles3TdisplayNCpertriangle<GLfloat,double,double> * tridisp =
    new triangles3TdisplayNCpertriangle<GLfloat,double,double>
      (tri.size(), & tri[0], & pts[0], & normals[0], & colors[0]);
  gobjpush(tridisp);  

  /** Mouse interaction. */
  zpr zz;
  glutMainLoop();
}



void triangles3Tdisplaytest::test05(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800,600);
  glutCreateWindow("");
  glutDisplayFunc(triangles3Tdisplaytest::display01);
  glutKeyboardFunc(triangles3Tdisplaytest::keyboard01);

  OpenGLinitialisation();

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_NORMALIZE);

  xGraphics.set();

  vector< point3<double> > pts;
  vector< point3<uint> > tri;
  vector< point3<double> > colors;

  commandline cmd(argc,argv);
  uint n(80);
  cmd.mapvar(n,"n");

  pipe01(n,tri,pts);

/*
  random11<double> r;
  for (uint i=0; i<tri.size(); ++i)
    colors.push_back( point3<double>(r(),r(),r()) );

  triangles3TdisplayCpertriangle<GLfloat,double,double> * tridisp =
    new triangles3TdisplayCpertriangle<GLfloat,double,double>
      (tri.size(), & tri[0], & pts[0], & colors[0]);
  gobjpush(tridisp);  
*/

  triangles3Tdisplaymulticolored<GLfloat,double> * tridisp =
    new triangles3Tdisplaymulticolored<GLfloat,double>
      (tri.size(), & tri[0], & pts[0]);
  gobjpush(tridisp);

  /** Mouse interaction. */
  zpr zz;
  zz.update();
  glutMainLoop();
}



