#include <stdlib.h>
#include <stdio.h>

#include "math.h"

#include "menu.h"
#include "level.h"

#include "tinerxml.h"

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

#include "glness.h"

#include "SDL/SDL.h"

#include "iostream"
using namespace std;

class controlsT
{
public:
    int up,dn,lt,rt,shoot,jump,change;
    controlsT(){
        up = dn = lt = rt = shoot = jump = change = 0;
    };
    ~controlsT();
protected:

private:

};


int done;//MOST MAIN LOOP!!

bool ingame = 0;

//my vars
//float number = 0;
Uint8*  keys = NULL;

level mylvl;
menu mymnu;
int mouse_x = 320, mouse_y = 240;
float mx =0, my =0;

int w = 640;
int h = 480;
int f = 0;

void InitGL(int Width, int Height)         // We call this right after our OpenGL window is created.
{
    glEnable(GL_TEXTURE_2D);
    glViewport(0, 0, Width, Height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();    // Reset The Projection Matrix

    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window

    glMatrixMode(GL_MODELVIEW);

    glClearColor(0.1f, 0.0f, 0.0f, 0.0f);     // Black Background
    glClearDepth(1.0f);       // Depth Buffer Setup
    glDepthFunc(GL_LEQUAL);       // Type Of Depth Testing
    glEnable(GL_DEPTH_TEST);      // Enable Depth Testing
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   // Enable Alpha Blending (disable alpha testing)
    glEnable(GL_BLEND);       // Enable Blending       (disable alpha testing)
    glAlphaFunc(GL_GREATER,0.1f);      // Set Alpha Testing     (disable blending)
    glEnable(GL_ALPHA_TEST);      // Enable Alpha Testing  (disable blending)
    glEnable(GL_TEXTURE_2D);      // Enable Texture Mapping
    glEnable(GL_CULL_FACE);       // Remove Back Face
    glShadeModel(GL_SMOOTH);         // Select Smooth Shading
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // Set Perspective Calculations To Most Accurate

}

int testtex = 0;
void InitGame() {
    keys = SDL_GetKeyState(NULL);
    mylvl.init(keys);
    mylvl.update(mx,my);
    mymnu.init();

    //SDL_WarpMouse(320, 240);

}

#define TICK_INTERVAL    30

Uint32 TimeLeft(void) {
    static Uint32 next_time = 0;
    Uint32 now = SDL_GetTicks();
    if ( next_time <= now ) {
        next_time = now+TICK_INTERVAL;
        return(0);//this hsouldnt really happen much...
    }
    Uint32 retval = next_time-now;
    //next_time = now+TICK_INTERVAL;
    return(retval);
}

void DoUpdate() {
    //SDL_Delay(TimeLeft());
    //SDL_Delay(15);
    //keys = SDL_GetKeyState(NULL);

    /*SDL_GetMouseState(&mouse_x, &mouse_y);
    mx=(mouse_x-w/2)*0.7;
    my=(-mouse_y+h/2)*0.7;*/

    if(keys[SDLK_ESCAPE]) {
        ingame = !ingame;
        keys[SDLK_ESCAPE] = 0;
        keys[SDLK_UP] = 0;
        keys[SDLK_DOWN] = 0;
    }
    if(!ingame) {
        if(keys[SDLK_RETURN]) {
            keys[SDLK_RETURN] = 0;
            if (mymnu.cstring() == "newgame") {
                mylvl.close();
                mylvl.init(keys);
                mylvl.update(mx,my);
                ingame = 1;
            }
            if (mymnu.cstring() == "exit") {
                done = 1;
            }
        }
        if(keys[SDLK_UP]) {
            mymnu.prevmenuitem();
            keys[SDLK_UP] = 0;
        }
        if(keys[SDLK_DOWN]) {
            mymnu.nextmenuitem();
            keys[SDLK_DOWN] = 0;
        }
    }

    if(ingame) {
        mylvl.update(mx,my);

        if(++mylvl.winner >= 0) {
            mymnu.clogo = mylvl.winner;
            ingame=!ingame;
            keys[SDLK_UP] = 0;
        }
    }
}
void DrawGLScene() {
    //GL_COLOR_BUFFER_BIT |
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear The Screen And The Depth Buffer
    glLoadIdentity();    // Reset The View
    float drawscale = 0.05f;
    glScalef(drawscale, drawscale, drawscale);

    mylvl.draw();
    if(!ingame)
        mymnu.draw();

    // swap buffers to display, since we're double buffered.
    SDL_GL_SwapBuffers();
}

void handleMousePress( Uint8 button ,bool press) {
    if(button == 2)
        mylvl.mmd(press,mx,my);
}


void initvid(int width,int height,int fs) {
    Uint32 flags = SDL_OPENGL | SDL_HWSURFACE;// | SDL_DOUBLEBUF;
    //Uint32 flags = SDL_HWSURFACE|SDL_OPENGLBLIT;
    if(fs)
        flags |= SDL_FULLSCREEN;
    if ( SDL_SetVideoMode(width, height, 32, flags) == NULL ) {
        fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError());
        SDL_Quit();
        //exit(2);
    }
    InitGL(width, height);
}

int main(int argc, char **argv) {
    /*keys = new Uint8[3200];
    for(int i=0;i<3200;i++)
        keys[i] = 0;*/
    if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
        fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
    }

    xmlfile settings;
    TiXmlElement *xGame = settings.getxmlfirstelement("settings.xml");
    TiXmlElement *xGraphics = settings.getelement(xGame, "graphics");
    w = (int)atoi(xGraphics->Attribute("w"));
    h = (int)atoi(xGraphics->Attribute("h"));
    f = (int)atoi(xGraphics->Attribute("fullscreen"));
    settings.endxml();


    initvid(w,h,f);

    SDL_WM_SetCaption("FreeHover", NULL);


    InitGame();

    done = 0;
    while ( ! done ) {
        DoUpdate();
        DrawGLScene();

        //This could go in a separate function
        SDL_Event event;
        while ( SDL_PollEvent(&event) ) {
            switch(event.type) {
            case SDL_QUIT:
                done = 1;
                break;
            case SDL_KEYDOWN:
                //cout << event.key.keysym.sym << " pressed" << endl;
                keys[event.key.keysym.sym] = 1;
                if ( event.key.keysym.sym == SDLK_F5 ) {
                    mylvl.save("testsave.lvl");
                }
                if ( event.key.keysym.sym == SDLK_F7 ) {
                    mylvl.load("testsave.lvl");
                }
                if ( event.key.keysym.sym == SDLK_F4 ) {
                    mylvl.close();
                    mylvl.init(keys);
                }

                if ( event.key.keysym.sym == SDLK_F1 ) {
                    //f=!f;
                    //initvid(w,h,f);
                }
                break;
            case SDL_KEYUP:
                //cout << event.key.keysym.sym << " released" << endl;
                keys[event.key.keysym.sym] = 0;
                break;
            case SDL_MOUSEBUTTONDOWN:
                handleMousePress( event.button.button ,1);
                break;
            case SDL_MOUSEBUTTONUP:
                handleMousePress( event.button.button ,0);
                break;
            }
        }

    }
    mylvl.close();
    SDL_Quit();
    return 1;
}
