/***************************************************************************
 *   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 "evachatwindowmanager.h"
#include "evaresource.h"
#include "evafriendlist.h"
#include "evausersetting.h"
#include "evachatwindow.h"
#include "evaqunchatwindow.h"
#include "evaqunlist.h"
#include "evamain.h"
#include "evauser.h"
#include "evaresource.h"
#include "evaqtutil.h"
#include "evahtmlparser.h"

#include <qmessagebox.h>
#include <qapplication.h>
#include <kwin.h>
#include <klocale.h>

EvaChatWindowManager::EvaChatWindowManager(EvaImageResource *img, EvaUserSetting *setting, QString myNickname, const int id)
{
	EvaChatWindow::setupImages(img);
	EvaChatWindow::myQQ = id;
	EvaChatWindow::myName = myNickname;
	
	EvaQunChatWindow::setupImages(img);
	EvaQunChatWindow::myQQ = id;
	EvaQunChatWindow::myName = myNickname;
	
	userSetting = setting;
	windowList.setAutoDelete(true);
	messageQueue.setAutoDelete(true);
	
	qunWindowList.setAutoDelete(true);
	qunMessageQueue.setAutoDelete(true);
	
}

EvaChatWindowManager::~EvaChatWindowManager()
{
	//closeAllWindows();
}

void EvaChatWindowManager::setMyName(QString myName, const int id)
{
	EvaChatWindow::myQQ = id;
	EvaChatWindow::myName = myName;
	EvaQunChatWindow::myQQ = id;
	EvaQunChatWindow::myName = myName;
}

bool EvaChatWindowManager::isChatWindowExisted(const int id)
{
	EvaChatWindow *win = getWindow(id);
	if(win){
		if(win->isHidden()){
			return false;
		}else{
			return true;
		}
	}else{
		return false;
	}	
}
	
void EvaChatWindowManager::openChatWindow(const QQFriend * frd)
{
	if(!frd) return;
	EvaChatWindow *win = getWindow(frd->getQQ());
	if(win){
		if(win->isHidden()){
			windowList.removeRef(win);
			win = newWindow(frd);
			win->show();
		}else{
			KWin::forceActiveWindow(win->winId());
			return;
		}
	}else{
		win = newWindow(frd);
		win->show();
	}
	
	Message *msg;
	for(uint i = 0; i<messageQueue.count(); i++){
		msg = messageQueue.at(i);
		if(msg->sender == frd->getQQ()){
			win->slotReceivedMessage(msg->sender, msg->isNormal, msg->message, msg->time, msg->size,
						msg->u, msg->i, msg->b, msg->blue, msg->green, msg->red);
			messageQueue.remove(i--);
		}
	}
}

void EvaChatWindowManager::closeAllWindows()
{
	EvaChatWindow *win;
	for(uint i=0; i<windowList.count();i++){
		win = windowList.at(i);
		if(win){
			if(win->isVisible()){
				win->close();
			}
			delete win;
			windowList.remove(i--);
		}
	}
}

std::list<int> EvaChatWindowManager::getMessages()
{
	std::list<int> list;
	for(uint i=0; i<messageQueue.count();i++){
		list.push_back(messageQueue.at(i)->sender);
	}
	return list;
}

void EvaChatWindowManager::graphicChanged()
{
	EvaChatWindow *win;
	for(uint i=0; i<windowList.count();i++){
		win = windowList.at(i);
		if(win->isVisible()){
			win->close();
			windowList.remove(i--);
			continue;
		}
		win->graphicChanged();
	}	
}

void EvaChatWindowManager::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)
{
	EvaChatWindow *win = getWindow(sender);
	if(win && win->isVisible()){
		win->slotReceivedMessage(sender, isNormal, message, time, size, u, i, b, blue, green, red);
		if(!win->isActiveWindow()){
			KWin::demandAttention(win->winId(), true);
		}
		return;
	}
	
	Message *msg = new Message;
	msg->sender = sender;
	msg->isNormal = isNormal;
	msg->message = message;
	msg->time = time;
	msg->size = size;
	msg->u = u;
	msg->i = i;
	msg->b = b;
	msg->blue = blue;
	msg->green = green;
	msg->red = red;
	
	messageQueue.append(msg);
}

void EvaChatWindowManager::slotSendResult(int id, bool ok)
{
	EvaChatWindow *win = getWindow(id);
	if(win && win->isVisible()) {
		win->slotSendResult(ok);
	}else{
		if(!ok)
			QMessageBox::information(0, i18n("Send Message"), QString(i18n("Send message to \"%1\" failed.")).arg(id));
	}
}

void EvaChatWindowManager::slotBuddyQQShowReady(const int id)
{
	EvaChatWindow *win = getWindow(id);
	if(win && win->isVisible())
		win->slotBuddyQQShowReady(id);	
}

void EvaChatWindowManager::slotMyQQShowReady()
{
	for(uint i=0; i<windowList.count();i++){
		if(windowList.at(i)->isVisible())
			windowList.at(i)->slotMyQQShowReady();
	}	
}

EvaChatWindow *EvaChatWindowManager::newWindow(const QQFriend *frd)
{
	EvaChatWindow::setQuickReplyMessages(userSetting->getQuickReplyList());
	EvaChatWindow::isSentByEnter = userSetting->isSendKeyEnterEnabled();
	EvaChatWindow *win = new EvaChatWindow(frd);
	windowList.append(win);
	QObject::connect(win, SIGNAL(requestDetails(const int)), this, SIGNAL(requestDetails(const int)));
	QObject::connect(win, SIGNAL(sendMessage(const int , const bool, QString &, const char , 
		const bool , const bool , const bool , 
		const char, const char , const char)), this, 
		SIGNAL(sendMessage(const int , const bool, QString &, const char, 
		const bool , const bool , const bool , 
		const char , const char, const char)));	
	QObject::connect(win, SIGNAL(requestHistory(const int )), this, SIGNAL(requestHistory(const int )));
	QObject::connect(win, SIGNAL(requestBuddyQQShow(const int)), this, SIGNAL(requestBuddyQQShow(const int)));
	QObject::connect(win, SIGNAL(requestMyQQShow()), this, SIGNAL(requestMyQQShow()));
	return win;
}

EvaChatWindow *EvaChatWindowManager::getWindow(const int id)
{
	for(uint i=0; i<windowList.count();i++){
		if(windowList.at(i)->getBuddyQQ() == id)
			return windowList.at(i);
	}
	return NULL;
}

void EvaChatWindowManager::slotReceivedQunMessage( int qunID, int senderQQ, 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 )
{
	EvaQunChatWindow *win = getQunWindow(qunID);
	if(win && win->isVisible()){
		win->slotReceivedMessage(qunID, senderQQ, message, time, size, u, i, b, blue, green, red);
		if(!win->isActiveWindow()){
			KWin::demandAttention(win->winId(), true);
		}
		return;
	}
	
	QunMessage *msg = new QunMessage;
	msg->qunID = qunID;
	msg->sender = senderQQ;
	msg->message = message;
	msg->time = time;
	msg->size = size;
	msg->u = u;
	msg->i = i;
	msg->b = b;
	msg->blue = blue;
	msg->green = green;
	msg->red = red;
	
	qunMessageQueue.append(msg);
	
	EvaHtmlParser parser;
	QString cachesPath = EvaMain::user->getSetting()->getPictureCacheDir();
	parser.setAbsImagePath(EvaMain::images->getSmileyPath(), cachesPath);
	std::list<CustomizedPic> picList = parser.convertToHtml(message, true, true);
	if(picList.size()) printf("EvaChatWindowManager::slotReceivedQunMessage -- Wow, some pics\n");
	if(picList.size()){
		EvaAskForCustomizedPicEvent *event = new EvaAskForCustomizedPicEvent();
		event->setPicList(picList);
		event->setQunID(qunID);
		QApplication::postEvent((QObject *)EvaMain::picManager, event);
		printf("EvaChatWindowManager::slotReceivedQunMessage -- posted in event loop.\n");
	}
}

void EvaChatWindowManager::slotQunSendResult( int id, bool ok ,QString msg)
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win && win->isVisible()) {
		win->slotSendResult(ok);
	}else{
		if(!ok)
			QMessageBox::information(0, i18n("Send Message Failed"), msg);
	}
}

EvaQunChatWindow * EvaChatWindowManager::getQunWindow( const int id )
{
	for(uint i=0; i<qunWindowList.count();i++){
		if(qunWindowList.at(i)->getQunID() == id)
			return qunWindowList.at(i);
	}
	return NULL;
}

EvaQunChatWindow * EvaChatWindowManager::newQunWindow( Qun * qun )
{
	EvaQunChatWindow::setQuickReplyMessages(userSetting->getQuickReplyList());
	EvaQunChatWindow::isSentByEnter = userSetting->isSendKeyEnterEnabled();
	EvaQunChatWindow *win = new EvaQunChatWindow(qun);
	qunWindowList.append(win);
	QObject::connect(win, SIGNAL(requestQunDetails(const int)), this, SIGNAL(requestQunDetails(const int)));
	QObject::connect(win, SIGNAL(sendQunMessage(const int, QString &, const char , 
			const bool, const bool, const bool, 
			const char, const char, const char)), this, 
		SIGNAL(sendQunMessage(const int, QString &, const char , 
			const bool, const bool, const bool, 
			const char, const char, const char)));	
	QObject::connect(win, SIGNAL(requestHistory(const int )), this, SIGNAL(requestQunHistory(const int )));
	QObject::connect(win, SIGNAL(requestQunOnlineList(const int)), this, SIGNAL(requestQunOnlineList(const int)));
	QObject::connect(win, SIGNAL(requestQunCard(const int, const int)), this, SIGNAL(requestQunCard(const int, const int)));
	QObject::connect(win, SIGNAL(requestQunMembers(const int)), this, SIGNAL(requestQunMembers(const int)));
	return win;
}

bool EvaChatWindowManager::isQunChatWindowExisted( const int id )
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win){
		if(win->isHidden()){
			return false;
		}else{
			return true;
		}
	}else{
		return false;
	}
}

void EvaChatWindowManager::openQunChatWindow( Qun * qun )
{
	if(!qun) return;
	EvaQunChatWindow *win = getQunWindow(qun->getQunID());
	if(win){
		if(win->isHidden()){
			qunWindowList.removeRef(win);
			win = newQunWindow(qun);
			win->show();
		}else{
			KWin::forceActiveWindow(win->winId());
			return;
		}
	}else{
		win = newQunWindow(qun);
		win->show();
	}
	
	QunMessage *msg;
	for(uint i = 0; i<qunMessageQueue.count(); i++){
		msg = qunMessageQueue.at(i);
		if(msg->qunID == qun->getQunID()){
			win->slotReceivedMessage(msg->qunID, msg->sender, msg->message, msg->time, msg->size,
						msg->u, msg->i, msg->b, msg->blue, msg->green, msg->red);
			qunMessageQueue.remove(i--);
		}
	}
}

void EvaChatWindowManager::slotQunOnlineMembers(const int id)
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win)
		win->slotUpdateOnlineMembers();
}

void EvaChatWindowManager::slotQunPicReady( const int id, const QString fileName , const QString tmpFileName)
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win)
		win->slotPictureReady(fileName, tmpFileName);
}

void EvaChatWindowManager::slotQunPicSent( const int id, const unsigned int sessionID, const unsigned int ip, const unsigned short port)
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win)
		win->slotSendImageDone(sessionID, ip, port);
}

void EvaChatWindowManager::slotSendImageError( const int id, const QString message )
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win)
		win->sendImageError(message);
}

void EvaChatWindowManager::slotQunMemberInfoReady( const int id)
{
	EvaQunChatWindow *win = getQunWindow(id);
	if(win)
		win->slotDisplayMembers();
}
