#include "widgetsimu.h"
#include "sailboat.h"
#include "qdebug.h"


extern double dt;



WidgetSimu::WidgetSimu(QWidget *parent) :
    QGLWidget(parent)
{   Zoom=0.2;    zRotCam=1000;   xRotCam=-1100;
    xCam=0;yCam=0;zCam=0;
}


void WidgetSimu::Start()
{   if (dt==0)  dt=0.05; else dt=0;
}

void WidgetSimu::Clock()
{   updateGL();
    if (dt==0)return;
    sailboat1.Clock();
    DrawSailboat();
}


/************************/
/*   dessin de la scène */
/************************/

void WidgetSimu::initializeGL()
{
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_NORMALIZE);
    glClearColor(0.9,0.9,1,1);  //arrière plan
            static const GLfloat lightPos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
            glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
            glEnable(GL_LIGHTING);
            xRotCam=-90; yRotCam=0;  zRotCam=20;
            glEnable(GL_COLOR_MATERIAL);
}

void WidgetSimu::paintGL()
{
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glTranslated(0.0,-2.0, -40.0);
        glRotated(xRotCam, 1.0, 0.0, 0.0);
        glRotated(yRotCam, 0.0, 1.0, 0.0);
        glRotated(zRotCam, 0.0, 0.0, 1.0);
        glScalef( Zoom, Zoom, Zoom);

        glTranslatef(xCam,yCam,zCam);


        DrawMer();
        DrawCable();
        DrawCircle();
        DrawBouees();
        DrawArrow(sailboat1.x+3,sailboat1.y+12,10,sailboat1.psi,2,1.0,0,0);  // Wind arrow
        DrawArrow(sailboat1.x+1,sailboat1.y+1,2,sailboat1.thetabar,1,0,1,0);  //
        DrawArrow(sailboat1.loadx,sailboat1.loady,0.1,sailboat1.alphabar,20.0,1.0,0.0,0.0);
        DrawArrow(sailboat1.loadx,sailboat1.loady,0.5,sailboat1.alphastar,20.0,1.0,0.0,0.0);
        DrawSailboat();
}



void WidgetSimu::resizeGL(int width, int height)
{
    int side = qMin(width, height);
    glViewport((width - side) / 2, (height - side) / 2, side, side);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, +1.0, -1.0, 1.0, 5.0, 60.0);
    glMatrixMode(GL_MODELVIEW);
}

void WidgetSimu::mousePressEvent(QMouseEvent *event)
{   lastMousePos = event->pos();
    //sailboat1.x = 0.0;  sailboat1.y = 0.0;
}

void WidgetSimu::mouseMoveEvent(QMouseEvent *event)
{   int dx = event->x() - lastMousePos.x();
    int dy = event->y() - lastMousePos.y();
    if (event->buttons() & Qt::LeftButton)
    {   xRotCam=xRotCam + dy;
        yRotCam=yRotCam + dx;
    }
    lastMousePos = event->pos();
}

void WidgetSimu::enterEvent(QEvent *event)    // interruption clavier
{       setFocus();
        grabKeyboard();
}

void WidgetSimu::keyPressEvent(QKeyEvent *event)
{   switch (event->key())
    {
       case Qt::Key_Plus:  Zoom=Zoom*1.1;   break;
       case Qt::Key_Minus: Zoom=Zoom/1.1;  break;
       case Qt::Key_W:     xCam+=1;  break;
       case Qt::Key_X:     xCam-=1;  break;
       case Qt::Key_L:     yCam+=1;  break;
       case Qt::Key_P:     yCam-=1;  break;
    }
}

void WidgetSimu::DrawMer()
{       glBegin(GL_POLYGON);
           glColor3f(0.5,0.5,1);
           glVertex3f(-100000,-100000,0);
           glVertex3f(100000,-100000,0);
           glVertex3f(100000,100000,0);
           glVertex3f(-100000,100000,0);
        glEnd();
}

