#include "StdAfx.h"
#include "chatwindow.h"
#include "bridgeserver_h.h"
#include "webctrl.h"

StringMap ChatWindow::tmap; 

void ChatWindow::LoadTranslator(const char * b)
{
	int i, n = env.GetInt(b,"nElements",0);

	char buffer[100];
	std::wstring key,data;
	tmap.Clear();
	for(i=0;i<n;i++){
		sprintf(buffer,"key%d",i+1);
		key = env.GetWideString(b,buffer,L"");
		sprintf(buffer,"data%d",i+1);		
		data = env.GetWideString(b,buffer,L"");
		tmap.Insert(key.data(),data.data());
	}
}

//

const TCHAR * MakeLinksClickable(const TCHAR * msg)
{
	static std::wstring buffer;
	TCHAR tmp[1024];
	std::wstring command, url;

	std::list<StringMapElement *>::iterator i;

	buffer = msg;
	std::wstring::size_type pos0 = 0, pos1;
	std::wstring::size_type npos = -1;
	
	// take care of all the http://
	while(1){

		pos0 = buffer.find(L"http://",pos0);

		if(pos0!=npos){

			// only replace if at the beginning or there is leading whitespace
			if(pos0==0 || (pos0>0 && buffer[pos0-1]==L' ')){
				// now step until we find whitespace
				for(pos1=pos0;pos1<buffer.size();pos1++){
					if(buffer[pos1]==L' ' || buffer[pos1]==L'\n'){
						break;
					}
				}
				// insert the html
				url = buffer.substr(pos0,pos1-pos0);
				_stprintf(tmp,L"<a href=\"%s\" target=\"_blank\">%s</a>",url.data(),url.data());
				command = tmp;
				buffer.replace(pos0,pos1-pos0,command);
				pos0 += command.size();
			} else
				pos0 += 7;
		} else
			break;
	}

	// next the www.
	pos0 = 0;
	while(1){

		pos0 = buffer.find(L"www.",pos0);

		if(pos0!=npos){

			// only replace if at the beginning or there is leading whitespace
			if(pos0==0 || (pos0>0 && buffer[pos0-1]==L' ')){
				// now step until we find whitespace
				for(pos1=pos0;pos1<buffer.size();pos1++){
					if(buffer[pos1]==L' ' || buffer[pos1]==L'\n'){
						break;
					}
				}
				// insert the html
				url = buffer.substr(pos0,pos1-pos0);
				_stprintf(tmp,L"<a href=\"http://%s\" target=\"_blank\">%s</a>",url.data(),url.data());
				command = tmp;
				buffer.replace(pos0,pos1-pos0,command);
				pos0 += command.size();
			} else 
				pos0 += 4;
		} else
			break;
	}

	return buffer.data();
}

const TCHAR * ChatWindow::TranslateMessage(const TCHAR * msg)
{
	return tmap.Map(MakeLinksClickable(msg));
}

ChatWindow::ChatWindow(int id, const TCHAR * r)
{
	recipient = r;
	recipientId = id;
	padding = 5;
}

ChatWindow::~ChatWindow(void)
{

}

static float RandomJitter(){
	return 2*((rand()/(float)RAND_MAX)-0.5);
}

int ChatWindow::Create(HWND parent)
{
	Load("chatwindow");

	// jitter the starting position a bit
	location.X += 25*RandomJitter();
	location.Y += 25*RandomJitter();

	title = env.GetWideString("chatwindow","title",L"ChatWindow");
	title += L": ";
	title += recipient;
	titlebar.Load("chatwindow::titlebar");
	titlebar.title = title;

	MyFormat = env.GetWideString("chatwindow","MyFormat",L"%s: %s<br>");
	FriendFormat = env.GetWideString("chatwindow","FriendFormat",L"%s: %s<br>");
	SystemFormat = env.GetWideString("chatwindow","SystemFormat",L"%s<br>");

	if(SkinnableFrame::Create(parent)){
		padding = resize.size.Width;
		// the history window
		history.Load("chatwindow::history");
		history.scrollbar.Load("chatwindow::scrollbar");
		history.location = Point(padding,padding+titlebar.size.Height);
		history.size = Size(size.Width-padding*2,size.Height-padding*2-100-titlebar.size.Height);
		//history.Create(hWnd,ES_LEFT|ES_MULTILINE|ES_AUTOVSCROLL|ES_READONLY);

		InitWebCtrl();

		TCHAR buffer[1024], dir[1024];
		GetCurrentDirectory(1023,dir);

		_stprintf(buffer,L"about:blank");

		hBrowser = CreateWindow(
						WC_WEBCTRL,
						buffer,
						WS_CHILD | WS_VISIBLE,
						history.location.X, history.location.Y,
						history.size.Width, history.size.Height,
						hWnd,
						(HMENU) NULL,
						env.hInstance,
						NULL );

		// the msg window
		msg.Load("chatwindow::message");
		msg.scrollbar.Load("chatwindow::scrollbar");
		msg.location = Point(padding,size.Height-100);
		msg.size = Size(size.Width-2*padding,100-padding);
		msg.Create(hWnd,ES_LEFT|ES_MULTILINE|ES_AUTOVSCROLL);
		msg.SetMsgOnCarriageReturn(hWnd,WM_CHAR,(WPARAM)0x0D,(LPARAM)msg.hWnd);

		_stprintf(buffer,L"<base href=\"file:///%s/\">\n",dir);
		SafeSendMessage(hBrowser,WC_APPEND,0,(LPARAM)buffer);

		std::wstring htmlbase = env.GetWideString("chatwindow","htmlbase",L"<html><body>");
		SafeSendMessage(hBrowser,WC_APPEND,0,(LPARAM)htmlbase.data());

		AddCustomNotification(bcUser);

		msg.SetText(L"");
		return 1;
	} else
		return 0;
}

