/*
* Filename: D:\Studienarbeit\Beispiel4\Beispiel4.cpp
* Version: 1.0
* Date: Tue Sept 8
* Author: junge
*/

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#endif /*WIN32*/

#ifdef __linux
#include <typeinfo>
#else
#include <typeinfo.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include "StrmSet.h"

#include "XGraph/XGraph.h"
#include "XGraph/AllPrims.h"
#include "XGraph/AllViews.h"

#include <tcl.h>
#include <tk.h>

#include "Messager.h"

#include "Vec3D.h"
#include "Angle.h"
#include "HMatrx3D.h"


Tk_TimerToken timerToken = NULL;
Tcl_Interp *MainInterp = NULL;

int i = 0;

RGBAColor bgCol(1.0, 1.0, 1.0);

ToglView *Client;
Space *MySpace = new Space ();

GeoObject *stapler = new GeoObject ();
GeoObject *gabel = new GeoObject ();


unsigned isInit = 0;

Vec3D CamPos   = Vec3D( 0.0, -20.0, 0.0);
Vec3D CamFocus = Vec3D( 0.0,   0.0, 0.0);
Vec3D CamUp    = Vec3D( 0.0,   0.0, 1.0); // EZ
ViewPoint ObjViewPoint(CamPos, CamFocus, CamUp);


void newView () {
  char buf[255];
  Ustring win (".top");
  win += Ustring (isInit);
  sprintf(buf, "makeTopLevel %s", win.str ());
  Tcl_Eval (MainInterp, buf);
  isInit++;
  ObjViewPoint = ViewPoint(CamPos, CamFocus, CamUp);
  Client = new ToglView (100, 100, 300, 300, bgCol, win.str (),(win + ".menu.look").str ());
  Client->addViewPoint (Ustring ("Default"), ObjViewPoint);
  Client->addViewPoint (Ustring ("Iso"),
                 ViewPoint( Vec3D (-12.37, -12.32,  9.75), //CamPos
                            Vec3D ( -1.42,   1.00, -0.40), //CamFoc
                            Vec3D (  0.20,   0.30,  0.60)  //CamUp
                           ) );
  Client->lightOn ();
  Client->smoothOn ();
  MySpace->insertView (*Client);
  Client->showGrid();
}

void InitModell () {
  fprintf(stdout,"InitModell A1:\n");
  if (!isInit) {
  fprintf(stdout,"InitModell A2:\n");

//######################################
//        Attribute
//######################################
    Attribute *chocAttrib   = ColorAttribute::create ("chocolate1");
    Attribute *gray50Attrib   = ColorAttribute::create ("gray50");
    Attribute *gray12Attrib   = ColorAttribute::create ("gray12");

//######################################
//        Primitiven
//######################################
    Primitive *Cubus   = Cube::create (Vec3D (-1.0, -0.5, -0.7), Vec3D (1.0, 0.5, 0.0));
    Primitive *Cubus2   = Cube::create (Vec3D (-1.0, -0.5, -0.0), Vec3D (0.5, 0.5, 1.0));

    Primitive *Rect     = PlaneQuad::create (Vec3D(0.520,-0.450,0.100), Vec3D(0.520, 0.450, 0.100), Vec3D(0.520, 0.450, 0.900), Vec3D(0.520, -0.450, 0.900));
    Primitive *Rect2     = PlaneQuad::create (Vec3D(-0.900,-0.520,0.100), Vec3D(0.400,-0.520,0.100), Vec3D(0.400,-0.520,0.900), Vec3D(-0.900,-0.520,0.900));
    Primitive *Rect3     = PlaneQuad::create (Vec3D(-0.900,0.520,0.100), Vec3D(-0.900,0.520,0.900), Vec3D(0.400,0.520,0.900), Vec3D(0.400,0.520,0.100));

    Primitive *Cubus3   = Cube::create (Vec3D (1.000,-0.400,-0.700), Vec3D (1.100,-0.200,2.000));
    Primitive *Cubus4   = Cube::create (Vec3D (1.000,0.200,-0.700), Vec3D (1.100,0.400,2.000));

    Primitive *Cylinder = Cylinder::create(0.300,0.200);

    Primitive *GabCubus   = Cube::create (Vec3D (-0.800,-0.400,-0.100), Vec3D (-0.700,-0.200,0.500));
    Primitive *GabCubus2   = Cube::create (Vec3D (-0.800,0.200,-0.100), Vec3D (-0.700,0.400,0.500));
    Primitive *GabCubus3   = Cube::create (Vec3D (-0.700,-0.400,-0.100), Vec3D (0.300,-0.200,0.000));
    Primitive *GabCubus4   = Cube::create (Vec3D (-0.700,0.200,-0.100), Vec3D (0.300,0.400,0.000));

//######################################
//        GeoPattern
//######################################
    GeoPattern *GPcubus = GeoPattern::create(*Cubus, *chocAttrib);
    GeoPattern *GPcubus2 = GeoPattern::create(*Cubus2, *chocAttrib);
    GeoPattern *GPrect = GeoPattern::create(*Rect, *gray50Attrib);
    GeoPattern *GPrect2 = GeoPattern::create(*Rect2, *gray50Attrib);
    GeoPattern *GPrect3 = GeoPattern::create(*Rect3, *gray50Attrib);
    GeoPattern *GPcubus3 = GeoPattern::create(*Cubus3, *gray12Attrib);
    GeoPattern *GPcubus4 = GeoPattern::create(*Cubus4, *gray12Attrib);

    Vec3D v1 = Vec3D(0.000,1.000,0.000).cross (EX);
    Vec3D v2 = EX * rotHMatrx3D (v1, Vec3D(0.000,1.000,0.000).angle (EX) - Angle (90.0));

    GeoPattern *GPcylinder = GeoPattern::create(*Cylinder, *gray12Attrib, Location(Vec3D(-0.650,-0.600,-0.700),v2,Vec3D(0.000,1.000,0.000)));
    GeoPattern *GPcylinder2 = GeoPattern::create(*Cylinder, *gray12Attrib, Location(Vec3D(0.650,-0.600,-0.700),v2,Vec3D(0.000,1.000,0.000)));
    GeoPattern *GPcylinder3 = GeoPattern::create(*Cylinder, *gray12Attrib, Location(Vec3D(-0.650,0.400,-0.700),v2,Vec3D(0.000,1.000,0.000)));
    GeoPattern *GPcylinder4 = GeoPattern::create(*Cylinder, *gray12Attrib, Location(Vec3D(0.650,0.400,-0.700),v2,Vec3D(0.000,1.000,0.000)));

    GeoPattern *GPgabcubus = GeoPattern::create(*GabCubus, *gray12Attrib);
    GeoPattern *GPgabcubus2 = GeoPattern::create(*GabCubus2, *gray12Attrib);
    GeoPattern *GPgabcubus3 = GeoPattern::create(*GabCubus3, *gray12Attrib);
    GeoPattern *GPgabcubus4 = GeoPattern::create(*GabCubus4, *gray12Attrib);

//######################################
//        Pattern
//######################################
    Pattern *Pstapler = Pattern::create ();
    Pstapler->insert (*GPcubus);
    Pstapler->insert (*GPcubus2);
    Pstapler->insert (*GPrect);
    Pstapler->insert (*GPrect2);
    Pstapler->insert (*GPrect3);
    Pstapler->insert (*GPcubus3);
    Pstapler->insert (*GPcubus4);
    Pstapler->insert (*GPcylinder);
    Pstapler->insert (*GPcylinder2);
    Pstapler->insert (*GPcylinder3);
    Pstapler->insert (*GPcylinder4);

    Pattern *Pgabel = Pattern::create ();
    Pgabel->insert (*GPgabcubus);
    Pgabel->insert (*GPgabcubus2);
    Pgabel->insert (*GPgabcubus3);
    Pgabel->insert (*GPgabcubus4);

//######################################
//        Einfuegen in GeoObjects
//        Positionierung
//######################################
    stapler->insert (*Pstapler);
    stapler->setParent (*MySpace);

    gabel->insert (*Pgabel);
    gabel->setParent (*stapler);

    stapler->move(Vec3D (0.0, 0.0, 1.0));

    gabel->move(Vec3D (1.9, 0.0, 0.0));

//######################################
//     Initialisierung der ToglView-Umgebung
//######################################

    ToglView::setup (MainInterp);
    newView();

  }

  else
  {
    //    delete Client;
    newView();
  }
}


