// EntryPoint.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include "RPCServer.h"
#include "HouseKeeper.h"
#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance

// Forward declarations of functions included in this code module:
ATOM				RegisterSkinnableWindowClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	 
	wVersionRequested = MAKEWORD( 2, 2 );
	 
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		MessageBox(NULL,L"Couldn't initialize Winsock",L"BridgeClient Error",MB_OK);
		return 0;
	}
	 
	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */
	 
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
			HIBYTE( wsaData.wVersion ) != 2 ) {
		MessageBox(NULL,L"Couldn't initialize Winsock",L"BridgeClient Error",MB_OK);
		WSACleanup( );
		return 0; 
	}
	 
	/* The WinSock DLL is acceptable. Proceed. */


	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	
	// Initialize GDI+.
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	MSG msg;
	HACCEL hAccelTable;

	// Register the window classes that we need
	RegisterSkinnableWindowClass(hInstance);
	
	// Initialize the rich edit control
	LoadLibrary(_T("riched32.dll"));

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_BRIDGESERVER);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	// Main message loop:
	int bRet;
	while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
	{ 
		if (bRet == -1)
		{
			// handle the error and exit
			break;
		}
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	GdiplusShutdown(gdiplusToken);

	RPCServer::ShutDown();

	db.Disconnect();

	env.console.StopLogging();

	return (int) msg.wParam;
}



//
//  FUNCTION: RegisterSkinnableWindowClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM RegisterSkinnableWindowClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;
	TCHAR szWindowClass[] = _T("SkinnableWindow");			// the generic window class name

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_SAVEBITS;
	wcex.lpfnWndProc	= (WNDPROC)SkinnableWindow::WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_BRIDGESERVER);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= NULL;
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // Store instance handle in our global variable
	
	env.hInstance = hInstance;
	// load various cursors
	env.normalcursor = LoadCursor(NULL,IDC_ARROW);
	env.handcursor = LoadCursor(NULL,IDC_HAND);
	env.resizecursor = LoadCursor(NULL,IDC_SIZENWSE);

	SetCurrentDirectory(L"resources");
	if(!env.LoadConfiguration("startup.tcl")){
		SetCurrentDirectory(L"../resources");
		if(!env.LoadConfiguration("startup.tcl")){
			MessageBox(NULL,L"Couldn't find startup.tcl or it contained errors.",L"BridgeServer Error",MB_OK);
		}	
	}


	std::wstring path = env.GetWideString(NULL,"path",L".");
	SetCurrentDirectory(path.data());

	env.InitConsole();
	env.console.Show();
	if(env.GetInt(NULL,"logging",0))
		env.console.StartLogging(env.GetWideString(NULL,"logfile",L"log.txt"));
	env.Timeout = env.GetInt(NULL,"timeout",5);

	print(L"BridgeServer (Build %d, compiled on %S %S)\n",BUILD_NUMBER,__DATE__,__TIME__);

	RPCServer::StartService();

	std::wstring sqlserver, sqltable, sqluser, sqlpassword;
	sqlserver = env.GetWideString("sql","server",L"studiomit6.mit.edu");
	sqltable = env.GetWideString("sql","table",L"testBridge2");
	sqluser = env.GetWideString("sql","user",L"sa");
	sqlpassword = env.GetWideString("sql","password",L"Bridge2001");

	// set db timeouts and connect
	db.ConnectionTimeout = env.GetInt("sql","ConnectionTimeout",db.ConnectionTimeout);
	db.CommandTimeout = env.GetInt("sql","CommandTimeout",db.CommandTimeout);
	if(!db.Connect(sqlserver.data(),sqltable.data(),sqluser.data(),sqlpassword.data()))
		print(L"BridgeDB: Unable to open connection to SQL server %s( %s) as %s.\n",sqlserver.data(),sqltable.data(),sqluser.data());
	else
		print(L"BridgeDB: connected to SQL server %s (%s) as %s.\n",sqlserver.data(),sqltable.data(),sqluser.data());

	// Start the house keeper thread
	hk.Start();

	return TRUE;
}


// Message handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		return TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
		{
			EndDialog(hDlg, LOWORD(wParam));
			return TRUE;
		}
		break;
	}
	return FALSE;
}