void ChatWindow::OnCarriageReturn(HWND h)
{
	if(h==msg.hWnd){

		if(theApp.user.Away){
			// set to not away anymore
			theApp.SetAwayStatus(0);
		}

		std::wstring message;
		msg.GetText(message);
		msg.SetText(_T(""));
		message.erase(message.end()-2,message.end());
		int result = rpc.SendInstantMessage(recipientId,message.data());

		if(result==bsOk)
			MyMessage(message.data());
		else if(result==bsRecipientNotLoggedOn){
			TCHAR buffer[1000];
			_stprintf(buffer,L"%s is not logged on and thus did not receive your message.\n",recipient.data());
			SystemMessage(buffer);
		} else if(result==bsRecipientIsAway){
			TCHAR buffer[1000];
			_stprintf(buffer,L"%s is away and thus did not receive your message.\n",recipient.data());
			SystemMessage(buffer);			
		} else {
			MyMessage(message.data());
			SystemMessage(L"Failed to send message.");
			print(L"ChatWindow: Failed to send message to %s\n",recipient.data());
		}

	}
}

void ChatWindow::OnSize(int cx, int cy)
{
	SkinnableFrame::OnSize(cx,cy);
	history.SetSize(size.Width-2*padding,size.Height-2*padding-100-titlebar.size.Height);
	SetWindowPos(hBrowser,NULL,0,0,history.size.Width,history.size.Height,SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
	msg.SetLocation(padding,size.Height-100);
	msg.SetSize(size.Width-2*padding,100-padding);
}

void ChatWindow::OnClose()
{
	theApp.CloseChatWindow(recipientId);
}

static TCHAR xxx[10000];

void ChatWindow::FriendMessage(const TCHAR * username, const TCHAR * msg)
{
	_stprintf(xxx,FriendFormat.data(),username,TranslateMessage(msg));
	SafeSendMessage(hBrowser,WC_APPEND,0,(LPARAM)xxx);
	SafeSendMessage(hBrowser,WC_SCROLL,-1000000,1000000);
}

void ChatWindow::MyMessage(const TCHAR * msg)
{
	_stprintf(xxx,MyFormat.data(),(TCHAR*)theApp.user.UserLogin,TranslateMessage(msg));
	SafeSendMessage(hBrowser,WC_APPEND,0,(LPARAM)xxx);
	SafeSendMessage(hBrowser,WC_SCROLL,-1000000,1000000);
}

void ChatWindow::SystemMessage(const TCHAR * msg)
{
	_stprintf(xxx,SystemFormat.data(),TranslateMessage(msg));
	SafeSendMessage(hBrowser,WC_APPEND,0,(LPARAM)xxx);
	SafeSendMessage(hBrowser,WC_SCROLL,-1000000,1000000);
}

void ChatWindow::OnCustomNotify(int id, Notification& n)
{
	TCHAR buffer[1024];
	COleDateTime now = COleDateTime::GetCurrentTime();

	switch(id){
	case bcUser:
		if(n.param[0]==recipientId){
			std::wstring username;
			db.GetCachedUsername(n.param[0],username);
			switch(n.reason){
			case bcLogOn:
				_stprintf(buffer,L"%s logged on at %s.",username.data(),now.Format(theApp.DateFormat));
				SystemMessage(buffer);
				break;
			case bcLogOff:
				_stprintf(buffer,L"%s logged off at %s.",username.data(),now.Format(theApp.DateFormat));
				SystemMessage(buffer);
				break;
			}
		}	
		break;
	}
}