#include <cstdio>
#include <ogl2d.h>
//#include <tnl.h>
//#include <tnlNetObject.h>

#include "sound.h"
#include "lumines.h"
#include "luskin.h"

#ifdef _DEBUG
#pragma comment(lib, "ogllibd.lib")
#pragma comment(lib, "eventd.lib")
#else
#pragma comment(lib, "ogllib.lib")
#pragma comment(lib, "event.lib")
#endif

using namespace ogl2d;

//extern Texture *block_tex; // in block.cpp
// define NEED_FPS will display fps 
//#define NEED_FPS

System *g_pSys = NULL;
Lumines *g_pGame = NULL;
Font *g_pfont = NULL;
Font *g_pscorefont = NULL;    
TextureResource *g_pTexres = NULL;


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_SIZE:
        g_pSys->Resize(480, 272);
        break;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        {
            PostQuitMessage(0);
            return 0;
        }
    default:
        if (g_pGame && g_pGame->msgHandle(hWnd, msg, wParam, lParam))
            return true;
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

HWND InitWindow(HINSTANCE hInstance, int width, int height)
{
    WNDCLASSEX wcex;
    HWND hWnd;
    wcex.cbSize         = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = "ogl2d.lumines";
    wcex.hIconSm        = NULL;
    
    RegisterClassEx(&wcex);
    
    hWnd = CreateWindow(
        wcex.lpszClassName, "lumines@pc, the remake",
        WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
        CW_USEDEFAULT, 0, width, height, NULL, NULL, hInstance, NULL
        );
    ShowWindow(hWnd, SW_SHOW);
    return hWnd;
}

class DataDisplayer
{
public:
    DataDisplayer()
    {
        for (int i=0;i<100;i++)
        {
            data[i] = 0.f;
        }
        last = 0;
        min = 0;
        max = 0;
        scale = 1.f;
    }
    void push(float _data)
    {
        last = (last+1)%100;
        if (_data > 100)
            _data = 100;
        data[last] = _data;
        min = max = 0;
        for (int i=1;i<100;i++)
        {
            if (data[i]>data[max])max = i;
            if (data[i]<data[min])min = i;
        }
    }
    void render()
    {
        int i;
        glDisable(GL_LINE_SMOOTH);
        glDisable(GL_BLEND);
        glLoadIdentity();
        glTranslatef(3,68,0);
        glScalef(1,2,1);
        glBegin(GL_LINES);
        glColor3f(.3f,.3f,.3f);
        for (i = 0; i < 10; i ++)
        {
            glVertex2d(0, i*10);
            glVertex2d(100, i*10);
        }
        glColor3f(0.f,1.f,.3f);
        glVertex2d(0, 100-60);
        glVertex2d(100, 100-60);
        glColor3f(1.f,1.f,.3f);
        glVertex2d(0, 100);
        glVertex2d(100, 100);
        glEnd();     
        // glTranslatef(0, 240,0);
        glColor3f(1,0,0);
        glBegin(GL_LINE_STRIP);
        for (i = (last+1)%100; i != last; i = (i+1)%100)
        {
            glVertex2d((100 + i - last)%100, min(100, max(0, 100 - data[i])));
        }
        glEnd();
        
    }
    int last;
    float data[100];
    int min, max;
    float scale;
};

void exitGameRelease()
{
    SAFEDELETE(g_pfont);
    SAFEDELETE(g_pscorefont);
    SAFEDELETE(g_pGame);
    SAFEDELETE(g_pTexres);
    EventManager::releaseInstance();
    System::ReleaseInstance(g_pSys);
    System::ShutDown();
    Sound::releaseInstance();
}
void check()
{
    MessageBox(0,"check point", "lumines", MB_OK);
}
int WINAPI WinMain(HINSTANCE hinstance, 
                   HINSTANCE hprevinstance, 
                   LPSTR lpcmdline, int ncmdshow)
{
    atexit(exitGameRelease);
    Sound* pSound = Sound::getInstance();
    if (pSound == NULL || !pSound->init())
    {
        //exitGameRelease();
        return -1;
    }
    // pSound->loadSkin("skin.ini");
    HWND hWnd = InitWindow(hinstance, 480 + 5, 272 + 24);
    g_pSys = System::GetInstance(hWnd);
    g_pSys->Create(480, 272);
    EventManager *pEventManager = EventManager::getInstance();
    DataDisplayer fpsdisp;
    g_pTexres = new TextureResource;
    if (g_pTexres == NULL)
    {
        //exitGameRelease();
        return -1;
    }
    //block_tex = g_pTexres->NewTexture("block.tga");
    MSG msg;
    
    PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
#if defined(_DEBUG) || defined(NEED_FPS)
    DWORD t, t2 = 0, frame = 0;
#endif
    int fps = 0, curfps = 0;
    extern void initbspline();
    initbspline();
    g_pfont = new Font;
    g_pfont->init(g_pSys, "Impact", IDM_BOLD);
    g_pscorefont = new Font;
    g_pscorefont->init(g_pSys, "Times New Roman", IDM_CHARACTER);

    Font *fontlist[2]={g_pfont,g_pscorefont,};
    g_pGame = new Lumines(fontlist);
//    glEnable(GL_DEPTH_TEST);

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else if (g_pSys->CheckFrameRateTime())
        {
            DWORD now = timeGetTime();
            pEventManager->tick();
            g_pGame->step();
            static DWORD lastTime = timeGetTime() - 1;
            if (now - lastTime > 10)
            {
#if defined(_DEBUG) || defined(NEED_FPS)
                frame++;
                if (frame%10 == 0)
                {
                    t = now;//timeGetTime();
                    //*
                    float tfps;
                    if (t - t2)
                    {
                        tfps = 10000.f / (t - t2);
                        fpsdisp.push(tfps);
                    }
                    t2 = t;
                    //*
                    curfps = int(tfps);
                    if (fps != curfps)
                    {
                        fps = curfps;
                        char str[64];
                        sprintf(str,"ogl2d.lumines@ %d fps",fps);
                        ::SetWindowText(hWnd, str);
                    }//*/
                }
#endif
                lastTime = now;

                g_pGame->render();
#if defined(_DEBUG) || defined(NEED_FPS)
                fpsdisp.render();
#endif
                g_pSys->Flush();
            }
        }
        else
        {
            Sleep(1);
        }
    }
    return 0;
}
