#include <windows.h>
#include <stdio.h>
#include <memory.h>
#include <malloc.h>

#include "fpse.h"
#include "win32def.h"

static FPSEWin32 FPSEWin32Info;

static char fps_en=0;
char *scrpath = { "snaps\\" };

LRESULT APIENTRY WndFunc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;

    switch (msg) {
    case WM_KEYDOWN:
        switch(wParam) {
            case VK_ESCAPE:
                DestroyWindow(hwnd);
                break;
            case VK_F12:
                GPU_ScreenShot(scrpath);
                break;
            case VK_F11:
                fps_en ^= 1;
                break;
/*
            case VK_F10:
                FPSE_Flags ^= VERBOSE;
                break;
            case VK_F9:
                FPSE_Flags ^= DISASMFLG;
                break;
*/
        }
        break;
    case WM_PAINT:
        GPU_Update();
        {
            PAINTSTRUCT ps;
            static int t0,t1,frame,fps;
            char szbuf[20];            

            hdc = BeginPaint(hwnd,&ps);

            if (fps_en) {
                if ((t1=GetTickCount()-t0)>1000) {
                    fps = 1000*frame/t1;
                    t0+=t1;
                    frame=0;
                }
                frame++;

                wsprintf(szbuf,"fps:%d",fps);
                TextOut(hdc,0,0,szbuf,strlen(szbuf));
            }
            EndPaint(hwnd,&ps);
        }
        break;
	case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd,msg,wParam,lParam);
    }
    return 0;
}

int win_init(void)
{
    static char szAppName[] = "FPSE Display";
    static char szClassName[] = "FPSE";
    WNDCLASS wndclass;
    HINSTANCE hInst = 0;

    memset(&FPSEWin32Info,0,sizeof(FPSEWin32Info));
    wndclass.style = 0; //CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndFunc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInst;
    wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
    wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szClassName;

    RegisterClass(&wndclass);

    FPSEWin32Info.HWnd = CreateWindow(
		szClassName, //classname
		szAppName, //title
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		320,
		240,
		NULL, //parent
		NULL, //menu
		hInst,
		NULL);

    ShowWindow(FPSEWin32Info.HWnd,SW_SHOW);

// Prepare the param struct
    FPSEWin32Info.SystemRam = ram;
    FPSEWin32Info.HInstance = (HINSTANCE)GetWindowLong(FPSEWin32Info.HWnd,GWL_HINSTANCE);
    FPSEWin32Info.ReadCfg  = INI_Read;
    FPSEWin32Info.WriteCfg = INI_Write;
    FPSEWin32Info.FlushRec = CompileFlush;

// Init Plug-in
    if (CD_Open((UINT32*)&FPSEWin32Info)   != FPSE_OK) {
        printf("CD-Rom initialization failed.\n");
        return FPSE_ERR;
    }
    if (SPU_Open((UINT32*)&FPSEWin32Info)  != FPSE_OK) {
        printf("SPU initialization failed.\n");
        return FPSE_ERR;
    }
    if (GPU_Open((UINT32*)&FPSEWin32Info)  != FPSE_OK) {
        printf("GPU initialization failed.\n");
        return FPSE_ERR;
    }
    if (JOY0_Open((UINT32*)&FPSEWin32Info) != FPSE_OK) {
        printf("Gameport 0 initialization failed.\n");
        return FPSE_ERR;
    }
    if (JOY1_Open((UINT32*)&FPSEWin32Info) != FPSE_OK) {
        printf("Gameport 1 initialization failed.\n");
        return FPSE_ERR;
    }

    UpdateWindow(FPSEWin32Info.HWnd);

    return FPSE_OK;
}

void win_update(void)
{
    MSG msg;

    if (FPSEWin32Info.Flags & GPU_USE_DIB_UPDATE)
        InvalidateRect(FPSEWin32Info.HWnd,NULL,FALSE);
    else
        GPU_Update();

    while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
        if (msg.message==WM_QUIT) exit(msg.wParam);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

void win_term(void)
{
    GPU_Close();
    SPU_Close();
    JOY0_Close();
    JOY1_Close();
    CD_Close();
}
