#include "global.h"
#include <commctrl.h>
#include "resource.h"
#include "cmainwnd.h"
#include "cdatalogwin.h"
#include "coutputwnd.h"
#include "cseparator.h"

CMainWindow::CMainWindow()
{
	static char classname[] = "cmainwindowinlog";
	WNDCLASS wc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
	wc.hCursor = ::LoadCursor(0,IDC_ARROW);
	wc.hIcon = LoadIcon(app.hInstance, MAKEINTRESOURCE(IDI_PROGRAM));
	wc.hInstance = app.hInstance;
	wc.lpfnWndProc = (WNDPROC)CMainWindow::StaticWindowProc;
	wc.lpszClassName = classname;
	wc.lpszMenuName = 0;
	wc.style = 0;
	::RegisterClass(&wc);

	hwnd = ::CreateWindowEx(0, classname, "InLog", WS_OVERLAPPEDWINDOW|WS_VISIBLE|WS_MAXIMIZE ,
		CW_USEDEFAULT,CW_USEDEFAULT,
		600, 500, 0, NULL, app.hInstance, 0);

	menu = ::LoadMenu(app.hInstance,MAKEINTRESOURCE(MENU_MAIN));
	::SetMenu(hwnd, menu);
	SetMenu(false);

	//asociuj okno s jeho instanciou
	::SetWindowLong(hwnd,GWL_USERDATA,(DWORD)this);

	accelerator = ::LoadAccelerators(app.hInstance,MAKEINTRESOURCE(ID_ACCELERATOR));

	atomsWindow = NULL;
	datalogWindow = NULL;
	outputWindow = NULL;
	htmlWindow = NULL;
	sepHorWindow = NULL; sepVerWindow = NULL;
	//hWndViewResult = NULL;
}

CMainWindow::~CMainWindow()
{
}

void CMainWindow::ChangeMenuState(UINT item,UINT state)
{
	MENUITEMINFO mii;
	mii.cbSize = sizeof(mii);
	mii.fMask = MIIM_STATE | MIIM_ID;
	mii.fState = state;
	mii.wID = item;
	::SetMenuItemInfo(::GetMenu(hwnd), item, FALSE, &mii);
	GetLastError();
}

LRESULT CALLBACK CMainWindow::WindowProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	switch (msg)
	{
	case WM_COMMAND:
		wmCOMMAND(wp,lp);
		break;
	case WM_ACTIVATE:
		if (this)
		{
			switch (LOWORD(wp))
			{
			case WA_ACTIVE:
				::SetFocus(focusHwnd);
				break;
			case WA_INACTIVE:
				focusHwnd = ::GetFocus();
				break;
			}
		}
		return 0;
	case WM_CLOSE:
		return wmCLOSE();
	case WM_DESTROY:
		wmDESTROY();
		break;
	case WM_SIZE:
		wmSIZE(wp,lp);
		break;
	case WM_NOTIFY:
		wmNOTIFY(wp,lp);
		break;
	}
	return ::DefWindowProc(hwnd,msg,wp,lp);
}

HACCEL CMainWindow::GetAccelerator()
{
	return accelerator;
}

HWND CMainWindow::GetHandle()
{
	return hwnd;
}

void CMainWindow::wmSIZE(WPARAM wp,LPARAM lp)
{
	if (!this)//prva sprava wmSIZE, este sme nevysli z konstruktora
		return;

	if (sepVerWindow && sepHorWindow)
	{
		//nastav vzdialenost sepHor od spodneho okraja a lavu stranu uprav na pravy okraj sepVer
		RECT rcMain; ::GetClientRect(hwnd, &rcMain);
		RECT rc; ::GetWindowRect(sepVerWindow->GetHandle(), &rc);
		POINT p; p.x = rc.right; p.y = 0; ::ScreenToClient(hwnd, &p);
		sepHorWindow->SetPosition(p.x, rcMain.bottom-app.options->win.sepHor,
			rcMain.right-p.x);

		//nastav vysku sepVer podla velkosti tohto parenta
		p.x = rc.left; p.y = rc.top; ::ScreenToClient(hwnd, &p);
		sepVerWindow->SetPosition(p.x, p.y, rcMain.bottom-p.y);
	}
}

void CMainWindow::SepVerGetMinMax(DWORD *minScreen, DWORD *maxScreen)
{
	RECT rc; POINT p;
	HWND mainHwnd = app.mainWindow->GetHandle();
	::GetClientRect(mainHwnd, &rc);
	p.x = 0; p.y = 0; ::ClientToScreen(mainHwnd, &p); *minScreen = p.x;
	p.x = rc.right; ::ClientToScreen(mainHwnd, &p); *maxScreen = p.x;
}