void animateViews (ClientData)
{
  if (i <= 10)
  {
   stapler->move(Vec3D (0.5, 0.0, 0.0));
   i++;
  }
  else if (i <=15)
       {
        stapler->rotate(EZ, Angle (-9.0));
        gabel->move(Vec3D (0.0, 0.0, 0.2));
        i++;
       }
       else if (i <=20)
            {
             stapler->rotate(EZ, Angle (9.0));
             gabel->move(Vec3D (0.0, 0.0, -0.2));
             i++;
             }
             else if (i <=30)
                  {
                   stapler->move(Vec3D (-0.5, 0.0, 0.0));
                   i++;
                   }
                   else if (i <=50)
                        {
                         stapler->move(Vec3D (0.5, 0.0, 0.0));
                         stapler->rotate(EZ, Angle (9.0));
                         i++;
                         }
  if (i == 51) i = 1;

  MySpace->flushAllViews();
  timerToken = Tk_CreateTimerHandler (300, animateViews, (ClientData) NULL);
}

int Exit(){
   delete MySpace;
   return 1;
}
//===========================================================================

int MainTclCmd (ClientData /*clientData*/, Tcl_Interp *interp,
                int /*argc*/, char *argv[] ) {
  MainInterp = interp;
  fprintf(stdout, "MainTclCmd A1 >%s<\n", argv[1]);
  if ( !strcmp("Init", argv[1]) ) {
    InitModell ();
  }
  else if ( !strcmp("NewView",  argv[1]) ) {
    newView();
  }
  else if ( !strcmp("Animate",  argv[1]) ) {
    if (timerToken) {
      Tk_DeleteTimerHandler (timerToken);
      timerToken = NULL;
    }
    else {
      timerToken = Tk_CreateTimerHandler (10, animateViews, (ClientData) NULL);
    }
  }
  else if ( !strcmp("Sichern",  argv[1]) ) {
    CamPos   = Client->Camera ()->CameraPos();
    CamFocus = Client->Camera ()->Focus();
    CamUp    = Client->Camera ()->CameraUp();

    ObjViewPoint = ViewPoint(CamPos, CamFocus, CamUp);
      cout << "View: Client: Cam, Foc, Up : " << CamPos << " "
                         << CamFocus << " " << CamUp << endl;
    /*
    ofstream out ("Sichern.ini");
      out << "View: Client: Cam, Foc, Up : " << CamPos << " "
                         << CamFocus << " " << CamUp << endl;
    out.close();*/
  }
  else if ( !strcmp("ExitTest", argv[1]) ) {
    if (timerToken) {
      Tk_DeleteTimerHandler (timerToken);
      timerToken = NULL;
    }
  } else {cout << "Nicht vorhanden >" << argv[1] << "<" << endl;}
  return TCL_OK;
}
