#ifndef GRAPHICSIMMEDIATEDEFERREDTEST_H
#define GRAPHICSIMMEDIATEDEFERREDTEST_H


#include <gobj.h>
#include <graphicsImmediateDeferred.h>
#include <graphicsImmediateDeferredSwitch.h>
#include <graphmisc.h>
#include <point.h>


class graphicsImmediateDeferredTestTri;

/*!
\brief Look at both graphicsImmediateDeferred and graphicsImmediateDeferredSwitch.
*/
class graphicsImmediateDeferredTest
{
  /** Global graphics stream. */
  gobjContainer xGraphics;
public:

  /** Constructor. */
  graphicsImmediateDeferredTest()
    : xGraphics(true) {}

  /** Program documentation on the command line and in the doxygen description. */
  static string doc[];

  /** Test geometry.*/
  static graphicsImmediateDeferredTestTri* model;

  typedef point2<double> pt2;
  /** Toggle the help menu. */

  /** Keyboard handler for test01. */
  static void keyboard01(unsigned char key, int x, int y);

  /** Displays gobj::global . */
  static void display01();

  /** Test opengl rendering */
  void test01(int argc, char** argv);
  /** Use ImmediateDefered callback display. */
  void test02(int argc, char** argv);
  /** Show code that does not work with ImmediateDeferred. */
  void test03(int argc, char** argv);
  /** Add a switch to test02.  */
  void test04(int argc, char** argv);
  /** Functional object with () callback. */
  void test05(int argc, char** argv);
  /** Functional object with (gobjContainer&) callback. */
  void test06(int argc, char** argv);
  /** */
  void test07(int argc, char** argv);

  /** Circle and shape menu options. */
  void menu01();
  /** Circle and shape menu options. */
  void menu02();
};


/*!
\brief Model class for graphicsImmediateDeferredTest.

I used this class to design/test the deferred geometry
 callbacks.  Although the concept is very simple I had
 some trouble getting my head around it.

Basically instead of a copy constructor or some other
 means of copying gobj's, have gobj's which when
 drawn create the geometry(other gobjs).

So while there is no general copy operation, the client
 writes something to create the geometry themselves.
*/
class graphicsImmediateDeferredTestTri : public gobj
{
public:

  /** Move circle. */
  double circledelta;

  /** Geometry. */
  gobjMyCircle circle;
  /** Drawing circle - immediate geometry. */
  gobjMyCircleDraw circledraw;

  /** Set the circle color. */
  gobjglColor3ub circlecolor;

  /** Set the shape color. */
  gobjglColor3ub shapecolor;

  /** draw displays this. */
  gobj* graphics;

  /** Used in graphicscreate02, graphicscreate03, graphicscreate07. */
  graphicsImmediateDeferred* g02;

  /** Used in graphicscreate04, graphicscreate05, graphicscreate06. */
  graphicsImmediateDeferredSwitch* g04;


  /** Toggle the shape. */
  uint g04switch;

  /** Constructor. */
  graphicsImmediateDeferredTestTri() : circledelta(0.1), 
  circledraw(point3<double>(0.0,0.0,0.1),circle), circlecolor(0,255,255), 
  shapecolor(255,0,0), graphics(0), g02(0), g04(0), g04switch(0) 
  {
    graphicsImmediateDeferredTest::model=this;
  }

  /** Draw a shape. */
  void graphicscreate01();
  /** Graphics uses callback class. */ 
  void graphicscreate02();
  /** Without a callback the code can be called once. */
  void graphicscreate03();
  /** Test graphicsImmediateDeferedSwitch */
  void graphicscreate04();
  void graphicscreate05();
  void graphicscreate06();
  /** Use containers pushcallback with deferred geometry. */
  void graphicscreate07();

  /** Push a colored triangle shape to container. */
  void addshape01(gobjContainer & shp);
  /** Push a colored triangle shape to the global graphics stream. */
  void addshape02();

  /** Draws the graphics pointed to by the graphics variable. */
  void draw();
};


/*!
\brief Display a test shape through pushing gobj's to global 
  graphics stream. 

The class when draw called writes graphics, the reference
 is used to forward the work to the reference class and
 call a function on it. 
*/
class graphicsImmediateDeferredTestg02 : public gobj
{
  /** Reference to class that writes the graphics. */
  graphicsImmediateDeferredTestTri& ref;
public:

  /** Constructor. */
  graphicsImmediateDeferredTestg02(graphicsImmediateDeferredTestTri & ref_)
    : ref(ref_) {}

  /** Indirect drawing by pushing geometry to global graphics stream. */
  void draw();
};



#endif