void CMainWindow::SepVerSized(RECT *rcParentClient)
{
	//nastav sirku atomswindow
	//nastav lavu poziciu sephor

	//uloz nastavenie
	app.options->win.sepHor = rcParentClient->left;

	RECT rcMain; ::GetClientRect(app.mainWindow->GetHandle(), &rcMain);
	::SetWindowPos(app.mainWindow->GetAtomsWindow()->GetHandle(), 0,
		0, 0, rcParentClient->left, rcParentClient->bottom,
		SWP_NOZORDER | SWP_NOMOVE | SWP_NOCOPYBITS);

	if (app.mainWindow->sepHorWindow)
	{
		HWND hSepHor = app.mainWindow->sepHorWindow->GetHandle();
		RECT rc; ::GetWindowRect(hSepHor, &rc);
		HWND mainHwnd = app.mainWindow->GetHandle();
		POINT p; p.x = rc.left; p.y = rc.top; ::ScreenToClient(mainHwnd, &p);
		::GetClientRect(mainHwnd, &rc);
		app.mainWindow->sepHorWindow->SetPosition(rcParentClient->right, p.y, rc.right-rcParentClient->right);
	}
}

void CMainWindow::SepHorGetMinMax(DWORD *minScreen, DWORD *maxScreen)
{
	RECT rc; POINT p;
	HWND mainHwnd = app.mainWindow->GetHandle();
	::GetClientRect(mainHwnd, &rc);
	p.x = 0; p.y = 0; ::ClientToScreen(mainHwnd, &p); *minScreen = p.y;
	p.y = rc.bottom; ::ClientToScreen(mainHwnd, &p); *maxScreen = p.y;
}

void CMainWindow::SepHorSized(RECT *rcClient)
{
	//nastav vysku a left datalogwindow
	//nastav vysku,top a left outputwindow

	RECT rcMain; ::GetClientRect(app.mainWindow->GetHandle(), &rcMain);

	//uloz nastavenie
	app.options->win.sepHor = rcMain.bottom - rcClient->top;

	::SetWindowPos(app.mainWindow->GetOutputWindow()->GetHandle(), 0,
		rcClient->left, rcClient->bottom, rcClient->right - rcClient->left, rcMain.bottom - rcClient->bottom,
		SWP_NOZORDER | SWP_NOCOPYBITS);
	::SetWindowPos(app.mainWindow->GetDatalogWindow()->GetHandle(), 0,
		rcClient->left, 0, rcClient->right - rcClient->left, rcClient->top,
		SWP_NOZORDER | SWP_NOCOPYBITS);

}

void CMainWindow::Connect(bool connect)
{
	if (connect)
	{
		if(app.GetDatabase()->Connect())
		{
			SetMenu(true);
			atomsWindow = _NEW(CAtomsWindow(hwnd)); atomsWindow->ShowWindow(true); atomsWindow->Refresh();
			datalogWindow = _NEW(CDatalogWindow(hwnd)); datalogWindow->ShowWindow(true);
			outputWindow = _NEW(COutputWindow(hwnd)); outputWindow->ShowWindow(true);
			htmlWindow = _NEW(CHtml(hwnd));
			::SetFocus(datalogWindow->GetHandle());
			app.GetDatabase()->UpdateStructure();
			atomsWindow->Refresh();


			RECT rc; ::GetClientRect(hwnd, &rc);
			sepHorWindow = _NEW(CSeparator(SEPARATOR_HORIZONTAL, hwnd, 
				app.options->win.sepVer, rc.bottom - app.options->win.sepHor,
				rc.right - app.options->win.sepVer,
				SepHorSized, SepHorGetMinMax));
			sepVerWindow = _NEW(CSeparator(SEPARATOR_VERTICAL, hwnd, 
				app.options->win.sepVer, 0,
				rc.bottom,
				SepVerSized, SepVerGetMinMax));
		}
		else
		{
			SetMenu(false);
		}
	}
	else
	{
		app.GetDatabase()->Disconnect();

		SetMenu(false);

		if (atomsWindow) { _DELETE(atomsWindow); atomsWindow = NULL;}
		if (outputWindow) {_DELETE(outputWindow); outputWindow = NULL;}
		if (datalogWindow) {_DELETE(datalogWindow); datalogWindow = NULL;}
		if (htmlWindow) {_DELETE(htmlWindow); htmlWindow = NULL;}
		if (sepHorWindow) {_DELETE(sepHorWindow); sepHorWindow = NULL;}
		if (sepVerWindow) {_DELETE(sepVerWindow); sepVerWindow = NULL;}

/*		if (hWndViewResult)
			::DestroyWindow(hWndViewResult);*/
	}

}

