
#include <cstdlib>
using namespace std;



#include <gobj.h>
#include <graphmisc.h>
#include <menusystem.h>
#include <menusystemtest.h>
#include <primitivewindow.h>
#include <zpr.h>


menusystem * menusystemtest::current = 0;
primitiveWindow * menusystemtest::pw = 0;

typedef point3<double> pt3;

class menu01 : public menusystem
{
public:

  menu01();

protected:

  int state;
  
  void readBufferedTerminationAction()
  {
    if (state==1)
    {
      cout << SHOW(readBufferedResult) << endl;
      state=0;
    }
 
  }

  void readImmediate(char const ch);
  
};


class menu02: public menusystemOneShot
{
public:

  menu02()
    : menusystemOneShot(point2<int>(160,30),20,1,menusystemOneShot::drawmenuparents)
  {
    addfont12("Read a String Menu",1);
    addfont10("Input a string:  ");
  }
};



class menu03 : public menusystem
{
public:

  menu03();

  void draw();

protected:
  void readImmediate(char const ch);
};

class menu04 : public menusystem
{
public:

  menu04();

  void draw();

protected:
  void readImmediate(char const ch);
};


void menu01::readImmediate(char const ch)
{
  switch (ch)
  {
    case '1':  
      transfercontroltosubmenu(0);
      break;
    
    case '2':
      readmodeimmediate=false;
      readBufferedSet(2);
      state=1;
      break;

    case '3':
      transfercontroltosubmenu(1);
      break;

    case 27:
      exit(0);
      break;
  }
}


menu01::menu01() : 
  menusystem(this,0,true,point2<int>(60,30),20)
{
  addfont12("  Main Menu",1);
  addfont10("1.  Read a string in.",1);
  addfont10("2.  Read a string in immediately:  ",1);
/*
  addfont10("2.  Read a string in immediately:  ");
  Xpush();
  X.x += 120;
  addfont10("");
  Xpop();
  addnewline();
*/
  addfont10("3.  Submenu",1);
  addfont10("ESC Quit");
}

void menu03::draw()
{
  drawparent();
  menusystem::draw();
}


void menu03::readImmediate(char const ch)
{
  switch (ch)
  {
    case '1':  
      transfercontroltosubmenu(0);
      break;

    case '3': transfercontroltoparent(); 
      break;
    
    case 27:
      exit(0);
      break;
  }
}

menu03::menu03() : 
  menusystem(this,0,true,point2<int>(120,30),20)
{
  addnewline(3);
  addfont12("  Submenu Menu",1);
  addfont10("1.  Documentation",1);
  addfont10("2.",1);
  addfont10("3.  Back",1);
  addfont10("ESC Quit");
}

void menu04::readImmediate(char const ch)
{
//cout << "@@@" << endl;
  transfercontroltoparent(); 
}

menu04::menu04() : 
  menusystem(this,0,true,point2<int>(210,30),20)
{
  addnewline(4);
  addfont10("These menus are all slightly different to explore ",1);
  addfont10("how menus can be construted.  The main menu has two",1);
  addfont10("ways to input a string, one vi a dedicated menu and",1);
  addfont10("the other at a point in the current menu.",2);
  addfont10("The submenu displays its parent.  The menus do not",1);
  addfont10("by default display their parents. The documentation",1); 
  addfont10("menu uses a function to do this.",2);

  string para;
  para += "Behind the scenes there is a smart pointer working. ";
  para += "The client links the menus which are flat - no ";
  para += "imbedded crap for simplicity.  An external ref ";
  para += "points to any one of the menus and the right display ";
  para += "and key catching is matched. ";

  addfont10paragraph(para,40,2);

  addfont10("Any Key  Back");

  X0 = point2<int>(410,110);
  reset();

  para.clear();
  para += "The class is in one of two modes - immediate or buffered. ";
  para += "In buffered mode characters are printed to the screen as they ";
  para += "are typed.  In immediate mode characters are the commands and ";
  para += "each menu can catches and handles the command.";
  addfont10paragraph(para,40,1);
  para.clear();

  para += "These last few paragraphs were formatted by a little routine";
  para += "All these menus are positioned by hand.  Unlike a ";
  para += "modern menu system which manages alignment this is ";
  para += "a primitive menu system.  But it is powerful enough";
  para += "to do all that you would at the command line. ";
  addfont10paragraph(para,40);

}

