/***************************************************************************
 *   Copyright (C) 2005 by yunfan                                          *
 *   yunfan_zg@163.com                                                     *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
  
#include "evachatwindow.h"
#include "evasmileypopup.h"
#include "evafontselecter.h"

#include "evaresource.h"
#include "evafriendlist.h"
#include "evasmileypopup.h"
#include "evatextedit.h"
#include "evahtmlparser.h"
#include "evachatview.h"
#include "evaipseeker.h"

#include <qtextcodec.h>
#include <qrect.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qiconset.h>
#include <qpixmap.h>
#include <qhostaddress.h>
#include <qevent.h>
#include <qpushbutton.h>
#include <qtoolbutton.h>
#include <qlineedit.h>
#include <qpopupmenu.h>
#include <qmessagebox.h>
#include <qtooltip.h>
#include <qregexp.h>
#include <klocale.h>
#include <kurl.h>
#include <kapplication.h>

#ifndef QQ_MSG_IM_MAX
#define QQ_MSG_IM_MAX 1500
#endif

int EvaChatWindow::myQQ=0;
QString EvaChatWindow::myName ="";
EvaImageResource *EvaChatWindow::images = NULL;
bool EvaChatWindow::isSentByEnter = false;

std::list<QString> EvaChatWindow::quickList;
	
EvaChatWindow::EvaChatWindow(const QQFriend * frd, QWidget* parent, const char* name, WFlags fl)
	: EvaChatUIBase(parent, name, fl), smileyPopup(NULL), fontSelecter(NULL), quickMenu(NULL),
	fontColor(Qt::black), fontSize(9)
{
	buddy = new QQFriend(*frd);
	codec = QTextCodec::codecForName("GB18030");
	initObjects();
	initInformation();
	initConnection();
	graphicChanged();
}

EvaChatWindow::~EvaChatWindow()
{
	delete buddy;
}

void EvaChatWindow::setupImages(EvaImageResource *res)
{
	if(!res) return;
	images = res;
}

void EvaChatWindow::setQuickReplyMessages(const std::list<QString> &list) 
{ 
	quickList = list; 
}

const int EvaChatWindow::getBuddyQQ()
{
	return buddy->getQQ();
}

void EvaChatWindow::graphicChanged()
{
	kteInput->mimeSourceFactory()->setFilePath(images->getSmileyPath());
	
	smileyPopup->setupSmiley(images);
	
	tbSmiley->setIconSet(*(images->getIcon("SMILEY")));
	tbFont->setIconSet(*(images->getIcon("FONT")));
	tbB->setIconSet(*(images->getIcon("FONT_B")));
	tbU->setIconSet(*(images->getIcon("FONT_U")));
	tbI->setIconSet(*(images->getIcon("FONT_I")));
	tbQuickReply->setIconSet(*(images->getIcon("QUICK_REPLY")));
	tbHideShows->setIconSet(*(images->getIcon("SHOW_PORTRAIT")));
	slotBuddyQQShowReady(getBuddyQQ());
	slotMyQQShowReady();
}

void EvaChatWindow::initObjects()
{
	fontSelecter = new EvaFontSelecter(this);
	fontSelecter->setColor(Qt::black);
	if(smileyPopup) delete smileyPopup;
	smileyPopup = new EvaSmileyPopup();	
	
	quickMenu = new QPopupMenu(tbQuickReply);
	if(quickList.size()){	
		std::list<QString>::iterator iter;
		int index = 0;
		for(iter=quickList.begin(); iter!=quickList.end(); ++iter)
			quickMenu->insertItem(*iter, index++);
		tbQuickReply->setPopup(quickMenu);
		tbQuickReply->setPopupDelay(10);
		QObject::connect(quickMenu, SIGNAL(activated(int)), this,  SLOT(slotQuickReplyActivated(int)));
	}
	
	sendKey = new QPopupMenu();
	sendKey->setCheckable(true);
	sendKey->insertItem(i18n("Press \"Enter\" to Send"),this,SLOT(setEnterSend()),SHIFT+ALT+Key_Enter,1);  
	sendKey->insertItem(i18n("Press \"Ctrl+Enter\" to Send"),this, SLOT(setCtrlEnterSend()),SHIFT+CTRL+ALT+Key_Enter,2);
	if(isSentByEnter)
		sendKey->setItemChecked(1,true);
	else
		sendKey->setItemChecked(2,true);
	pbSendKey->setPopup(sendKey); 
	kteInput->setEnterSendEnabled(isSentByEnter);
}

void EvaChatWindow::initInformation()
{
	if(!buddy) return;
	QString nick = codec->toUnicode(buddy->getNick().c_str());
	QString title = QString(i18n("Chatting with %1")).arg(nick);
	setCaption(title);
	QString status =i18n("(offline)");
	QIconSet face;
	int faceId = buddy->getFace();
	QPixmap *faceOnPic=NULL, *faceOffPic=NULL;
	if(buddy->hasUserHead()){
		faceOnPic = images->getUserHeadPixmap(buddy->getQQ());
		faceOffPic = images->getUserHeadPixmap(buddy->getQQ(), true); // true means grayscale true
	}
	if(!faceOnPic || !faceOffPic){
		faceOnPic = images->getFace(images->getFaceFileIndex(faceId));
		faceOffPic = images->getFace(images->getFaceFileIndex(faceId), false); // false means on-line off
	}
	setIcon(*faceOnPic);
	
	face.setPixmap(*faceOffPic,QIconSet::Large);
	tbBuddy->setIconSet(face);
	switch(buddy->getStatus()){
	case 10:
		status = i18n("(online)");
		face.setPixmap(*faceOnPic,QIconSet::Large);
		tbBuddy->setIconSet(face);
		break;
	case 20:
		//status = i18n("(offline)");
		//face.setPixmap(*(images->getFace(images->getFaceFileIndex(faceId), false)),QIconSet::Large);
		//tbBuddy->setIconSet(face);
		break;
	case 30:{
		status = i18n("(leave)");
		QPixmap pixleave(*faceOnPic);
		QPixmap pixna(*(images->getIcon("NA")));
		copyBlt(&pixleave, pixleave.width()-pixna.width(),pixleave.height()-pixna.height(), 
			&pixna,0,0, pixna.width(), pixna.height());
		face.setPixmap(pixleave, QIconSet::Large);
		tbBuddy->setIconSet(face);
		}
		break;
	case 40:
		status = i18n("(invisible)");
		face.setPixmap(*faceOffPic, QIconSet::Large);
		tbBuddy->setIconSet(face);
		break;
	}
	tbBuddy->setTextLabel(nick);
	QToolTip::add(tbBuddy, nick + "("+QString::number(buddy->getQQ()) +") " + status);
	
	QString ip = QHostAddress(buddy->getIP()).toString();
	EvaIPSeeker ipAddr(EvaGlobal::getDirPath().latin1());
	QString addr = codec->toUnicode(ipAddr.getIPLocation(ip.latin1()).c_str());
	leIP->setText(addr);
	
	QString sig = codec->toUnicode(buddy->getSignature().c_str());
	lblSignature->setText("  " + sig);
	
	QString port = QString::number(((int)(buddy->getPort()))==-1?0:(unsigned int)(buddy->getPort()));
	QToolTip::add(leIP, ip + " : " + port);
	
}

void EvaChatWindow::initConnection()
{
	if(smileyPopup)
		connect(smileyPopup, SIGNAL(smileySelected(Q_UINT8)), this, SLOT(slotSmileySelected(Q_UINT8)));
	QObject::connect(tbBuddy, SIGNAL(clicked()), this, SLOT(slotTbBuddyClick()));
	QObject::connect(tbSmiley, SIGNAL(clicked()), this, SLOT(slotSmileyClick()));
	QObject::connect(tbFont, SIGNAL(clicked()), this, SLOT(slotFontClick()));
	QObject::connect(tbQuickReply, SIGNAL(clicked()), this, SLOT(slotQuickReplyClick()));
	QObject::connect(tbHideShows, SIGNAL(clicked()), this, SLOT(slotHideShowsClick()));
	QObject::connect(pbHistory, SIGNAL(clicked()), this, SLOT(slotHistoryClick()));
	QObject::connect(pbSendKey, SIGNAL(clicked()), this, SLOT(slotSendKeyClick()));
	QObject::connect(pbSend, SIGNAL(clicked()), this, SLOT(slotSend()));
	QObject::connect(tbShowBuddy, SIGNAL(clicked()), this, SLOT(slotTbShowBuddyClick()));
	QObject::connect(tbShowMe, SIGNAL(clicked()), this, SLOT(slotTbShowMeClick()));
	QObject::connect(kteInput, SIGNAL(keyPressed(QKeyEvent *)), this, SLOT(slotInputKeyPress(QKeyEvent *)));
	
	QObject::connect(fontSelecter, SIGNAL(fontChanged(QColor, int)), this, SLOT(slotFontChanged(QColor, int)));
	QObject::connect(pbClose, SIGNAL(clicked()), this, SLOT(slotPbCloseClick()));
}

void EvaChatWindow::displaySendingMessage()
{
	EvaHtmlParser parser;
	parser.setAbsImagePath(images->getSmileyPath());
	QString text = kteInput->text();
	parser.convertToPlainTxt(text);
	parser.convertToHtml(text,true, true);
	
	chatDisplay->append( myName, sendtime, Qt::blue, true, fontColor, (char)fontSize, 
				tbU->isOn(), tbI->isOn(), tbB->isOn(), text);
	kteInput->setText("");
}

void EvaChatWindow::slotReceivedMessage(int sender, bool isNormal, QString message, QDateTime time, const char size, 
					const bool u, const bool i, const bool b, 
					const char blue, const char green, const char red)
{
	if(sender != buddy->getQQ()) return;
	QString nick = codec->toUnicode(buddy->getNick().c_str());
	EvaHtmlParser parser;
	parser.setAbsImagePath(images->getSmileyPath());
	parser.convertToHtml(message, true, true);
	chatDisplay->append(nick, time, Qt::red, isNormal, QColor((Q_UINT8)red, (Q_UINT8)green,(Q_UINT8)blue), size, u, i, b, message);
}

void EvaChatWindow::slotAddMessage(int , QString sNick, int , QString , bool isNormal, 
				QString message, QDateTime time, const char , 
				const bool , const bool , const bool , 
				const char , const char , const char )
{	
	EvaHtmlParser parser;
	parser.convertToHtml(message, false);
	QString msg = sNick + (isNormal?(""):i18n("(Auto-Reply)")) + " " + time.toString("yyyy-MM-dd hh:mm:ss") + "<br />" + message;
	kteInput->append(msg);
}

void EvaChatWindow::slotSendResult(bool ok)
{
	if(!ok) {
		QMessageBox::information(0, i18n("Message"), i18n("message sent failed"));
		return;
	}
}

void EvaChatWindow::slotBuddyQQShowReady(const int id)
{
	if(id!= getBuddyQQ()) return;
	QPixmap *pix = images->getQQShow(id);
	if(pix) tbShowBuddy->setIconSet(*pix);
}

void EvaChatWindow::slotMyQQShowReady()
{
	QPixmap *pix = images->getQQShow(myQQ);
	if(pix) tbShowMe->setIconSet(*pix);
}

void EvaChatWindow::slotSmileySelected(Q_UINT8 fid)
{
    QString smiley = "<img src=\"" + QString::number(fid) + ".gif\">";
	
    int para;
    int index;
    QFont saveFont = kteInput->font();
    QColor saveColor = kteInput->color();
    // determine the current position of the cursor
    kteInput->insert("\255", false, true, true);	
    kteInput->getCursorPosition(&para,&index);
    QString txt = kteInput->text();
    txt.replace(QRegExp("\255"),smiley);
    kteInput->setText(txt);
    kteInput->setCursorPosition(para, index);
    kteInput->setCurrentFont(saveFont);
    kteInput->setColor(saveColor);
}

void EvaChatWindow::slotTbBuddyClick()
{
	emit requestDetails(buddy->getQQ());
}

void EvaChatWindow::slotSmileyClick()
{
	if(smileyPopup){
		QPoint p = kteInput->mapToGlobal(QPoint(0,0));
		smileyPopup->setGeometry(p.x() + tbSmiley->x() , p.y(), smileyPopup->width(), smileyPopup->height());
		smileyPopup->show();
	}	
}

void EvaChatWindow::slotFontClick()
{
	if(!fontSelecter) return;
	if(fontSelecter->isVisible()) 
		fontSelecter->hide();
	else{
		QPoint p = kteInput->mapToGlobal(QPoint(0,0));
		fontSelecter->setGeometry(p.x() + tbFont->x() , p.y(), fontSelecter->width(), fontSelecter->height());	
		fontSelecter->show();
	}
}

void EvaChatWindow::slotQuickReplyClick()
{
	//tbQuickReply->openPopup();
	//quickMenu->exec();
}

void EvaChatWindow::slotQuickReplyActivated(int id)
{
	std::list<QString>::iterator iter;
	int index = 0;
	for(iter=quickList.begin(); iter!=quickList.end(); ++iter){
		if(index == id) break;	
		index++;
	}
	QString message = *iter;
	EvaHtmlParser parser;
	parser.convertToHtml(message, false);
	kteInput->append(message);	
	slotSend();
}

void EvaChatWindow::slotHideShowsClick()
{
	if(lblBuddyShow->isVisible()){
		lblBuddyShow->hide();
		tbShowBuddy->hide();
		lblMeShow->hide();
		tbShowMe->hide();
		EvaChatUIBaseLayout->removeItem(layout19);
		tbHideShows->setIconSet(*(images->getIcon("SHOW_PORTRAIT")));
	}else{
		lblBuddyShow->show();
		tbShowBuddy->show();
		lblMeShow->show();
		tbShowMe->show();
		EvaChatUIBaseLayout->addLayout(layout19);
		tbHideShows->setIconSet(*(images->getIcon("HIDE_PORTRAIT")));
	}
}

void EvaChatWindow::slotHistoryClick()
{
	emit requestHistory(getBuddyQQ());
}

void EvaChatWindow::slotSendKeyClick()
{
}

void EvaChatWindow::slotSend()
{
	QString msg = kteInput->text();
	EvaHtmlParser parser;
	parser.convertToPlainTxt(msg);
	if(msg == ""){
		QMessageBox::information(0, i18n("Message"), i18n("Cannot send empty message."));
		return;
	}
	if(strlen(msg.ascii()) > QQ_MSG_IM_MAX){
		QMessageBox::information(0, i18n("Message"), i18n("Message is too long, cannot send."));
		return;
	}	
	sendtime = QDateTime::currentDateTime(Qt::LocalTime);
	displaySendingMessage();
	emit sendMessage(getBuddyQQ(), true, msg, (char)fontSize, tbU->isOn(), tbI->isOn(), tbB->isOn(),
			(char)(fontColor.blue()) , (char)(fontColor.green()), (char)(fontColor.red()));	

}

void EvaChatWindow::slotTbShowBuddyClick()
{
	emit requestBuddyQQShow(getBuddyQQ());
}

void EvaChatWindow::slotTbShowMeClick()
{
	emit requestMyQQShow();
}

void EvaChatWindow::slotInputKeyPress(QKeyEvent *e)
{
	if(isSentByEnter && ((e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return) ) && (e->state() == Qt::NoButton) ){
		e->accept();
		slotSend();
	}else{
		if( !(isSentByEnter) &&
			( (e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return) ) && 
			( (e->state() & Qt::ControlButton)==Qt::ControlButton)    ){
		e->accept();
		slotSend();
		}
	}
}

void EvaChatWindow::slotFontChanged(QColor color, int size)
{
	fontColor = color;
	fontSize = size;
}

void EvaChatWindow::setEnterSend()
{
	isSentByEnter = true;
	sendKey->setItemChecked(1,true);
	sendKey->setItemChecked(2,false);
	kteInput->setEnterSendEnabled(isSentByEnter);
}

void EvaChatWindow::setCtrlEnterSend()
{
	isSentByEnter = false;
	sendKey->setItemChecked(1,false);
	sendKey->setItemChecked(2,true);
	kteInput->setEnterSendEnabled(isSentByEnter);
}

void EvaChatWindow::slotPbCloseClick()
{
	close();
}

