/***************************************************************************
 *   Copyright (C) 2004 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 "evapacketmanager.h"
#include "evausersetting.h"
#include "evaconnecter.h"
#include <qdatetime.h>
#include <qtimer.h>
#include <qtextcodec.h>
#include <stdlib.h>
#include <map>

EvaPacketManager::EvaPacketManager(EvaUser *user, EvaConnecter *connecter)
{
	this->user = user;
	addingBuddyQQ = 0;
	deletingBuddyQQ = 0;
	OutPacket::setQQ(user->getQQ());
	Packet::setPasswordKey((unsigned char *)(user->getMd5Password()));
	this->connecter = connecter;
	Packet::setUDP(connecter->getConnectionType() == EvaNetwork::UDP);
	QObject::connect(connecter, SIGNAL(newPacket()), this, SLOT(newPacketSlot()));
	QObject::connect(connecter, SIGNAL(networkException(int)), this, SLOT(networkExceptionSlot(int)));
	QObject::connect(connecter, SIGNAL(packetException(int)), this, SLOT(packetExceptionSlot(int)));
	
	timer = new QTimer(this);
	QObject::connect(timer, SIGNAL(timeout()), SLOT(timerSlot()) );
}

EvaPacketManager::~EvaPacketManager()
{
	if(timer->isActive()){
		timer->stop();
	}
	delete timer;
	if(user) delete user;
	if(connecter) delete connecter;
}

// void EvaPacketManager::isReadySlot( )
// {
// 	doLogin();
// }

void EvaPacketManager::newPacketSlot()
{
	InPacket *packet = connecter->getInPacket();
	if(packet==NULL){
		fprintf(stderr, "grab packet error: NULL pointer!\n");
		return;
	}
	parsePacket(packet);
}

void EvaPacketManager::networkExceptionSlot(int exp)
{
	printf("network exception: %d\n", exp);
	emit networkException(exp);
}

void EvaPacketManager::packetExceptionSlot(int cmd)
{
	printf("packet exception: (cmd)0x%4x\n",cmd);
	emit packetException(cmd);
}

void EvaPacketManager::timerSlot()
{
	connecter->append(new KeepAlivePacket());
	receivedPacketList.clear();
	receivedCacheList.clear();
}

void EvaPacketManager::redirectTo(const int ip, const short port)
{
	//QObject::connect(connecter, SIGNAL(isReady()), this, SLOT(isReadySlot()) );
	connecter->redirectTo(ip, port);
}

void EvaPacketManager::saveBuddyQQ(const int id, const short seq)
{
	std::map<short, int>::iterator iter = sendRemoveCacheList.find(seq);
	if( iter != sendRemoveCacheList.end()) return ;
	
	sendRemoveCacheList[seq] = id;
}

void EvaPacketManager::removeSenquence(const short seq)
{
	std::map<short, int>::iterator iter = sendRemoveCacheList.find(seq);
	if( iter == sendRemoveCacheList.end()) return;
	sendRemoveCacheList.erase(iter);
}

const int EvaPacketManager::getSavedBuddyQQ(const short seq)
{
	std::map<short, int>::iterator iter = sendRemoveCacheList.find(seq);
	if(iter == sendRemoveCacheList.end()) return -1;
	
	return sendRemoveCacheList[seq];
}

void EvaPacketManager::parsePacket(InPacket *packet)
{
	int index = receivedPacketList.findIndex(packet->hashCode());
	if(index != -1 && packet->getCommand() != QQ_CMD_RECV_IM) {
		delete packet;
		return;
	}
	receivedPacketList.append(packet->hashCode());
	
	switch(packet->getCommand()){
	case QQ_CMD_LOGIN:
		processLoginReply(packet);
		break;
	case QQ_CMD_KEEP_ALIVE:
		//printf("keep alive reply\n");
		processKeepAliveReply(packet);
		break;
	case QQ_CMD_GET_USER_INFO:
		printf("user info\n"); 
		processGetUserInfoReply(packet);
		break;
	case QQ_CMD_CHANGE_STATUS:
		printf("change status reply\n");
		processChangeStatusReply(packet);
		break;
	case QQ_CMD_GET_FRIEND_LIST:
		printf("friend list\n");
		processGetFriendListReply(packet);
		break;
	case QQ_CMD_GET_FRIEND_ONLINE:
		//printf("online-friend list\n");
		processGetOnlineFriendReply(packet);
		break;
	case QQ_CMD_SEND_IM:
		printf("send im reply\n");
		processSendIMReply(packet);
		break;
	case QQ_CMD_RECV_IM:
		printf("received new message\n");
		processReceiveIM(packet);
		break;
	case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
		printf("friend change status\n");
		processFriendChangeStatus(packet);
		break;
	case QQ_CMD_GROUP_NAME_OP:
		printf("upload/download group names reply\n");
		processGroupNameOp(packet);
		break;
	case QQ_CMD_DOWNLOAD_GROUP_FRIEND:
		printf("grouped friends reply\n");
		processDownloadGroupFriendReply(packet);
		break;	
	case QQ_CMD_UPLOAD_GROUP_FRIEND:
		printf("upload grouped friend reply\n");
		processUploadGroupFriendReply(packet);
		break;
	case QQ_CMD_DELETE_FRIEND:
		printf("delete friend reply\n");
		processDeleteFriendReply(packet);
		break;
	case QQ_CMD_ADD_FRIEND:
		printf("add friend reply\n");
		processAddFriendReply(packet);
		break;
	case QQ_CMD_ADD_FRIEND_AUTH:
		printf("add friend auth reply\n");
		processAddFriendAuthReply(packet);
		break;				
	case QQ_CMD_RECV_MSG_SYS:
		printf("system message\n");
		processSystemNotification(packet);
		break;
	case QQ_CMD_MODIFY_INFO:
		printf("received modify info\n");
		processModifyInfoReply(packet);
		break;
	case QQ_CMD_SEARCH_USER:
		printf("search reply\n");
		processSearchUserReply(packet);
		break;
	case QQ_CMD_DELETE_ME:
		printf("delete me reply\n");
		processDeleteMeReply(packet);
		break;
	}
        delete packet;
}

void EvaPacketManager::doLogin()
{
	unsigned char mode = QQ_LOGIN_MODE_INVISIBLE;
	if(user->getStatus() == EvaUser::Eva_Online)
		mode = QQ_LOGIN_MODE_NORMAL;
	connecter->append(new LoginPacket(mode));
}

void EvaPacketManager::processLoginReply(const InPacket *in)
{
        LoginReplyPacket *packet = new LoginReplyPacket();
        packet->setInPacket(in);
	packet->parse();
	//printf("login Reply msg:%s\n", (uchar)packet->getReplyMessage().c_str());
	switch(packet->getReplyCode())
	{
	case QQ_LOGIN_REPLY_OK:
		{
		printf("user \"%d\" logged in!\n", user->getQQ());
		connecter->append(new GetOnlineFriendsPacket());
		timer->start(60000, false);
		emit loginOK();
		}
		break;
	case QQ_LOGIN_REPLY_REDIRECT:
		printf("EVA redirect to: %8x, %d\n", packet->getRedirectedIP(), packet->getRedirectedPort());
		if(packet->getRedirectedIP() == 0) {
			emit serverBusy();
		}else
			redirectTo(packet->getRedirectedIP(),packet->getRedirectedPort());
		//doLogin();
		break;
	case QQ_LOGIN_REPLY_PWD_ERROR:
		printf("pwd error:%s\n",packet->getReplyMessage().c_str());
		//doOffline();
		emit wrongPassword();
		break;
	case QQ_LOGIN_REPLY_MISC_ERROR:
		printf("sth error:%s\n",packet->getReplyMessage().c_str());
		//doOffline();
		break;
        default:
                printf("no known reply code\n");
	}
}

void EvaPacketManager::doLogout( )
{
	if(timer->isActive())
		timer->stop();
	connecter->stop();
	for(int i=0; i<4; i++)
		connecter->append(new LogoutPacket());
	Packet::clearAllKeys();
	emit logoutOK();
}

void EvaPacketManager::doGetUserInfo( const int id )
{
	connecter->append(new GetUserInfoPacket(id));
}

void EvaPacketManager::processGetUserInfoReply( const InPacket * in )
{
	GetUserInfoReplyPacket *packet = new GetUserInfoReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	ContactInfo info = packet->contactInfo();
	std::string strID = info.at(ContactInfo::Info_qqID);
	int id = atoi(strID.c_str());
	if( id == user->getQQ()){
		user->setDetails(info);
		emit myInfoReady();
	}else{
		user->getFriendList().addContactInfoTo(id, info);
	}
	user->saveGroupedBuddyList();
	emit userInfoReady(convertDetails(info));
}

void EvaPacketManager::doChangeStatus( EvaUser::UserStatus newStatus )
{
	user->setStatus( newStatus );
	connecter->append(new ChangeStatusPacket(EvaUser::getStatusCode(newStatus)));
}

void EvaPacketManager::processChangeStatusReply( const InPacket * in )
{
	ChangeStatusReplyPacket *packet = new ChangeStatusReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	if(packet->isAccepted()){  // if change status failed,  in most cases it's because of connection problem, 
		switch(user->getStatus()){             // so we simply emit a offline signal
		case EvaUser::Eva_Online:
			emit onlineReady();
			break;
		case EvaUser::Eva_Offline:
			if(timer->isActive())
				timer->stop();
			connecter->stop();
			emit offlineReady();
			break;	
		case EvaUser::Eva_Invisible:
			emit invisibleReady();
			break;
		case EvaUser::Eva_Leave:
			emit leaveReady();
			break; 
		}
	}else{
		if(timer->isActive())
			timer->stop();
		connecter->stop();
		emit offlineReady();    // if we meet any problem, just emit offline signal
	}
}

void EvaPacketManager::doGetAllFriends( )
{
	user->getFriendList().clearFriendList();
	connecter->append(new GetFriendListPacket());
}

void EvaPacketManager::processGetFriendListReply( const InPacket * in )
{
	GetFriendListReplyPacket *packet = new GetFriendListReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	friendItemList gotList = packet->getFriendList();
	friendItemList::iterator iter;
	for(iter = gotList.begin(); iter!= gotList.end(); ++iter){
		QQFriend frd;
		frd.setFriendItem(*iter);
		user->getFriendList().addFriend(frd);
	}
	if(packet->getPosition()!=QQ_FRIEND_LIST_POSITION_END){
		connecter->append(new GetFriendListPacket(packet->getPosition()));
	}else{
		emit friendListReady();
		connecter->append(new GetOnlineFriendsPacket());
	}
}

void EvaPacketManager::doSendMessage( const int receiver, const bool isNormal, QString & message, const char fontSize, 
					const bool u, const bool i, const bool b, 
					const char blue, const char green, const char red )
{	
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	QString rNick = codec->toUnicode( user->getFriendList().getFriend(receiver)->getNick().c_str());
	QString sNick = codec->toUnicode(user->getDetails().at(ContactInfo::Info_nick).c_str());
	QDateTime time = QDateTime::currentDateTime(Qt::LocalTime);	
	user->getSetting()->saveMessage(receiver,  user->getQQ(), sNick, receiver, rNick,
				isNormal, message, time, fontSize, u, i, b, blue, green, red);
	SendTextIMPacket *packet = new SendTextIMPacket();
	packet->setReceiver(receiver);
	packet->setFontSize(fontSize);
	packet->setUnderline(u);
	packet->setItalic(i);
	packet->setBold(b);
	packet->setBlue(blue);
	packet->setGreen(green);
	packet->setRed(red);
	packet->setAutoReply(isNormal);
	QCString str = codec->fromUnicode(message);
	packet->setMessage(str.data());
	saveBuddyQQ(receiver, packet->getSequence());
	connecter->append(packet);	
}

void EvaPacketManager::processSendIMReply( const InPacket * in )
{
	SendIMReplyPacket *packet = new SendIMReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	int id = getSavedBuddyQQ(packet->getSequence());
	if(id==-1) return;
	removeSenquence(packet->getSequence());
	emit sentMessageResult(id, packet->isSentOK());
}

void EvaPacketManager::processKeepAliveReply( const InPacket * in )
{
	KeepAliveReplyPacket *packet = new KeepAliveReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	numOnlineUsers = packet->numOnlineUsers();
	connecter->append(new GetOnlineFriendsPacket());
}

void EvaPacketManager::processGetOnlineFriendReply( const InPacket * in )
{
	GetOnlineFriendReplyPacket *packet = new GetOnlineFriendReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	onlineList list = packet->getOnlineFriendList();
	onlineList::iterator iter;
	for(iter = list.begin(); iter!=list.end(); ++iter){
		user->getFriendList().addOnlineFriendEntryTo(iter->getQQ(), *iter);
	}
	if(packet->getPosition() != QQ_FRIEND_ONLINE_LIST_POSITION_END){
		connecter->append(new GetOnlineFriendsPacket(packet->getPosition()));
	}
}

void EvaPacketManager::processFriendChangeStatus( const InPacket * in )
{
	FriendChangeStatusPacket *packet = new FriendChangeStatusPacket();
	packet->setInPacket(in);
	packet->parse();
	
	user->getFriendList().updateFriendIP(packet->getQQ(), packet->getIP());
	user->getFriendList().updateFriendPort(packet->getQQ(), packet->getPort());
	user->getFriendList().updateFriendStatus(packet->getQQ(), packet->getStatus());	
	emit friendStatusChanged(packet->getQQ());
}

void EvaPacketManager::processReceiveIM( const InPacket * in )
{
	ReceiveIMPacket *packet = new ReceiveIMPacket();
	packet->setInPacket(in);
	packet->parse();
	ReceiveIMReplyPacket *packetReply = new ReceiveIMReplyPacket(packet->getReplyKey());
	packetReply->setSequence(packet->getSequence());
	connecter->append(packetReply);
	int index = receivedCacheList.findIndex(packet->hashCode());
	if(index != -1 ) return;
	receivedCacheList.append(packet->hashCode());
    	//for(int i=0; i<1000; i++);
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	switch(packet->getIMType()){
	case QQ_RECV_IM_TO_BUDDY:
	case QQ_RECV_IM_TO_UNKNOWN:{
		NormalIMBase *base = new NormalIMBase(packet->getBodyData(), packet->getBodyLength());		
		base->parseData();
		switch(base->getNormalIMType())
		{
		case QQ_IM_NORMAL_TEXT:{
			ReceivedNormalIM * received = new ReceivedNormalIM();
			received->setNormalIMBase(base);
			received->parseData();
			const QQFriend *frd = user->getFriendList().getFriend(received->getSender());
			if(frd==NULL){
				QQFriend f(received->getSender(),received->getSenderFace());
				f.setGroupIndex(EvaUser::getAnonymousIndex());
				user->getFriendList().addFriend(f);				
			}
			user->getFriendList().updateFriendIP(packet->getSender(), packet->getSenderIP());
			user->getFriendList().updateFriendPort(packet->getSender(), packet->getSenderPort());
			user->getFriendList().updateFriendFileSessionKey(packet->getSender(),received->getBuddyFileSessionKey());
			QString msg = codec->toUnicode(received->getMessage().c_str());
			QDateTime time;
			time.setTime_t(received->getSendTime());
			
			int sender = received->getSender();
			bool isNormal = received->isNormalReply();
			char fontSize = received->getFontSize();
			bool u = received->isUnderline();
			bool i = received->isItalic();
			bool b = received->isBold();
			char blue = received->getBlue();
			char green = received->getGreen();
			char red = received->getRed();
			
			QString sNick = codec->toUnicode(user->getFriendList().getFriend(sender)->getNick().c_str());
			QString rNick = codec->toUnicode(user->getDetails().at(ContactInfo::Info_nick).c_str());
			user->getSetting()->saveMessage(sender, sender, sNick, user->getQQ(), rNick, 
						isNormal, msg, time, fontSize, u, i, b, blue, green, red);
						
			emit txtMessage(sender, isNormal, msg, time, fontSize, 
					u, i, b, blue, green, red);
			delete received;
			}
			break;
		default:
			printf("Got a non-text msg, can't process it, ignore it\n");
		}
		delete base;
		}
		break;
	case QQ_RECV_IM_SYS_MESSAGE:{
		ReceivedSystemIM *sys = new ReceivedSystemIM(packet->getBodyData(), packet->getBodyLength());		
		switch(sys->getSystemIMType())
		{
		case QQ_RECV_IM_KICK_OUT:
			printf("this account has logged in somewhere, you are kicked out!\n");
			if(timer->isActive())
				timer->stop();
			connecter->stop();
			emit kickedOut();
			break;
		default:
			printf("Got a system msg: %s\n", sys->getMessage().c_str());
		}
		delete sys;
		}
	case QQ_RECV_IM_CLUSTER_IM:{
		ReceivedQunIM *im = new ReceivedQunIM(packet->getBodyData(), packet->getBodyLength());
		printf("==============================\n");
		printf("Qun %d Message:\n From QQ:%d\n%s\n", packet->getSender(), im->getSenderQQ(), im->getMessage().c_str());
		printf("==============================\n");
		delete im;
		}
		break;
	default:
		printf("message code: 0x%4x -- sender:%d  -- Unknown\n",packet->getSender(), packet->getIMType());
	}
	delete packet;
}

void EvaPacketManager::doGetGroups( )
{
	connecter->append(new GroupNameOpPacket(QQ_DOWNLOAD_GROUP_NAME));
}

void EvaPacketManager::doUploadGroups()
{
	GroupNameOpPacket *packet = new GroupNameOpPacket(QQ_UPLOAD_GROUP_NAME);
// 	std::list<std::string>::iterator iter = user->getGroupNames().begin();
// 	for(iter; iter != user->getGroupNames().end(); ++iter){  
// 		printf("Group: %s\n", iter->c_str());
// 	}
	packet->setGroups(user->getGroupNames());
	connecter->append(packet);
}

void EvaPacketManager::processGroupNameOp( const InPacket * in )
{
	GroupNameOpReplyPacket *packet = new GroupNameOpReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	if(packet->isDownloadReply()){
		std::list<std::string>::iterator iter;
		std::list<std::string> names = packet->getGroupNames();
		user->clearGroupNames(); // note that the first group won't be deleted
		for(iter = names.begin(); iter != names.end(); ++iter){
			user->newGroup(*iter);
		}
		//emit groupNamesDownloadReady();
		doGetGroupedFriends();
	}else{
		//emit groupNamesUploadReady();
		std::map<int, QQFriend> srcList = user->getFriendList().getFriendList();
		std::map<int, QQFriend>::iterator iter;
		std::map<int, int> destList;
		for(iter = srcList.begin(); iter!= srcList.end(); ++iter){
			if((iter->second).getGroupIndex() != user->getAnonymousIndex() &&
				(iter->second).getGroupIndex() != user->getBlackIndex()){
				destList[(iter->second).getQQ()] = (iter->second).getGroupIndex();
			}
		}
		UploadGroupFriendPacket *packet = new UploadGroupFriendPacket();
		packet->setGroupedFriends(destList);
		connecter->append(packet);		
	}
}

void EvaPacketManager::doGetGroupedFriends( )
{
	connecter->append(new DownloadGroupFriendPacket());
}

void EvaPacketManager::processDownloadGroupFriendReply( const InPacket * in )
{
	DownloadGroupFriendReplyPacket *packet = new DownloadGroupFriendReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	std::list<DownloadFriendEntry> friends = packet->getGroupedFriends();
	std::list<DownloadFriendEntry>::iterator iter;
	for(iter = friends.begin(); iter!= friends.end(); ++iter){
		if(!iter->isQun()){
			user->getFriendList().updateFriendGroupIndex(iter->getQQ(), iter->getGroupID());
		}else
			printf("friend in Qun %d. (group index:%d)\n", iter->getQQ(),iter->getGroupID());
	}
	printf("totally num frd:%d\n", packet->getGroupedFriends().size());
	
	int nextID = packet->getNextStartID();
	printf("next start:%d\n",nextID);
	if(nextID != 0x0000){
		connecter->append(new DownloadGroupFriendPacket(nextID));
	}else
		emit friendGroupsReady();
}

void EvaPacketManager::processUploadGroupFriendReply(const InPacket *in)
{
	UploadGroupFriendReplyPacket *packet = new UploadGroupFriendReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	if(packet->uploadOk()) 
		emit friendGroupsUploadReady(true);
	else
		emit friendGroupsUploadReady(false);	
}

void EvaPacketManager::doDeleteBuddy( const int id )
{
	if(deletingBuddyQQ)
		return;
	deletingBuddyQQ = id;
	DeleteFriendPacket *packet = new DeleteFriendPacket(id);
	saveBuddyQQ(id, packet->getSequence());
	connecter->append(packet);
}

void EvaPacketManager::processDeleteFriendReply( const InPacket * in )
{
	DeleteFriendReplyPacket *packet = new DeleteFriendReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	if(packet->isDeleted()){
		user->getFriendList().deleteFriend(deletingBuddyQQ);
		user->saveGroupedBuddyList();
	}
	deletingBuddyQQ = 0;
	int id = getSavedBuddyQQ(packet->getSequence());
	if(id==-1) return;
	removeSenquence(packet->getSequence());
	emit deleteBuddyReady(id, packet->isDeleted());	
}

void EvaPacketManager::doAddBuddy( const int id )
{
	if(addingBuddyQQ) {
		emit addingBuddy(addingBuddyQQ);
		return;
	}
	addingBuddyQQ = id;
	connecter->append(new AddFriendPacket(id));
}

void EvaPacketManager::processAddFriendReply( const InPacket * in )
{
	AddFriendReplyPacket *packet = new AddFriendReplyPacket();
	packet->setInPacket(in);
	packet->parse();	
	switch(packet->getReplyCode()){
	case QQ_AUTH_NO_AUTH:{
		QQFriend frd(addingBuddyQQ, 0);
		user->getFriendList().addFriend(frd);
		addingBuddyQQ = 0;
		emit addBuddyReady();
		}
		break;
	case QQ_AUTH_NEED_AUTH:
		addingBuddyQQ = 0;
		emit addBuddyNeedAuth();
		break;
	case QQ_AUTH_NO_ADD:
		addingBuddyQQ = 0;
		emit addBuddyRejected();
		break;
	}	
}

void EvaPacketManager::doAddAuthBuddy( const int id, const QString &message)
{
	AddFriendAuthPacket *packet = new AddFriendAuthPacket(id, QQ_MY_AUTH_REQUEST);
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	QCString msg = codec->fromUnicode(message);
	packet->setMessage(msg.data());
	connecter->append(packet);
}

void EvaPacketManager::doApproveBuddy( const int id)
{
	AddFriendAuthPacket *packet = new AddFriendAuthPacket(id, QQ_MY_AUTH_APPROVE);
	connecter->append(packet);
}

void EvaPacketManager::doRejectBuddy( const int id , const QString &message)
{
	AddFriendAuthPacket *packet = new AddFriendAuthPacket(id, QQ_MY_AUTH_REJECT);
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	QCString msg = codec->fromUnicode(message);
	packet->setMessage(msg.data());
	connecter->append(packet);
}

void EvaPacketManager::processAddFriendAuthReply( const InPacket * in )
{
	AddFriendAuthReplyPacket *packet = new AddFriendAuthReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	emit addBuddySentToServer(packet->isSentOK());
}

void EvaPacketManager::processSystemNotification( const InPacket * in )
{
	SystemNotificationPacket *packet = new SystemNotificationPacket();
	packet->setInPacket(in);
	packet->parse();
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	QString msg = codec->toUnicode(packet->getMessage().c_str());	
	
	user->getSetting()->saveSysMessage( packet->getType(), packet->getFromQQ(), packet->getMyQQ(), msg);
	switch(packet->getType()){
	case QQ_MSG_SYS_BEING_ADDED:
		emit systemMeBeenAdded( packet->getFromQQ());
		break;       
	case QQ_MSG_SYS_ADD_FRIEND_REQUEST:
		emit systemAddMeRequest(packet->getFromQQ(), msg);
		break;
	case QQ_MSG_SYS_ADD_FRIEND_APPROVED:{
		QQFriend frd(packet->getFromQQ(), 0);
		user->getFriendList().addFriend(frd);
		emit systemAddRequestApproved(packet->getFromQQ());
		}
		break;
	case QQ_MSG_SYS_ADD_FRIEND_REJECTED:
		emit systemAddRequestRejected(packet->getFromQQ(), msg);
		break;
	default:
		emit systemNotification(packet->getFromQQ(), msg);	
	}		
}

void EvaPacketManager::doModifyDetails(QStringList info, QString oldPwd, QString newPwd)
{
	std::vector<std::string> result;
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	for(uint i=0; i< info.count(); i++){
		result.push_back((codec->fromUnicode(info[i])).data());
	}
	//ContactInfo details;
	//changingDetails;
	changingDetails.setDetails(result);
	ModifyInfoPacket *packet = new ModifyInfoPacket(changingDetails);
	if(oldPwd != QString::null && newPwd != QString::null){
		std::string o, n;
		o = codec->fromUnicode(oldPwd).data();
		n = codec->fromUnicode(newPwd).data();
		packet->setPassword(o);
		packet->setNewPassword(n);
	}
	connecter->append(packet);
}

void EvaPacketManager::processModifyInfoReply(const InPacket *in)
{
	ModifyInfoReplyPacket *packet = new ModifyInfoReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	if(packet->isAccepted()){
		user->setDetails(changingDetails);
		user->saveGroupedBuddyList();
		emit myInfoReady();
		emit modifyInfo(true);
	}else
		emit modifyInfo(false);
}

QStringList EvaPacketManager::convertDetails(const ContactInfo &info)
{
	QStringList result;
	QTextCodec *codec = QTextCodec::codecForName("GBK");
	for(uint i=0; i< info.count(); i++){
		result.append(codec->toUnicode(info.at(i).c_str()));
	}
	return result;
}

void EvaPacketManager::doSearchUsers( const bool isSearchAll, const QString page, const QString id, 
				const QString nick, const QString email, const bool match )
{
	SearchUserPacket *packet = new SearchUserPacket();
	if(!isSearchAll){
		QTextCodec *codec = QTextCodec::codecForName("GBK");
		packet->setSearchType(QQ_SEARCH_CUSTOM);
		packet->setPage(codec->fromUnicode(page).data());
		packet->setQQ(codec->fromUnicode(id).data());
		packet->setNick(codec->fromUnicode(nick).data());
		packet->setEmail(codec->fromUnicode(email).data());		
		packet->setMatchEntireString(match);
	}
        connecter->append(packet);
}

void EvaPacketManager::processSearchUserReply( const InPacket * in )
{
	SearchUserReplyPacket *packet = new SearchUserReplyPacket();
	packet->setInPacket(in);
	packet->parse();

	emit searchUsersReady(packet->isFinished(), packet->getUsers());
}

void EvaPacketManager::doDeleteMeFrom( const int id )
{
	DeleteMePacket *packet = new DeleteMePacket(id);
	connecter->append(packet);
}

void EvaPacketManager::processDeleteMeReply( const InPacket * in )
{
	DeleteMeReplyPacket *packet = new DeleteMeReplyPacket();
	packet->setInPacket(in);
	packet->parse();
	emit deleteMeReady(packet->isDeleted());
}


