//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// ChatSelector.cpp : implementation file
//

#include "stdafx.h"
#include "emule.h"
#include "ChatSelector.h"
#include "packets.h"
#include "otherfunctions.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


CChatItem::CChatItem(){
	log = 0;
	messagepending = 0;
	notify = false;
}

// CChatSelector

IMPLEMENT_DYNAMIC(CChatSelector, CTabCtrl)
CChatSelector::CChatSelector()
{
	m_pCloseBtn = NULL;
	m_pMessageBox = NULL;
	m_pSendBtn = NULL;
	lastemptyicon=false;
}

CChatSelector::~CChatSelector(){
	//KillTimer();
}


BEGIN_MESSAGE_MAP(CChatSelector, CTabCtrl)
	ON_WM_TIMER()
	ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnTcnSelchangeChatsel)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_CCLOSE, OnBnClickedCclose)
	ON_BN_CLICKED(IDC_CSEND, OnBnClickedCsend)
END_MESSAGE_MAP()



// CChatSelector message handlers
void CChatSelector::Init()
{
	CRect rect;
	GetClientRect(&rect);
	AdjustRect(FALSE, rect);
	
	CRect rClose;
	m_pCloseBtn = GetParent()->GetDlgItem(IDC_CCLOSE);
	m_pCloseBtn->SetParent(this);
	m_pCloseBtn->GetWindowRect(&rClose);
	m_pCloseBtn->SetWindowPos(NULL, rect.right-7-rClose.Width(), rect.bottom-7-rClose.Height(),
							  rClose.Width(), rClose.Height(), SWP_NOZORDER);
	CRect rSend;
	m_pSendBtn = GetParent()->GetDlgItem(IDC_CSEND);
	m_pSendBtn->SetParent(this);
	m_pSendBtn->GetWindowRect(&rSend);
	m_pSendBtn->SetWindowPos(NULL, rect.right-7-rClose.Width()-7-rSend.Width(), rect.bottom-7-rSend.Height(),
							 rSend.Width(), rSend.Height(), SWP_NOZORDER);
	
	CRect rMessage;
	m_pMessageBox = GetParent()->GetDlgItem(IDC_CMESSAGE);
	m_pMessageBox->SetParent(this);
	m_pMessageBox->GetWindowRect(&rMessage);
	m_pMessageBox->SetWindowPos(NULL, rect.left+7, rect.bottom-9-rMessage.Height(), 
								rect.right-7-rClose.Width()-7-rSend.Width()-21, 
								rMessage.Height(), SWP_NOZORDER);

	int iTop = rClose.Height() > rSend.Height() ? rClose.Height() : rSend.Height();
	if(iTop < rMessage.Height())
		iTop = rMessage.Height();
	
	CRect rChatOut = rect;
	rChatOut.top += 7;
	rChatOut.left += 7;
	rChatOut.right -= 7;
	rChatOut.bottom -= iTop + 17;

	ModifyStyle(0, WS_CLIPCHILDREN);
	chatout.CreateEx(NULL/*WS_EX_STATICEDGE*/,0,"ChatWnd",WS_VISIBLE | WS_CHILD | WS_BORDER | HTC_WORDWRAP |HTC_AUTO_SCROLL_BARS | HTC_UNDERLINE_HOVER,rChatOut,this,0);
	chatout.AppendHyperLink(CString("eMule "),0,CString("http://www.emule-project.net"),0,0);
	chatout.AppendText(CString(" Version ")+ CString(CURRENT_VERSION_LONG)+ CString(" - ")+GetResString(IDS_CHAT_WELCOME));

	imagelist.Create(16,16,theApp.m_iDfltImageListColorFlags | ILC_MASK,0,10);
	imagelist.Add(theApp.LoadIcon(IDI_CHAT));
	imagelist.Add(theApp.LoadIcon(IDI_MESSAGE));		
	imagelist.Add(theApp.LoadIcon(IDI_MPENDING));
	SetImageList(&imagelist);

	m_Timer = SetTimer(20,1500,0);
}

