#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <FTGL/ftgl.h>

#define PITCH   8.0
#define WSCREEN 1920.0
#define HSCREEN 1080.0


int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_VIDEO);
    SDL_WM_SetCaption("Suite de Syracuse",NULL);
    SDL_SetVideoMode(WSCREEN, HSCREEN, 32, SDL_OPENGL|SDL_FULLSCREEN);
    SDL_EnableKeyRepeat(75, 75);
    glTranslated(-1,-1,0);

    //Chargement du texte
    FTGLPixmapFont font("arial.ttf");
    font.FaceSize(20);

    bool continuer = true, compressed = false;
    char buff[100];
    int n = 63, pos = 0, tmp = 0, h = 0, w = 0, val = 0, xmouse = 0;
    SDL_Event event;

    while (continuer)
    {
        SDL_WaitEvent(&event);
        switch(event.type) {
            case SDL_QUIT:
                continuer = false;
                break;

            case SDL_KEYDOWN:
                    if (event.key.keysym.sym == SDLK_ESCAPE)
                        continuer = false;
                    if (event.key.keysym.sym == SDLK_UP) {
                        n++;
                        pos = 0;
                    }
                    if (event.key.keysym.sym == SDLK_DOWN) {
                        n = (n < 2)? 1 : n-1;
                        pos = 0;
                    }
                    if (event.key.keysym.sym == SDLK_c)
                        compressed = (compressed == false)? true : false;
                    if (event.key.keysym.sym == SDLK_LEFT)
                        pos = (pos<PITCH)? 0 : pos-PITCH;
                    if (event.key.keysym.sym == SDLK_RIGHT)
                        pos = (pos>=w-WSCREEN)? pos : pos+PITCH ;
                    break;

            case SDL_MOUSEMOTION:
                    xmouse = event.motion.x;
                    break;
        }

        tmp = n;
        h = n;
        for(w=PITCH; tmp>1; w+=PITCH) {
                tmp = (tmp%2==0)? tmp/2.0 : (3*tmp)+1;
                h = (tmp>h)? tmp : h;
        }
        w = (w+5*PITCH<WSCREEN)? WSCREEN : w+5*PITCH;
        if(compressed && h != n)    h /= 2.0;
        h = (h==1)? 2 : h;
        h /= 2.0;

        glClear(GL_COLOR_BUFFER_BIT);
        //Texte
        if(compressed)
                sprintf(buff, "Suite de Syracuse compressee du nombre %d", n);
        else    sprintf(buff, "Suite de Syracuse du nombre %d", n);
            glPixelTransferf(GL_RED_BIAS, -0.0f);
            glPixelTransferf(GL_GREEN_BIAS, -0.0f);
            glPixelTransferf(GL_BLUE_BIAS, -0.0f);
            font.Render(buff, strlen(buff), FTPoint(0,HSCREEN-20,0));
            glPixelTransferf(GL_RED_BIAS, -0.6f);
            glPixelTransferf(GL_GREEN_BIAS, -0.6f);
            glPixelTransferf(GL_BLUE_BIAS, -0.6f);
        sprintf(buff, "1");
        if( (HSCREEN*5.0/(double)h) - (HSCREEN/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN/(double)h)+5));
        sprintf(buff, "10");
        if( (HSCREEN*50.0/(double)h) - (HSCREEN*5.0/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*5.0/(double)h)+5));
        sprintf(buff, "100");
        if( (HSCREEN*500.0/(double)h) - (HSCREEN*50.0/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*50.0/(double)h)+5));
        sprintf(buff, "1000");
        if( (HSCREEN*5000.0/(double)h) - (HSCREEN*500.0/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*500.0/(double)h)+5));
        sprintf(buff, "10000");
        if( (HSCREEN*50000.0/(double)h) - (HSCREEN*5000.0/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*5000.0/(double)h)+5));
        sprintf(buff, "100000");
        if( (HSCREEN*500000.0/(double)h) - (HSCREEN*50000.0/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*50000.0/(double)h)+5));
        sprintf(buff, "1000000");
        if( (HSCREEN*5000000.0/(double)h) - (HSCREEN*500000.0/(double)h) > 25.0)
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*500000.0/(double)h)+5));
        sprintf(buff, "10000000");
            font.Render(buff, strlen(buff), FTPoint(WSCREEN-font.Advance(buff), (HSCREEN*5000000.0/(double)h)+5));

        //Graduation log10
        glBegin(GL_LINES);
            glColor3ub(51,51,51);
            glVertex2d(0.0,1.0/(double)h);
            glVertex2d(2.0,1.0/(double)h);
            glVertex2d(0.0,10.0/(double)h);
            glVertex2d(2.0,10.0/(double)h);
            glVertex2d(0.0,100.0/(double)h);
            glVertex2d(2.0,100.0/(double)h);
            glVertex2d(0.0,1000.0/(double)h);
            glVertex2d(2.0,1000.0/(double)h);
            glVertex2d(0.0,10000.0/(double)h);
            glVertex2d(2.0,10000.0/(double)h);
            glVertex2d(0.0,100000.0/(double)h);
            glVertex2d(2.0,100000.0/(double)h);
        glEnd();
        glBegin(GL_LINE_STRIP);
            tmp = n;
            glColor3ub(0,200,255);
            //glVertex2d(2*(-pos)/WSCREEN, (double)tmp/(double)h);
            for(double i=-pos; i<=pos+WSCREEN; i+=PITCH) {
                glVertex2d(2*i/WSCREEN, (double)tmp/(double)h);
                if(tmp>1) {
                    if(compressed)
                        tmp = (tmp%2==0)? tmp/2 : ((3*tmp)+1)/2.0;
                    else    tmp = (tmp%2==0)? tmp/2 : (3*tmp)+1;
                }
                else glColor3ub(0,255,0);
            }
        glEnd();

        tmp = n;
        val = (xmouse-pos+PITCH/2.0)/PITCH;
        for(double i=-pos; i<=pos+val*PITCH; i+=PITCH) {
            if(i==pos+val*PITCH) {
                    glPointSize(5);
                glBegin(GL_POINTS);
                    glColor3ub(255,0,0);
                    glVertex2d(2*i/WSCREEN, (double)tmp/(double)h);
                glEnd();
                glBegin(GL_LINES);
                    glColor3ub(100,0,0);
                    glVertex2d(0.0,(double)tmp/(double)h);
                    glVertex2d(2.0,(double)tmp/(double)h);
                    glVertex2d(2*i/WSCREEN,0.0);
                    glVertex2d(2*i/WSCREEN,2.0);
                glEnd();
                sprintf(buff, "%d ; i:%d", tmp, (int)(i/PITCH));
                if((HSCREEN*0.5*(double)tmp/(double)h)+25 <= HSCREEN) {
                    if(i+10 < WSCREEN-font.Advance(buff))
                            font.Render(buff, strlen(buff), FTPoint(i+5, (HSCREEN*0.5*(double)tmp/(double)h)+5));
                    else    font.Render(buff, strlen(buff), FTPoint(i-font.Advance(buff)-5, (HSCREEN*0.5*(double)tmp/(double)h)+5));
                }
                else {
                    if(i+10 < WSCREEN-font.Advance(buff))
                            font.Render(buff, strlen(buff), FTPoint(i+5, HSCREEN-20));
                    else    font.Render(buff, strlen(buff), FTPoint(i-font.Advance(buff)-5, HSCREEN-20));
                }
            }
            if(tmp>1) {
                if(compressed)
                        tmp = (tmp%2==0)? tmp/2 : ((3*tmp)+1)/2.0;
                else    tmp = (tmp%2==0)? tmp/2 : (3*tmp)+1;
            }
        }

        glFlush();
        SDL_GL_SwapBuffers();
    }

    SDL_Quit();

    return 0;
}

