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

#include "masc_dll.h"

static char *callbacks[] = { "init_window", "init_loop", "wait_msg","doevents","msgbox", 0 };
enum cback { INIT_WIN, INIT_LOOP, WAIT_MSG,DO_EVENTS, MSG_BOX };




int conc(const char *name) {
	int i;
	for(i = 0; callbacks[i] != 0; i++) {
		if(strcmp(callbacks[i],name) == 0)
			return i;
	}

	return -1;
}
HBITMAP LoadSprite(char *str)
{
	HBITMAP hbm;
	hbm = (HBITMAP)LoadImage(NULL, str, IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
	return hbm;
}

BOOL run = TRUE;
struct BackEnd *bend = 0;
int bd_off = 0;
int win = 0, dw = 0;
HWND hwnd;
HBITMAP logo;

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) {
	switch(msg) {
		case WM_DESTROY:
			run = FALSE;
			DeleteObject(logo);
			PostQuitMessage(0);
			break;
		case WM_KEYDOWN: {
			struct symNode *node = 0;
			if(masc_getbend(0) != 0)
			node = Search(&masc_getbend(0)->g_stable.root,"msg");
			if(node) {
				node->value = (float) wParam;
				masc_call(0,"keydown");
			}
			}
			 break;
		case WM_CREATE: {
			struct symNode *lptr = Search(&masc_getbend(0)->g_stable.root,"img");
			if(lptr) {
			logo = LoadSprite(print_FixString(lptr->str_value));
			}
			else
				logo = 0;
			}
			break;
		case WM_PAINT: {
			PAINTSTRUCT ps;
			
			HDC dc = BeginPaint(hwnd,&ps);
			HDC cdc = CreateCompatibleDC(dc);
			SelectObject(cdc,logo);
			
			BitBlt(dc,0,0,640,480,cdc,0,0,SRCCOPY);
			EndPaint(hwnd,&ps);
			DeleteDC(cdc);
		}
	    break;
		default:
			return DefWindowProc(hwnd,msg,wParam,lParam);
	}
	return 0;
}

void InitWindow(const char *name, const char *cls, WNDPROC WndProc) {
	WNDCLASS wc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
	wc.hInstance = GetModuleHandle(0);
	wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL,IDC_ARROW);
	wc.lpfnWndProc = (WNDPROC) WndProc;
	wc.lpszClassName = cls;
	wc.lpszMenuName = NULL;
	wc.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&wc);

	hwnd = CreateWindow(cls,name,WS_OVERLAPPEDWINDOW,0,0,640,480,0,0,GetModuleHandle(0),0);
	ShowWindow(hwnd,SW_SHOW);
	UpdateWindow(hwnd);
}

void InitLoop() {
	MSG msg;
	while(GetMessage(&msg,0,0,0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

int __stdcall callback(const char *proc_name, struct BackEnd *bendx, struct Token *ptr_tok) {
	bend = bendx;
	switch(conc(proc_name)) {
		case INIT_WIN: {
			struct symNode *win_name = Search(&bend->g_stable.root,"name"), *win_class = Search(&bend->g_stable.root,"class");
			if(win_name && win_class) {
				InitWindow(print_FixString(win_name->str_value),print_FixString(win_class->str_value),WndProc);
			}
			}
			break;
		case INIT_LOOP: {
			InitLoop();
			}
			break;
		case MSG_BOX: {
			struct symNode *key_pressed;
			key_pressed = Search(&masc_getbend(0)->g_stable.root,"keyp");
			if(key_pressed)
			MessageBox(NULL,key_pressed->str_value,"It worked!.",MB_OK | MB_ICONINFORMATION);

		}
	    break;
		
	}
	return 1;
}


int main(int argc, char *argv[]) {

	struct BackEnd *bendx = 0;
	masc_callback(callback);
	win = masc_run("window.mas",bendx);
	bend = bendx;
	masc_stop(bend);
	masc_stop(bendx);
	return 0;
}
