#include "dp.h"
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
#include <time.h>

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#define CHAT_PACKET_ID		dppt_MAKE('C','H')
int TimerID;
int blob=0;
dp_session_t	sessions[50];
int	players[50];
int n_sessions = 0;
int n_players = 0;
static char		adrString[256];
static short	defaultSessType;
dpio_t			*dpio = NULL;
dp_transport_t 	CommDLLName;
char 			pname[17];
dpid_t          myID = dp_ID_NONE;
dpid_t          mylowestId = dp_ID_NONE;
dp_t            *myDP = NULL;
static int my_nPlayer = 0;

dp_result_t theError = dp_RES_OK;
#define dumpBuf(buf, len)

HWND hMainWin;
HWND hChat;
HWND hChatIn;
HWND hPlayers;
HWND hGames;

FAR PROC DefEditProc;
FAR PROC DefEditProc1;
FAR PROC DefEditProc2;
const char g_szClassName[] = "myWindowClass";
#define IDC_MAIN_CHAT	 101
#define IDC_MAIN_CHATIN	 102
#define IDC_MAIN_PLAYERS 103
#define IDC_MAIN_GAMES   104


void AppendText(HWND hWndEdit, LPCSTR szText) {
	SendMessage(hWndEdit,EM_SETSEL,INT_MAX,INT_MAX);
	SendMessage(hWndEdit,EM_REPLACESEL,TRUE,(LPARAM)szText);
}

void pTime() {
	char buf[9];
	time_t t = time(NULL);
	struct tm *ts = localtime(&t);
	sprintf(buf, "[%02d:%02d] ",ts->tm_hour, ts->tm_min);
	AppendText(hChat, buf);
}

void dp_PASCAL create_player_cb(dpid_t id, char_t *name, long flags, void *context) {
	char buf[300];
	if (id != dp_ID_NONE) {
		myID = id;
		theError = dp_RES_OK;
	} else {
		AppendText(hChat, "...failure (bah, bad name possibly?)\r\n");
		theError = dp_RES_BAD;
	}

	(void) context;
	(void) flags;
	return FALSE;
}

int dp_PASCAL join_sess_cb(dp_session_t *ps, long *pTimeout, long flags, void *context) {
	char buf[255];
	if (ps) {
		dpCreatePlayer(myDP, create_player_cb, pname, pname);
	}

	(void) context;
	return FALSE;
}
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch(msg) {
		case WM_INITDIALOG: {
			return TRUE;
		}
		case WM_COMMAND: {
			switch(LOWORD(wParam)) {
				case IDOK: {
					EndDialog(hwnd, IDOK);
					break;
				}
				case IDCANCEL: {
					EndDialog(hwnd, IDCANCEL);
					break;
				}
			}
			break;
		}
		default: {
			return FALSE;
		}

	}
	return TRUE;
}
BOOL CALLBACK SetNameProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch(msg) {
		case WM_INITDIALOG: {
			SendDlgItemMessage(hwnd, IDC_EDIT1, EM_SETLIMITTEXT, 14, 0);
			return TRUE;
		}
		case WM_COMMAND: {
			switch(LOWORD(wParam)) {
				case IDOK: {

					int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT1));
					if(len > 0) {
						char* buf;
						int i;
						if (len > 14) len = 14;

						buf = (char*)GlobalAlloc(GPTR, 16);
						GetDlgItemText(hwnd, IDC_EDIT1, buf, len + 1);
						pname[0] = 208;
						pname[1] = '-';
						strcat(pname, buf);
						
						GlobalFree((HANDLE)buf);
						EndDialog(hwnd, IDOK);
					}
					else {
						MessageBox(NULL, "You must enter a name...!", "Error!", MB_ICONEXCLAMATION | MB_OK);
						return FALSE;
					}

					break;
				}
			}
			break;
		}
		default: {
			return FALSE;
		}

	}
	return TRUE;
}