void menu04::draw()
{
  drawparents();
  menusystem::draw();
}

class t01
{
public:
  ostream & print(ostream & os) const;

};


ostream & t01::print(ostream & os) const
{
  os << "t01" << endl;
  os << "have fun" << endl;
  os << "The quick brown fox jumped over the lazy dog.";
  os << "life sux." << endl << endl;
  return os;
}

ostream & operator << (ostream & os, t01 const & x)
{
  return x.print(os);
}

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

  OpenGLinitialisation();

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

  xGraphics.set();

  menu01 * m1 = new menu01();
  m1->addsubmenu( new menu02() );
  menu03 * m3 = new menu03();
  m1->addsubmenu( m3 );
  m3->addsubmenu( new menu04() );
  current = m1;

  pw = new primitiveWindow( point3<double>(0.0,0.0,0.0), 0.1 );

  string tmp("cat \n mat");

  *pw << tmp;
///  *pw << t01();

  t01 tmp2;
//  cout << tmp2 << endl;
  *pw << tmp2;
  //t01().print(*pw);

  tmp = "The weather is very lovely if you like it hot. I have to write ";
  tmp += "some silly text and display it, though I am looking forward to ";
  tmp += "seeing this software in the product.";

  pw->addparagraph(tmp,63);

  pw->vg.push_back
  ( 
    new gobjMyBitmapCharacter
    (
      "be happy?",
      point3<double>(.2,.3,.7),
      GLUT_BITMAP_HELVETICA_18
    ) 
  );

  zpr zz;

  zz.update();
  glutMainLoop();
}


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

  //xGraphics.draw();
  assert(current!=0);
  current->draw();

  pw->draw();

  glerrordisplay();
  glutSwapBuffers();
}

void menusystemtest::keyboard01
(
  unsigned char key, 
  int x, 
  int y
)
{
  assert(current!=0);
  current->read(key);
}

void menusystemtest::display02()
{ 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  gobj::global->draw();

  glerrordisplay();
  
  glutSwapBuffers();
}

void menusystemtest::keyboard02
(
  unsigned char key, 
  int x, 
  int y
)
{
  static uint messageid=1;

  switch (key)
  {
    case 27: exit(0); break;
    case 'm': 
    {
      stringstream ss;
      ss << messageid++;
      current->addfont12start(ss.str() + " message.",1);
    }
    break;

    case ' ': current->scrolldown(); break;
   
    case 'M': 
    {
      string str = "This is some text. It has to be a paragraph. ";
      str += "Testing the paragraph writing in the message mode.";
      current->addfont10paragraphstart(str,40,1);
    }
    break;

    case 'a':
    {
      string str = "1.Cabbage\n2.Tomatoes\n3.Pears";
      current->addfont10blockstart(str,1);
    }
    break;
   
  }

  glutPostRedisplay();
}

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

  OpenGLinitialisation();

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

  xGraphics.set();

  current = 
    new menusystem(0,0,true,point2<GLint>(60,50),10);
  gobjpush(current);
  current->fontcolor = point4<float>(1.0,0.0,0.0,0.8);
  current->lightingdisable();

  menusystem * mainmenu = 
    new menusystem(0,0,true,point2<GLint>(250,70),10);
  mainmenu->fontcolor = point4<float>(240.0/255.0,192.0/255.0,10.0/255.0,0.8);
  mainmenu->addfont12("menusystem test",2);
  mainmenu->addfont10("m    - print a message.",1);
  mainmenu->addfont10("M    - print a paragraph(no user returns in string).",1);
  mainmenu->addfont10("space",1);
  mainmenu->addfont10("a    - print a block(user returns in string).",1);
  gobjpush(mainmenu);

 
  //current->addfont12start("The first message.",1);

  zpr zz;

  zz.update();
  glutMainLoop();
}