CChatItem* CChatSelector::StartSession(CUpDownClient* client, bool show){
	if (GetTabByClient(client) != 0xFFFF){
		if (show){
			SetCurSel(GetTabByClient(client));
			chatout.SetHyperText(GetItemByClient(client)->log);
		}
		return 0;
	}

	CChatItem* chatitem = new CChatItem();
	chatitem->client = client;
	chatitem->log = new CPreparedHyperText();

	CTime theTime = CTime::GetCurrentTime();
	CString sessions = GetResString(IDS_CHAT_START)+CString(client->GetUserName()) + " - "+theTime.Format("%c")+ "\n";
	chatitem->log->AppendKeyWord(sessions,RGB(255,0,0));
	client->SetChatState(MS_CHATTING);

	CString name;
	if (client->GetUserName()!=NULL) name=client->GetUserName(); else name.Format("(%s)",GetResString(IDS_UNKNOWN));

	TCITEM newitem;
	newitem.mask = TCIF_PARAM|TCIF_TEXT|TCIF_IMAGE;
	newitem.lParam = (LPARAM)chatitem;
	newitem.pszText = name.GetBuffer();
	newitem.cchTextMax = name.GetLength()+1;
	newitem.iImage = 0;
	uint16 itemnr = InsertItem(GetItemCount(),&newitem);
	if (show){
		SetCurSel(itemnr);
		chatout.SetHyperText(chatitem->log);
	}
	return chatitem;
}

uint16 CChatSelector::GetTabByClient(CUpDownClient* client){
	for (int i = 0; i < GetItemCount();i++){
		TCITEM cur_item;
		cur_item.mask = TCIF_PARAM;
		GetItem(i,&cur_item);
		if (((CChatItem*)cur_item.lParam)->client == client)
			return i;
	}
	return -1;
}

CChatItem* CChatSelector::GetItemByClient(CUpDownClient* client){
	for (int i = 0; i < GetItemCount();i++){
		TCITEM cur_item;
		cur_item.mask = TCIF_PARAM;
		GetItem(i,&cur_item);
		if (((CChatItem*)cur_item.lParam)->client == client)
			return (CChatItem*)cur_item.lParam;
	}
	return 0;
}

void CChatSelector::ProcessMessage(CUpDownClient* sender, char* message){
	CString Cmessage=CString(message).MakeLower();
	CString resToken;
	int curPos=0;
	resToken= theApp.glob_prefs->GetMessageFilter().Tokenize("|",curPos);
	while (resToken != "")
	{
		if (Cmessage.Find(resToken.MakeLower())>-1) {return;}
		resToken= theApp.glob_prefs->GetMessageFilter().Tokenize("|",curPos);
	};


	// continue
	CChatItem* ci = GetItemByClient(sender);
	bool isNewChatWindow = false;
	if (!ci) {
		if (GetItemCount()>=theApp.glob_prefs->GetMsgSessionsMax()) return;
		ci = StartSession(sender,false);
		isNewChatWindow = true; 
	}
	ci->log->AppendKeyWord(CString(sender->GetUserName()),RGB(50,200,250));
	ci->log->AppendText(CString(": "));
	ci->log->AppendText(CString(message)+ CString("\n"));
	if (GetCurSel() == GetTabByClient(sender) && GetParent()->IsWindowVisible())
		chatout.SetHyperText(ci->log);
	else { 
		ci->notify = true;
		//START - enkeyDEV(kei-kun) -TaskbarNotifier- 	
        if (isNewChatWindow || theApp.glob_prefs->GetNotifierPopsEveryChatMsg())  //<<-31/10/2002 (kei-kun)
                theApp.emuledlg->ShowNotifier(GetResString(IDS_TBN_NEWCHATMSG)+CString(" ")+CString(sender->GetUserName()) + CString(":'") + CString(message)+ CString("'\n"), TBN_CHAT);

		isNewChatWindow = false;
		//END - enkeyDEV(kei-kun) -TaskbarNotifier-
	}
}

