#include <windows.h>
#include <deque.h>

#define VKEY_LEFT 37
#define VKEY_UP 38
#define VKEY_RIGHT 39
#define VKEY_DOWN 40
#define VKEY_Q 81
#define VKEY_START 69

/* NOTEPAD WEEKEND HIJACK FRAMEWORK
 * ================================
 *
 * What is this file?
 * -> It is a framework for making applications that hijack an open Notepad window for input and output.
 *    It starts by displaying a message box, then sleeping until a Notepad window is found, and then creates
 *    a keyboard hook to capture all keypresses (system-wide). It then loops until exited, hitting the main
 *    loop every 50 ms (because of a timer set at startup). For input, read keypresses from the events buffer.
 *    For output, use window_write() to write to the Notepad window.
 *
 * How do I use it?
 * -> You can take this file and edit the two TODO locations to make a game or do something else cool.
 *    It should be very easy to compile, but is most certainly Windows-only code.
 *
 * What does window_write() do?
 * -> This function sets the text of the Notepad window to the string passed in.
 *
 * What does resize_window() do?
 * -> This function resizes the notepad window. You can call it after the call to SetTimer() in order to
 *    only do it once and immediately after finding the Notepad window. It's not that important or fancy.
 *
 */

// Global variables.
HWND hwnd=0, edit;
MSG m;
HHOOK hHook;
deque<int> events;
bool quit = false;

// Prototypes.
LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam);
bool window_write(char* c);
void resize_window(HWND hWnd, int width, int height);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "Close this window, open Notepad, and enjoy!", "(c) Zach Barth, 2007", MB_ICONEXCLAMATION);

    // Find a notepad window.
    while (hwnd == 0)
    {
        hwnd = FindWindow("Notepad", NULL);
        Sleep(100);
    }

    // Find the edit control, hook, and set a timer.
    edit = FindWindowEx(hwnd, NULL, "Edit", NULL);
    hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook, hInstance, 0);
    SetTimer(NULL, 0, 50, NULL); // Creates a timer message every 50ms, making GetMessage return.

    // Main game loop.
    while (!quit)
    {
        // Process keypresses.
        GetMessage(&m, 0, 0, 0);
        while ( !events.empty() )
        {
            switch ( events[0] )
            {
                // TODO: Handle keypresses here!
                case VKEY_Q:
                    quit = true;
                    break;
            }
            events.pop_front();
        }

        // TODO: Do stuff in the infinite loop! (hit every 50 ms)
        window_write("HELLO");
    }
}

// Hook function to push WM_KEYDOWN messages to the event queue.
LRESULT CALLBACK KeyboardHook (int nCode, WPARAM wParam, LPARAM lParam )
{
	if (nCode == HC_ACTION)
	{
		if (wParam == WM_SYSKEYDOWN || wParam == WM_KEYDOWN)
		{
			events.push_back( (((PKBDLLHOOKSTRUCT)lParam)->vkCode) );
		}
	}
	return CallNextHookEx(hHook, nCode, wParam, lParam);
}

// Clear and write to the notepad window.
bool window_write(char* c)
{
    return SendMessage(edit, WM_SETTEXT, NULL, (LPARAM)c);
}

// Resize a window.
void resize_window(HWND hWnd, int width, int height)
{
    RECT r;
    GetWindowRect(hWnd, &r);
    MoveWindow(hWnd,r.left,r.top,width,height,TRUE);
}