void WidgetSimu::DrawBouees()
{   glPushMatrix();
    glColor3f(1, 0.0, 0.0);
    GLUquadricObj* q=gluNewQuadric();
    gluQuadricDrawStyle(q,GLU_FILL);
    gluSphere(q,1.0,10,10);
    for (int k=1;k<5;k++)
    {  glColor3f(0.0, 1.0, 0.0);
       gluSphere(q,1.0,5,5);
       glTranslatef(10,0, 0);
    }
    glPopMatrix();
    glPushMatrix();
        glTranslatef(sailboat1.loadx,sailboat1.loady, 1);
        glColor3f(0, 0.0, 1.0);
        gluSphere(q,2.0,10,10);
    glPopMatrix();

    for (int i=0;i<sailboat1.trajLoadx.size();i++)
    {
         glPushMatrix();
         glTranslatef(sailboat1.trajLoadx[i],sailboat1.trajLoady[i], 1);
         glColor3f(1.0, 0.0, 1.0);
         gluSphere(q,1.0,3,3);
         glPopMatrix();
    }
}

void WidgetSimu::DrawCircle()
{   glPushMatrix();
    glTranslated(sailboat1.loadx,sailboat1.loady,0);
    glBegin(GL_LINE_LOOP);
            glColor3f(0.0,1.0,0.0);
            for (double t=0;t<2*M_PI;t=t+0.1)
              glVertex3f(sailboat1.L0*cos(t),sailboat1.L0*sin(t),0.5);
    glEnd();
    glBegin(GL_POLYGON);
            glColor3f(1.0,0.0,0.0);
            for (double t=M_PI+sailboat1.psi-sailboat1.zeta;t<M_PI+sailboat1.psi+sailboat1.zeta;t=t+0.1)
                glVertex3f(sailboat1.L0*cos(t),sailboat1.L0*sin(t),0.8);
    glEnd();
    glBegin(GL_POLYGON);
            glColor3f(0.0,0.0,1.0);
            for (double t=sailboat1.psi-sailboat1.zeta;t<sailboat1.psi+sailboat1.zeta;t=t+0.1)
                glVertex3f(sailboat1.L0*cos(t),sailboat1.L0*sin(t),0.8);
    glEnd();
    glPopMatrix();


    glPushMatrix();
    glBegin(GL_LINE_LOOP);
    glColor3f(1.0,1.0,0.0);
    for (double t=0;t<2*M_PI;t=t+0.1)
        glVertex3f(sailboat1.Radiusfield*cos(t),sailboat1.Radiusfield*sin(t),0.5);
    glEnd();
    glPopMatrix();

}

void WidgetSimu::DrawCable()
{       glBegin(GL_LINES);
                glColor3f(1.0,1.0,0.0);
                for (double t=0.0;t<1;t=t+0.01)
                { double err=hypot(sailboat1.x-sailboat1.loadx,sailboat1.y-sailboat1.loady)-sailboat1.L0; //erreur de tension de cable
                  double px=2*t*(1-t)*err*cos(sailboat1.theta);  // perturbation pour la courbure du cable
                  double py=2*t*(1-t)*err*sin(sailboat1.theta);
                  glVertex3f(t*sailboat1.x+(1-t)*(sailboat1.loadx)+px ,t*sailboat1.y+(1-t)*(sailboat1.loady)+py,0.5);
                }
        glEnd();
}


void WidgetSimu::DrawArrow(double x,double y, double z, double angle, double L, double rouge, double vert, double bleu)
{   glPushMatrix();
    glTranslated(x,y,z);
    glRotatef(angle*180.0/M_PI,0.0,0.0,1.0);
    glBegin(GL_LINE_LOOP);  //Fleche
            glColor3f(rouge,vert,bleu);
            glVertex3f(0,-0.1,0);            glVertex3f(L,-0.1,0);
            glVertex3f(L,-0.3,0);            glVertex3f(L+0.3,0,0);
            glVertex3f(L,0.3,0);             glVertex3f(L,0.1,0);
            glVertex3f(0,0.1,0);
    glEnd();
    glPopMatrix();
}