bool CChatSelector::SendMessage(char* message){
	sint16 to = GetCurSel();
	if (to == (-1)){
		return false;
	}
	TCITEM item;
	item.mask = TCIF_PARAM;
	GetItem(to,&item);
	CChatItem* ci = (CChatItem*)item.lParam;
	if (ci->client->GetChatState() == MS_CONNECTING){
		return false;
	}
	if (ci->client->socket && ci->client->socket->IsConnected()){
		uint16 mlen = (uint16)strlen(message);
		Packet* packet = new Packet(OP_MESSAGE,mlen+2);
		memcpy(packet->pBuffer,&mlen,2);
		memcpy(packet->pBuffer+2,message,mlen);
		theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
		ci->client->socket->SendPacket(packet,true,true);
		ci->log->AppendKeyWord(CString(theApp.glob_prefs->GetUserNick()),RGB(1,180,20));
		ci->log->AppendText(CString(": "));
		ci->log->AppendText(CString(message)+CString("\n"));
		chatout.UpdateSize(true);
	}
	else{
		ci->log->AppendKeyWord(CString("*** ")+GetResString(IDS_CONNECTING),RGB(255,0,0));
		ci->messagepending = nstrdup(message);
		ci->client->SetChatState(MS_CONNECTING);
		ci->client->TryToConnect();
	}
	if (chatout.GetHyperText() == ci->log)
		chatout.UpdateSize(true);
	return true;
}

void CChatSelector::ConnectingResult(CUpDownClient* sender,bool success){
	CChatItem* ci = GetItemByClient(sender);
	if (!ci)
		return;
	ci->client->SetChatState(MS_CHATTING);
	if (!success){
		if (ci->messagepending){
			ci->log->AppendKeyWord(CString(" ")+GetResString(IDS_FAILED) +CString("\n"),RGB(255,0,0));
			delete[] ci->messagepending;
		}
		else
			ci->log->AppendKeyWord(GetResString(IDS_CHATDISCONNECTED) +CString("\n"),RGB(255,0,0));
		ci->messagepending = 0;
	}
	else{
		ci->log->AppendKeyWord(CString(" ok\n"),RGB(255,0,0));
		uint16 mlen = (uint16)strlen(ci->messagepending);
		Packet* packet = new Packet(OP_MESSAGE,mlen+2);
		memcpy(packet->pBuffer,&mlen,2);
		memcpy(packet->pBuffer+2,ci->messagepending,mlen);
		theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
		ci->client->socket->SendPacket(packet,true,true);
		ci->log->AppendKeyWord(CString(theApp.glob_prefs->GetUserNick()),RGB(1,180,20));
		ci->log->AppendText(CString(": "));
		ci->log->AppendText(CString(ci->messagepending)+CString("\n"));
		delete[] ci->messagepending;
		ci->messagepending = 0;
	}
	if (chatout.GetHyperText() == ci->log)
		chatout.UpdateSize(true);
}

void CChatSelector::DeleteAllItems(){
	for (int i = 0; i < GetItemCount();i++){
		TCITEM cur_item;
		cur_item.mask = TCIF_PARAM;
		GetItem(i,&cur_item);
		delete (CChatItem*)cur_item.lParam;
	}
}

void CChatSelector::OnTimer(UINT_PTR nIDEvent){
	blinkstate = !blinkstate;
	bool globalnotify = false;
	for (int i = 0; i < GetItemCount();i++){
		TCITEM cur_item;
		cur_item.mask = TCIF_PARAM;
		GetItem(i,&cur_item);
		cur_item.mask = TCIF_IMAGE;
		if (((CChatItem*)cur_item.lParam)->notify){
			cur_item.iImage = (blinkstate)? 1:2;
			SetItem(i,&cur_item);
			globalnotify = true;
		}
		else if (cur_item.iImage != 0){
			cur_item.iImage = 0;
			SetItem(i,&cur_item);
		}
	}
	if (globalnotify) {
		theApp.emuledlg->ShowMessageState(((blinkstate)? 1:2));
		lastemptyicon=false;
	}
	else if (!lastemptyicon) {theApp.emuledlg->ShowMessageState(0); lastemptyicon=true;}
}


void CChatSelector::ShowChat(){
	if (GetCurSel() == (-1))
		return;
	TCITEM cur_item;
	cur_item.mask = TCIF_PARAM;
	GetItem(GetCurSel(),&cur_item);
	CChatItem* ci = (CChatItem*)cur_item.lParam;
	chatout.SetHyperText(ci->log);
	ci->notify = false;
}


void CChatSelector::OnTcnSelchangeChatsel(NMHDR *pNMHDR, LRESULT *pResult){
	ShowChat();
	*pResult = 0;
}

