#include "global.h"
#include "coutputwnd.h"
#include <stdlib.h>
#include <richedit.h>

COutputWindow::COutputWindow(HWND parent)
{
	RECT rc;
	::GetClientRect(parent, &rc);
	hwnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", 0,
		WS_CHILD|WS_TABSTOP|WS_HSCROLL|WS_VSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,
		202, 302, rc.right-202, rc.bottom-302, parent, (HMENU)NULL, app.hInstance, NULL);

	HFONT hFont = (HFONT)::CreateFont(16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
		DEFAULT_QUALITY, 0, "Courier New CE");
	::SendMessage(hwnd, WM_SETFONT, (LPARAM)hFont, 0);

	//nastav vlastnu wndproc (chcem aby nereagoval na stlacenie klavesy - readonly)
	//pri nastaveni ES_READONLY ma tmavu farbu pozadia, co nechcem, chcem aby mal normalnu bielu

	//asociuj okno s jeho instanciou
	::SetWindowLong(hwnd,GWL_USERDATA,(DWORD)this);
	oldWindowProc = (WNDPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
	::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)StaticWindowProc);

	buffer = NULL;
}

void COutputWindow::ShowWindow(bool show)
{
	::ShowWindow(hwnd, show ? SW_SHOW : SW_HIDE);
}

COutputWindow::~COutputWindow()
{
	StopBuffering();
	DestroyWindow(hwnd);
}

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

void COutputWindow::AddLine(char* string)
{
	::SendMessage(hwnd, EM_REPLACESEL, FALSE, (LONG)string);
	::SendMessage(hwnd, EM_REPLACESEL, FALSE, (LONG)"\x0d\x0a");
}

void COutputWindow::StartBuffering(DWORD numOfLines)
{
	buffer = _NEW(CMemory());
	buffer->AddData(NULL, 4*numOfLines);
}

void COutputWindow::StopBuffering()
{
	if (buffer)

	{
		for (DWORD i=0; i<buffer->GetSize()/4; i++)
		{
			CStringTable *st = ((CStringTable**)(buffer->GetPointer()))[i];
			if (st)
			{
				_DELETE(st);
			}
		}
		_DELETE(buffer);
		buffer = NULL;
	}
}

void COutputWindow::WriteBuffer()
{
	if (buffer)
	{
		for (DWORD i=0; i<buffer->GetSize()/4; i++)
		{
			CStringTable *st = ((CStringTable**)(buffer->GetPointer()))[i];
			if (st)
			{
				for (DWORD j=0; j<st->GetCount(); j++)
					AddLine((char*)st->Get(j));
			}
		}

		StopBuffering();
	}
}

void COutputWindow::AddNumberedLineToBuffer(char* string, int line)
{
	CStringTable *st = ((CStringTable**)(buffer->GetPointer()))[line-1];
	if (!st)
	{
		st = _NEW(CStringTable());
		((CStringTable**)(buffer->GetPointer()))[line-1] = st;
	}
	char *tmp = CMemory::printstr("(%i) %s", line, string);
	st->Add(tmp); _DELETE(tmp);
}

void COutputWindow::AddNumberedLine(char* string, int line)
{
	char *tmp = CMemory::printstr("(%i) %s\x00d\x00a", line, string);
	::SendMessage(hwnd, EM_REPLACESEL, FALSE, (LONG)tmp); _DELETE(tmp);
}


void COutputWindow::Clear()
{
	::SendMessage(hwnd, EM_SETSEL, 0, -1);
	::SendMessage(hwnd, EM_REPLACESEL, FALSE, (LONG)"");
}

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

LRESULT CALLBACK COutputWindow::WindowProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	switch (msg)
	{
	case WM_CHAR:
		return 0;//read-only
	case WM_LBUTTONDBLCLK:
		wmLBUTTONDBLCLK();
		break;
	}
	return ::CallWindowProc(oldWindowProc, hwnd,msg,wp,lp);
}

void COutputWindow::wmLBUTTONDBLCLK()
{
	//skoc na riadok
	//TODO 2048 pamate
	char* str = (char*)::GlobalAlloc(GMEM_FIXED, 2048);
	DWORD line = ::SendMessage(hwnd, EM_LINEFROMCHAR, -1, 0);//aktualny riadok
	::SendMessage(hwnd, EM_GETLINE, line, (LPARAM)str);//vrat riadok

	//riadok je v tvare (riadok,stlpec) error

	if (str[0] == '(')
	{
		//nacitaj cislo riadku
		line = atoi(&str[1]);
		//nastav v okne pre datalog danu poziciu
		CHARRANGE chr;
		HWND h = app.mainWindow->GetDatalogWindow()->GetHandle();
		chr.cpMax = chr.cpMin = ::SendMessage(h, EM_LINEINDEX, line-1, 0);
		::SendMessage(h, EM_EXSETSEL, 0, (LPARAM)&chr);
		::SetFocus(h);
	}
	::GlobalFree(str);
}

void COutputWindow::DoResize()
{
	RECT /*rc,*/rcParent,rcAtom,rcDatalog;
	//::GetWindowRect(hwnd, &rc);
	::GetClientRect(::GetParent(hwnd), &rcParent);
	::GetWindowRect(app.mainWindow->GetAtomsWindow()->GetHandle(), &rcAtom);
	::GetWindowRect(app.mainWindow->GetDatalogWindow()->GetHandle(), &rcDatalog);
	::SetWindowPos(hwnd, 0, rcAtom.right-rcAtom.left+3, rcParent.bottom-200,
		rcParent.right-(rcAtom.right-rcAtom.left)-2, 200, SWP_NOZORDER);
}