dp_result_t SendChatMessage( char *szChatText )
{
#include "dppack1.h"
	struct {
		dp_packetType_t type;
		char buf[200];
		char skip[6];	/* Caution: six bytes after buf trashed by dpSend! */
	} pkt;
#include "dpunpack.h"
	dp_result_t err;
	int i;
	pkt.type = CHAT_PACKET_ID;

	strcpy(pkt.buf, szChatText);


	err = dpSend(myDP, myID, dp_ID_BROADCAST, dp_SEND_RELIABLE, &pkt, sizeof(pkt)-sizeof(pkt.skip));
	return err;
}

int dp_PASCAL listSessions_cb(dp_session_t *sDesc, long *pTimeout,long flags,void *context)
{
	char buf[300];
	char status[20] = "";

	if (!sDesc) {
		return FALSE;
	}

	sessions[n_sessions] = *sDesc;
	n_sessions++;

	if (sDesc->flags == 0xc4) {
		if (sDesc->dwUser1 > 0) {
		strncpy(status, "€ ", sizeof(status));
		}
	}


	sprintf(buf, "%s%s (%d/%d)\n", status, sDesc->sessionName, sDesc->currentPlayers, sDesc->maxPlayers);
	
	SendMessage(hGames, LB_ADDSTRING, 0, (LPARAM)buf);

	return TRUE;
}

void dp_PASCAL listPlayersSess_cb(dpid_t id, char_t *name, long flags, void *context)
{
	if (id != dp_ID_NONE) {
		AppendText(hChat, name);
		AppendText(hChat, ", ");
	}
	else { 
		AppendText(hChat, "\r\n");
	}

	(void) context;
	(void) flags;
}

void dp_PASCAL listPlayers_cb(dpid_t id, char_t *name, long flags, void *context)
{

	if (id != dp_ID_NONE) {
		SendMessage(hPlayers, LB_ADDSTRING, 0, (LPARAM)name);
	}
	(void) context;
	(void) flags;
}


LRESULT CALLBACK SessionsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
     switch(message) {
			case WM_LBUTTONDBLCLK: {
				int i = SendMessage(hGames, LB_GETCURSEL, 0, 0);
				n_players = 0;
				AppendText(hChat, "Listing players in '");
				AppendText(hChat, sessions[i].sessionName);
				AppendText(hChat, "': ");

				dpEnumPlayers(myDP, &sessions[i], listPlayersSess_cb, NULL, 1750L);
				break;
			}
          default:
               return( (LRESULT)CallWindowProc((WNDPROC)DefEditProc1,hwnd,message,wParam,lParam) );
          break;
     }
     return(0);
}