INT	CChatSelector::InsertItem(int nItem,TCITEM* pTabCtrlItem){
	if (!GetItemCount()){
		WINDOWPLACEMENT wp;
		chatout.GetWindowPlacement(&wp);
		wp.rcNormalPosition.top +=20;
		chatout.SetWindowPlacement(&wp);
	}
	int result = CTabCtrl::InsertItem(nItem,pTabCtrlItem);
	RedrawWindow();
	return result;
}

BOOL CChatSelector::DeleteItem(int nItem){
	CTabCtrl::DeleteItem(nItem);
	if (!GetItemCount()){
		WINDOWPLACEMENT wp;
		chatout.GetWindowPlacement(&wp);
		wp.rcNormalPosition.top -=20;
		chatout.SetWindowPlacement(&wp);
	}
	RedrawWindow();
	return true;
}

void CChatSelector::EndSession(CUpDownClient* client){
	sint16 usedtab;
	if (client){
		usedtab = GetTabByClient(client);
	}
	else{
		usedtab = GetCurSel();
	}
	if (usedtab == (-1))
		return;
	TCITEM item;
	item.mask = TCIF_PARAM;
	GetItem(usedtab,&item);
	CChatItem* ci = (CChatItem*)item.lParam;
	ci->client->SetChatState(MS_NONE);
	
	DeleteItem(usedtab);
	if (chatout.GetHyperText() == ci->log)
		chatout.SetHyperText(0);
	delete ci;
}
void CChatSelector::OnSize(UINT nType, int cx, int cy)
{
	CTabCtrl::OnSize(nType, cx, cy);	

	CRect rect;
	GetClientRect(&rect);
	AdjustRect(FALSE, rect);
		
	CRect rClose;
	m_pCloseBtn->GetWindowRect(&rClose);
	m_pCloseBtn->SetWindowPos(NULL, rect.right-7-rClose.Width(), rect.bottom-7-rClose.Height(),
								rClose.Width(), rClose.Height(), SWP_NOZORDER);
	CRect rSend;
	m_pSendBtn->GetWindowRect(&rSend);
	m_pSendBtn->SetWindowPos(NULL, rect.right-7-rClose.Width()-7-rSend.Width(), rect.bottom-7-rSend.Height(),
								rSend.Width(), rSend.Height(), SWP_NOZORDER);
	
	CRect rMessage;
	m_pMessageBox->GetWindowRect(&rMessage);
	m_pMessageBox->SetWindowPos(NULL, rect.left+7, rect.bottom-9-rMessage.Height(), 
									rect.right-7-rClose.Width()-7-rSend.Width()-21, 
										rMessage.Height(), SWP_NOZORDER);

	int iTop = rClose.Height() > rSend.Height() ? rClose.Height() : rSend.Height();
	if(iTop < rMessage.Height())
		iTop = rMessage.Height();
	
	chatout.SetWindowPos(NULL, rect.left+7, rect.top+7, rect.right-18, rect.Height()-7-iTop-14, SWP_NOZORDER);
}

void CChatSelector::OnBnClickedCclose(){
	EndSession();
}

void CChatSelector::OnBnClickedCsend()
{
	uint16 len = m_pMessageBox->GetWindowTextLength()+2;
	char* messagetosend = new char[len+1];
	m_pMessageBox->GetWindowText(messagetosend,len);
	if(SendMessage(messagetosend))
		m_pMessageBox->SetWindowText("");
	delete[] messagetosend;
}

BOOL CChatSelector::PreTranslateMessage(MSG* pMsg)
{
	if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == 13))
	{
		if (pMsg->hwnd == m_pMessageBox->m_hWnd)
			OnBnClickedCsend();
	}

	return CTabCtrl::PreTranslateMessage(pMsg);
}

void CChatSelector::Localize(void)
{
	if(m_hWnd)
	{
		if(m_pSendBtn)
			m_pSendBtn->SetWindowText(GetResString(IDS_CW_SEND));
		else
			GetParent()->GetDlgItem(IDC_CSEND)->SetWindowText(GetResString(IDS_CW_SEND));
		if(m_pCloseBtn)
			m_pCloseBtn->SetWindowText(GetResString(IDS_CW_CLOSE));
		else
			GetParent()->GetDlgItem(IDC_CCLOSE)->SetWindowText(GetResString(IDS_CW_CLOSE));
	}
}