void CMainWindow::SetMenu(bool connect)
{
	if (connect)
	{
		ChangeMenuState(MENU_CONNECT, MFS_DISABLED | MFS_GRAYED);

		ChangeMenuState(MENU_DISCONNECT, MFS_ENABLED);
		ChangeMenuState(MENU_REFRESH_DB, MFS_ENABLED);
		ChangeMenuState(MENU_LOAD, MFS_ENABLED);
		ChangeMenuState(MENU_SAVE, MFS_ENABLED);
		ChangeMenuState(MENU_HILIGHT, MFS_ENABLED);
		ChangeMenuState(MENU_EVALUATE, MFS_ENABLED);
		ChangeMenuState(MENU_NEW, MFS_ENABLED);
		ChangeMenuState(MENU_SAVEAS, MFS_ENABLED);
	}
	else
	{
		//connect = FALSE
		ChangeMenuState(MENU_CONNECT, MFS_ENABLED);
		ChangeMenuState(MENU_DISCONNECT, MFS_DISABLED | MFS_GRAYED);
		ChangeMenuState(MENU_REFRESH_DB, MFS_DISABLED | MFS_GRAYED);

		ChangeMenuState(MENU_SAVEAS, MFS_DISABLED | MFS_GRAYED);
		ChangeMenuState(MENU_NEW, MFS_DISABLED | MFS_GRAYED);
		ChangeMenuState(MENU_LOAD, MFS_DISABLED | MFS_GRAYED);
		ChangeMenuState(MENU_SAVE, MFS_DISABLED | MFS_GRAYED);
		ChangeMenuState(MENU_HILIGHT, MFS_DISABLED | MFS_GRAYED);
		ChangeMenuState(MENU_EVALUATE, MFS_DISABLED | MFS_GRAYED);
	}
}

void CMainWindow::Menu(WPARAM wp)
{
	switch (LOWORD(wp))
	{
		case MENU_CONNECT:
			Connect(true);
			break;
		case MENU_DISCONNECT:
			Connect(false);
			break;
		case MENU_REFRESH_DB:
			app.GetDatabase()->UpdateStructure();
			atomsWindow->Refresh();//este EDB treeview zmen
			datalogWindow->Colorize();//prefarbi EDB atomy
			break;
		case MENU_LOAD:
			datalogWindow->LoadFromFile();
			break;
		case MENU_SAVE:
			datalogWindow->SaveToFile();
			break;
		case MENU_NEW:
			datalogWindow->NewFile();
			break;
		case MENU_SAVEAS:
			datalogWindow->SaveToFileAs();
			break;
		case MENU_HILIGHT:
			datalogWindow->ColorizeIDBAtoms();
			break;
		case MENU_EVALUATE:
			datalogWindow->Evaluate();
			break;
		case MENU_SETTINGS:
			app.options->SetSettings();
			break;
		case MENU_EXIT:
			wmCLOSE();
			break;
		case MENU_ABOUT:
			::DialogBoxParam(app.hInstance, MAKEINTRESOURCE(DLG_ABOUT), hwnd, (DLGPROC)StaticDialogProcAbout, 0);
			break;
	}
}

INT_PTR CALLBACK CMainWindow::StaticDialogProcAbout(HWND hwnd, UINT msg, WPARAM wp,LPARAM lp)
{
	switch (msg)
	{
	case WM_COMMAND:
		if (LOWORD(wp) == IDOK)
			EndDialog(hwnd, 1);
		break;
	}
	return 0;
}

void CMainWindow::wmDESTROY()
{
	Connect(false);
	::PostQuitMessage(1);
}

void CMainWindow::wmCOMMAND(WPARAM wp,LPARAM lp)
{
	if ( (HIWORD(wp) == 0) || (HIWORD(wp) == 1) )
		Menu(LOWORD(wp));

	if (datalogWindow)
	{
		if ((HWND)lp == datalogWindow->GetHandle())
			datalogWindow->wmCOMMANDfromParent(wp);
	}
}

LRESULT CMainWindow::wmCLOSE()
{
	if (datalogWindow)
		if (!datalogWindow->Close())
			return 0;
	::DestroyWindow(hwnd);
	return 0;
}

void CMainWindow::wmNOTIFY(WPARAM wp, LPARAM lp)
{
	HWND h = ((NMHDR*)lp)->hwndFrom; 
	if (atomsWindow)
		if ( h == atomsWindow->GetHandle())
			atomsWindow->WmNotify(lp);
	if (datalogWindow)
		if ( h == datalogWindow->GetHandle() )
			datalogWindow->wmNOTIFYfromParent((NMHDR*)lp);
}

//static
LRESULT CALLBACK CMainWindow::StaticWindowProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	DWORD p = ::GetWindowLong(hwnd,GWL_USERDATA);
	if (p)
		return ((CMainWindow*)p)->WindowProc(hwnd,msg,wp,lp);
	else
		return ::DefWindowProc(hwnd, msg, wp, lp);
}

CDatalogWindow *CMainWindow::GetDatalogWindow()
{
	return datalogWindow;
}

CHtml *CMainWindow::GetHtmlWindow()
{
	return htmlWindow;
}


CAtomsWindow *CMainWindow::GetAtomsWindow()
{
	return atomsWindow;
}

COutputWindow *CMainWindow::GetOutputWindow()
{
	return outputWindow;
}

//HWND CMainWindow::hWndViewResult = NULL;