LRESULT CALLBACK MyEditProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
     switch(message) {
          case WM_CHAR:
               if( wParam == VK_RETURN ) {
						int len = GetWindowTextLength(GetDlgItem(hMainWin, IDC_MAIN_CHATIN));
						if(len > 0) {
							char* buf;

							buf = (char*)GlobalAlloc(GPTR, len + 3);
							GetDlgItemText(hMainWin, IDC_MAIN_CHATIN, buf, len + 3);

							SendChatMessage(buf);
							pTime();
							AppendText(hChat, pname);
							AppendText(hChat, ": ");
							sprintf(buf, "%s\r\n", buf);
							AppendText(hChat, (LPCSTR)buf);
							GlobalFree((HANDLE)buf);
							SetWindowText(hwnd, (LPCSTR)"");
						}
               }
               else return( (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hwnd,message,wParam,lParam) );
          break;
          default:
               return( (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hwnd,message,wParam,lParam) );
          break;
     }
     return(0);
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch(msg) {
		case WM_CREATE: {
			HWND hTemp;
			int i = 0;

			hTemp = CreateWindowEx(
				WS_EX_CLIENTEDGE, "EDIT", "",
				WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL,
				0, 0, 400, 300, hwnd, (HMENU)IDC_MAIN_CHAT,
				GetModuleHandle(NULL), NULL
			);
			hChat = hTemp;
			SendMessage(hTemp,EM_SETLIMITTEXT,0xFFFFFF,0);

			hTemp = CreateWindowEx(
				WS_EX_CLIENTEDGE, "LISTBOX", "",
				WS_CHILD | WS_VISIBLE,
				400, 0, 130, 200, hwnd, (HMENU)IDC_MAIN_PLAYERS,
				GetModuleHandle(NULL), NULL
			);
			hPlayers = hTemp;
			
			hTemp = CreateWindowEx(
				WS_EX_CLIENTEDGE, "LISTBOX", "",
				WS_CHILD | WS_VISIBLE,
				400, 205, 130, 95, hwnd, (HMENU)IDC_MAIN_GAMES,
				GetModuleHandle(NULL), NULL
			);

			hGames = hTemp;

			hTemp = CreateWindowEx(
				WS_EX_CLIENTEDGE, "EDIT", "",
				WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
				0, 300, 400, 20, hwnd, (HMENU)IDC_MAIN_CHATIN,
				GetModuleHandle(NULL), NULL
			);
			hChatIn = hTemp;
			SendMessage(hTemp,EM_SETLIMITTEXT,199,0);

			
			DefEditProc = (WNDPROC)GetWindowLong(hChatIn,GWL_WNDPROC);
			SetWindowLong(hChatIn,GWL_WNDPROC,(long)MyEditProc);
			DefEditProc1 = (WNDPROC)GetWindowLong(hGames,GWL_WNDPROC);
			SetWindowLong(hGames,GWL_WNDPROC,(long)SessionsProc);

		}
		case WM_COMMAND: {
			switch(LOWORD(wParam)) {
				case ID_FILE_EXIT: {
					PostMessage(hwnd, WM_CLOSE, 0, 0);
					break;
				}
				case ID_HELP_ABOUT:	{
					int ret = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
				}
			}
		}
		break;
		case WM_SIZE: {
			RECT rc;
			int rightside = 230;

			GetClientRect(hwnd, &rc);

			SetWindowPos(hChatIn, NULL, 0, rc.bottom - 20, rc.right - rightside, 20, SWP_NOZORDER);
			SetWindowPos(hChat, NULL, 0, 0, rc.right - rightside, rc.bottom - 22, SWP_NOZORDER);
			SetWindowPos(hPlayers, NULL, rc.right - rightside, 0, rightside, rc.bottom - 100, SWP_NOZORDER);
			SetWindowPos(hGames, NULL, rc.right - rightside, rc.bottom - 95, rightside, 100, SWP_NOZORDER);
		}
		case WM_LBUTTONDOWN: {
			break;
		}
		case WM_CLOSE: {
			DestroyWindow(hwnd);
			break;
		}
		case WM_DESTROY: {
			if (myDP)
				dpClose(myDP);
			PostQuitMessage(0);
			break;
		}
		default: {
			return DefWindowProc(hwnd, msg, wParam, lParam);
		}
	}
	return 0;
}