void WidgetSimu::DrawSailboat()

{

        glTranslated(sailboat1.x,sailboat1.y,0.0);
        glRotatef(sailboat1.theta*180.0/M_PI,0.0,0.0,1.0);
        glPushMatrix();
        glRotatef(sailboat1.phi*180.0f/M_PI,1,0,0);

        // ***************************************
        //       COQUE
        // ***************************************

                                            {   glBegin(GL_QUADS);   //plancher
                                                   glVertex3f(-1,-1.5,0.1);        glVertex3f(3,-1.5, 0.1);
                                                   glVertex3f(3,1.5,0.1);          glVertex3f(-1,1.5,0.1);
                                                   glVertex3f(4.5,-0.75, 0.1);     glVertex3f(5.06,-0.375, 0.1);
                                                   glVertex3f(5.25,0, 0.1);        glVertex3f(5.06,0.375, 0.1);
                                                   glVertex3f(4.5,0.75, 0.1);
                                                glEnd();
                                                // ---------------------------- dessus avant ----------------------------------------------------------------------
                                                glTranslatef(0.01,0,0.01);
                                                glBegin(GL_POLYGON);  //dessus avant
                                                   glColor3f(0.8,0.2,0.2);            glVertex3f(3,-2,1.0);
                                                   glVertex3f(3.1,-1.9,1.01);         glVertex3f(3.75,-1.6, 1.01);
                                                   glVertex3f(5.0,-1,1.01);           glVertex3f(5.75,-0.5,1.01);
                                                   glVertex3f(6.0, 0, 1.01);          glVertex3f(5.75,0.5,1.01);
                                                   glVertex3f(5.0,1,1.01);            glVertex3f(3.75,1.6,1.01);
                                                   glVertex3f(3.1,1.9,1.01);          glVertex3f(3,2,1.01);
                                                glEnd();

                                                //--------------------------- faces latérales ---------------------------------------------------------------------
                                                glTranslatef(-0.01,0,0);
                                                glBegin(GL_POLYGON); //faces latérales droite
                                                    glColor3f(0,1,0);
                                                    glVertex3f(-1,-1.5,0);       glVertex3f(-1, -1.9, 0.5);
                                                    glVertex3f(-1,-2,1.0);       glVertex3f(3,-2,1.0);
                                                    glVertex3f(3, -1.9, 0.5);    glVertex3f(3,-1.5,0);
                                                    glVertex3f(-1,-1.5,0);
                                                glEnd();
                                                glBegin(GL_POLYGON); //faces latérales gauche
                                                    glColor3f(0,0,1);
                                                    glVertex3f(-1,1.5,0);        glVertex3f(-1, 1.9, 0.5);
                                                    glVertex3f(-1,2,1.0);        glVertex3f(3,2,1.0);
                                                    glVertex3f(3, 1.9, 0.5);     glVertex3f(3,1.5,0);
                                                    glVertex3f(-1,1.5,0);
                                                glEnd();
                                                //--------------------------- banc ----------------------------------------------------------------------------------
                                                glTranslatef(0,-0.01,0);
                                                glBegin(GL_QUADS);              //banc
                                                    glColor3f(1,1,1);
                                                    glVertex3f(-1,2,1.0);         glVertex3f(-1, 1.3, 1.0);
                                                    glVertex3f(3, 1.3, 1.0);      glVertex3f(3,2,1.0);
                                                    glVertex3f(-1, 1.3, 1.0);     glVertex3f(-1, 1.1, 4*1.0/5);
                                                    glVertex3f(3, 1.1, 4*1.0/5);  glVertex3f(3, 1.3, 1.0);
                                                    glVertex3f(-1, 1.1, 4*1.0/5); glVertex3f(-1, 0.9, 3*1.0/5);
                                                    glVertex3f(3, 0.9, 3*1.0/5);  glVertex3f(3, 1.1, 4*1.0/5);
                                                    glVertex3f(-1, 0.9, 3*1.0/5); glVertex3f(-1,0.8,0);
                                                    glVertex3f(3,0.8,0);          glVertex3f(3, 0.9, 3*1.0/5);
                                                glEnd();
                                                glTranslatef(0,0.01,0);

                                                // -------------------------------- autre banc ----------------------------------------------------------------
                                                glBegin(GL_QUADS);              //banc
                                                    glColor3f(1,1,1);
                                                    glVertex3f(-1,-2,1.0);        glVertex3f(-1, -1.3, 1.0);
                                                    glVertex3f(3, -1.3, 1.0);     glVertex3f(3,-2,1.0);
                                                    glVertex3f(-1, -1.3, 1.0);    glVertex3f(-1, -1.1, 4*1.0/5);
                                                    glVertex3f(3, -1.1, 4*1.0/5); glVertex3f(3, -1.3, 1.0);
                                                    glVertex3f(-1, -1.1, 4*1.0/5);glVertex3f(-1, -0.9, 3*1.0/5);
                                                    glVertex3f(3, -0.9, 3*1.0/5); glVertex3f(3, -1.1, 4*1.0/5);
                                                    glVertex3f(-1, -0.9, 3*1.0/5);glVertex3f(-1,-0.8,0);
                                                    glVertex3f(3,-0.8,0);         glVertex3f(3, -0.9, 3*1.0/5);
                                                glEnd();
                                                glTranslatef(0,-0.01,0);
                                                // ---------------------- face avant mat --------------------------------
                                                glBegin(GL_POLYGON); //face "avant mat"
                                                    glColor3f(0,0,1);
                                                    glNormal3f(-1,0,0);                glVertex3f(3+0,-1.5+0.4,0);
                                                    glVertex3f(3+0, -1.9+0.4, 0.5);    glVertex3f(3+0,-2+0.4,1.0);
                                                    glVertex3f(3+0,2-0.4,1.0);         glVertex3f(3+0, 1.9-0.4, 0.5);
                                                    glVertex3f(3+0,1.5-0.4,0);         glVertex3f(3+0,-1.5+0.4,0);
                                                glEnd();
                                                // ------------------------ face arrière -----------------------------------------------
                                                glTranslatef(-0.01,0,0);
                                                glBegin(GL_POLYGON); //face arrière
                                                    glColor3f(0.5,1,0);              glNormal3f(-1,0,0);
                                                    glVertex3f(-1,-1.5,0);           glVertex3f(-1, -1.9, 0.5);
                                                    glVertex3f(-1,-2,1.0);           glVertex3f(-1,2,1.0);
                                                    glVertex3f(-1, 1.9, 0.5);        glVertex3f(-1,1.5,0);
                                                    glVertex3f(-1,-1.5,0);
                                                glEnd();
                                                glTranslatef(0.01,-0.01,0);
                                                // ----------------------------- face avant ------------------------------------------
                                                glBegin(GL_POLYGON);
                                                   glVertex3f(3,-2,1.0);           glVertex3f(3.1,-1.7,1.0);
                                                   glVertex3f(3.75,-1.5, 1.0);     glVertex3f(5.0,-1,1.0);
                                                   glVertex3f(5.75,-0.5,1.0);      glVertex3f(6.0, 0, 1.0);
                                                   glVertex3f(5.25,0, 0);          glVertex3f(5.06,-0.375, 0);
                                                   glVertex3f(4.5,-0.75, 0);       glVertex3f(3,-1.5,0);
                                                   glVertex3f(3, -1.9, 0.5);       glVertex3f(3,-2,1.0);
                                                   glVertex3f(3,2,1.0);            glVertex3f(3.1,1.7,1.0);
                                                   glVertex3f(3.75,1.5, 1.0);      glVertex3f(5.0,1,1.0);
                                                   glVertex3f(5.75,0.5,1.0);       glVertex3f(6.0, 0, 1.0);
                                                   glVertex3f(5.25,0, 0);          glVertex3f(5.06,0.375, 0);
                                                   glVertex3f(4.5,0.75, 0);        glVertex3f(3,1.5,0);
                                                   glVertex3f(3, 1.9, 0.5);        glVertex3f(3,2,1.0);
                                                glEnd();
                                            }



        glPopMatrix();
        glPushMatrix();
             glTranslatef(-1,0,0);
             glRotatef(sailboat1.deltag*180.0/M_PI,0,0,1);

             // ***************************************
             //       RUDDER
             // ***************************************
             {   glColor3f(0,0,1);
                 glBegin(GL_POLYGON);
                 glVertex3f(0,-0.05,1);       glVertex3f(0,-0.05,0);      glVertex3f(-0.6,-0.05,0);
                 glVertex3f(-0.3,-0.05,1);    glVertex3f(0,-0.05,1);      glVertex3f(0,0.05,1);
                 glVertex3f(0,0.05,0);        glVertex3f(-0.6,0.05,0);    glVertex3f(-0.3,0.05,1);
                 glVertex3f(0,0.05,1);
                 glVertex3f(0,-0.05,1);       glVertex3f(0,0.05,1);       glVertex3f(0,-0.05,0);
                 glVertex3f(0,0.05,0);        glVertex3f(-0.6,-0.05,0);   glVertex3f(-0.6,0.05,0);
                 glVertex3f(-0.3,-0.05,1);    glVertex3f(-0.3,0.05,1);    glVertex3f(0,-0.05,1);
                 glVertex3f(0,0.05,1);
                 glEnd();
                 glDisable(GL_TEXTURE_2D);
                 glTranslatef(-0.6,0,1);
                 glRotatef(90,0,1,0);
                 GLUquadricObj*q1=gluNewQuadric();  //barre
                 gluQuadricOrientation(q1, GLU_OUTSIDE);
                 gluQuadricTexture(q1, GL_TRUE);
                 gluCylinder(q1,0.05,0.05,3, 10,10);
                 gluDeleteQuadric(q1);
             }

        glPopMatrix();
        glPushMatrix();
            glTranslatef(5,0,0);
            glRotatef(sailboat1.deltav*180.0/M_PI,0,0,1);

           // ***************************************
           //       SAIL
           // ***************************************

            {   glColor3f(0.9,0.9,0.9);
                GLUquadricObj*q1=gluNewQuadric();  //mât
                gluQuadricOrientation(q1, GLU_OUTSIDE);
                gluQuadricTexture(q1, GL_TRUE);
                gluCylinder(q1,0.08,0.08,14, 10,10);
                gluDeleteQuadric(q1);
                glDisable(GL_TEXTURE_2D);

                glColor3f(1,1,0);
                float a=-atan(sailboat1.fv/500);  // courbure de la voile
                glEnable(GL_TEXTURE_2D);
                glBegin(GL_TRIANGLE_FAN);
                    glVertex3f(0,0,2);     glVertex3f(0,0,12);    glVertex3f(-1,a*1.5,10);
                    glVertex3f(-2,a*2,8);  glVertex3f(-3,a*2,6);  glVertex3f(-4,a*1.5,4);  glVertex3f(-5,0,2);
                glEnd();

                glDisable(GL_BLEND);
                glDisable(GL_TEXTURE_2D);
                glTranslatef(0,0,2);
                glRotatef(-90,0,1,0);
                glEnable(GL_TEXTURE_2D);         //bome
                glBindTexture(GL_TEXTURE_2D,5);

                q1=gluNewQuadric();
                gluQuadricOrientation(q1, GLU_OUTSIDE);
                gluQuadricTexture(q1, GL_TRUE);
                gluCylinder(q1,0.1,0.1,5.5, 10,10);
                gluDeleteQuadric(q1);
                glDisable(GL_TEXTURE_2D);
            }
        glPopMatrix();
}
