#include "stdafx.h"
#include <wchar.h>//by Kobarin
#include <process.h>
#include "Ggs4Controller.h" //by Kobarin
#include "PowerControlWindow.h"

using namespace std;

namespace GuruGuruSmf { namespace Core {
	
	// コールバック関数置き場
	void (*callBackSuspend)() = 0;
    /* del by Kobarin
    void thread_entry(void* p_userdata)
    {
        PowerControlWindow* p_win = (PowerControlWindow*)p_userdata;
        p_win->createWindow();
        p_win->MessageLoop();
    }
    */
    //by Kobarin
    unsigned __stdcall thread_entry(void* p_userdata)
    {
        PowerControlWindow* p_win = (PowerControlWindow*)p_userdata;
        p_win->createWindow();
        p_win->MessageLoop();
        return 0;
    }
    //ここまで
    
    LRESULT WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

	// コンストラクタ
	PowerControlWindow::PowerControlWindow(GgsController *ggs_ctrl)
	{
        //_beginthread(thread_entry, 0, this);//del by Kobarin
        //by Kobarin
        _hWnd = NULL;
        _ggs_ctrl = ggs_ctrl;
        _class_name[0] = 0;
        _hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        _hThread = (HANDLE)_beginthreadex(NULL, 0, thread_entry, this, 0, NULL);
        //ここまで
	}
	
	// デストラクタ
	PowerControlWindow::~PowerControlWindow()
	{
        WaitForSingleObject(_hEvent, INFINITE);//by Kobarin(ウィンドウが作成し終わるまで待つ)
        SendMessage(_hWnd, WM_CLOSE, NULL, NULL);
        //by Kobarin
        WaitForSingleObject(_hThread, INFINITE);
        CloseHandle(_hEvent);
        CloseHandle(_hThread);
        //ここまで
	}

	const wchar_t *g_AppName  = L"GuruGuruSMFHidden";
    void PowerControlWindow::createWindow()
    {
        //マルチプルインスタンス対応の為、クラス名をインスタンスごとに異なるものにする
        _snwprintf_s(_class_name, _TRUNCATE, L"%s-%08x-%08x", g_AppName, GetCurrentThreadId(), GetTickCount());
        WNDCLASSEX wcex;
        wcex.cbSize         = sizeof(WNDCLASSEX);
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = &WindowProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = GetModuleHandle(NULL);
        wcex.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = NULL;
        //wcex.lpszClassName  = g_AppName;
        wcex.lpszClassName  = _class_name;//by Kobarin

        wcex.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

        RegisterClassEx(&wcex);

        _hWnd = CreateWindow(
			//g_AppName, g_AppName, WS_OVERLAPPEDWINDOW,
            _class_name, g_AppName, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
			NULL, NULL, GetModuleHandle(NULL), NULL
		);
        //
        SetWindowLongPtr(_hWnd, GWLP_USERDATA, (LONG_PTR)_ggs_ctrl);//by Kobarin
        //ShowWindow(_hWnd, SW_SHOWDEFAULT);
        UpdateWindow(_hWnd);
        SetEvent(_hEvent);//by Kobarin(ウィンドウの作成完了)
    }
    /*
	void PowerControlWindow::SetCallBackSuspend(void (*func)())
	{//廃止 by Kobarin 代わりに ctrl->Suspend() を呼ぶ

		callBackSuspend = func;
	}
    */
    void PowerControlWindow::MessageLoop()
    {
        MSG msg = {0};

        while (GetMessage(&msg, NULL, 0, 0))
        {
            if(msg.message == WM_QUIT)
            {
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        UnregisterClass(_class_name, GetModuleHandle(NULL));//by Kobarin
    }
	
    LRESULT WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        case WM_POWERBROADCAST:
			switch(wParam)
			{
			case PBT_APMSUSPEND:{
				//if (callBackSuspend)	callBackSuspend();
                GgsController* ctrl = (GgsController*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
                if(ctrl)ctrl->Suspend();
                break;
            }
			case PBT_APMRESUMESUSPEND:
				break;
			}
			break;
        
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}}