int  __stdcall poll_server() {
	dp_session_t  sess;
	dpid_t idFrom;
	dpid_t idTo;
	char buf[512];
	char nameBuf[256];
	#include "dppack1.h"
	struct {
		dp_packetType_t type PACK;
		union {
			dp_user_addPlayer_packet_t addPlayer;
			dp_user_delPlayer_packet_t delPlayer;
			dp_user_addGroup_packet_t ag;
			dp_user_delGroup_packet_t dg;
			dp_addPlayerToGroup_packet_t gap;
			dp_delPlayerFromGroup_packet_t gdp;
			dp_user_playerData_packet_t pv;
			dp_objectDelta_packet_t delta;
			dp_account_packet_t acctpkt;
			dp_sessionResult_packet_t sessRes;
			unsigned char buf[512];
		} u PACK;
	} pkt;
	#include "dpunpack.h"
	size_t size;
	dp_result_t   err;
	int i;	


	blob++;
	if (blob == 200) {
		
		n_sessions = 0;
		SendMessage(hGames, LB_RESETCONTENT, 0, 0);
		sess.sessionType = atoi("669");
		dpEnumSessions(myDP, &sess, NULL, 1750L, listSessions_cb, NULL);

		SendMessage(hPlayers, LB_RESETCONTENT, 0, 0);
		dpEnumPlayers(myDP, NULL, listPlayers_cb, NULL, 1750L);

		blob = 0;
	}

	if (myDP) {
		size = sizeof(pkt);
		err = dpReceive(myDP, &idFrom, &idTo, 0, &pkt, &size);
		if (err == dp_RES_EMPTY)
			return 1;

		switch (pkt.type) {
			case dp_USER_ADDPLAYER_PACKET_ID: {
				pTime();
				AppendText(hChat, "**** ");
				AppendText(hChat, pkt.u.delPlayer.name);
				AppendText(hChat, " enters the room\r\n");
				FlashWindow(hMainWin, TRUE);
				break;
			}
			case dp_USER_DELPLAYER_PACKET_ID: {
				pTime();
				AppendText(hChat, "**** ");
				AppendText(hChat, pkt.u.delPlayer.name);
				AppendText(hChat, " leaves the room\r\n");
				break;
			}
			case CHAT_PACKET_ID: {
				err = dpGetPlayerName(myDP, idFrom, nameBuf, sizeof(nameBuf));
				for (i = 4; i < size-3; i++) {
					pkt.u.buf[i-4] = pkt.u.buf[i];
				}
				pkt.u.buf[size-7] = 0;
				pTime();
				AppendText(hChat, nameBuf);
				AppendText(hChat, ": ");
				AppendText(hChat, pkt.u.buf);
				AppendText(hChat, "\r\n");
				FlashWindow(hMainWin, TRUE);
				break;
			}
			case dp_SESSIONLOST_PACKET_ID:
				sprintf(buf, "******* Connection to server lost (Restart DROM)******");
				AppendText(hChat, buf);
				break;
			default: {
				char buf[300];
				sprintf(buf, "Odd; got unexpected packet %d, %x size %d\n", pkt.type, size);
			}
		}
	}
	KillTimer(0, TimerID);
	TimerID = SetTimer(0, 0, 10, poll_server);
	return 1;
};

void connectServer() {
	dp_result_t   err;
	short sesstype = atoi("669");
	dp_session_t sess;
	strncpy(adrString, "vps.gr", sizeof(adrString));
	adrString[sizeof(adrString)-1] = '\0';

	strncpy(CommDLLName.fname, "winets2.dll", sizeof(CommDLLName.fname));
	CommDLLName.fname[sizeof(CommDLLName.fname)-1] = '\0';

	AppendText(hChat, "Opening connection...");
	err = dpCreate(&myDP, &CommDLLName, NULL, NULL);
	if (err != dp_RES_OK) {
		AppendText(hChat, "...failed (shouldnt do that...)\r\n");
	}
	else {
		AppendText(hChat, "...success\r\n");
	}
	AppendText(hChat, "Setting Game Server (vps.gr)...");
	err = dpSetGameServerEx(myDP, adrString, sesstype);
	if (err != dp_RES_OK) {
		AppendText(hChat, "...failed (no internet connection? / server down?)\r\n");
	}
	else {
		AppendText(hChat, "...success\r\n");
	}
	err = dpOpen(myDP, NULL, join_sess_cb, NULL);
}

int  __stdcall say_something() {
	SendChatMessage("TEST MESSAGE FOR DROM (EVERY 10 MINUTES)");
	pTime();
	AppendText(hChat, "++++SENT TEST MESSAGE++++\r\n");
	return 1;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc;
	HWND hwnd;
	TimerID = SetTimer(0, 0, 10, poll_server);

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
	wc.hIconSm       = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0);
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
	wc.lpszClassName = g_szClassName;

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!", "Error!",
		MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE, g_szClassName,
		"DROM v0.5", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, 600, 380,
		NULL, NULL, hInstance, NULL
	);

	hMainWin = hwnd;
	DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_NAME), hwnd, SetNameProc);

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	connectServer();

	while(GetMessage(&Msg, NULL, 0, 0) > 0) {
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}





