/***************************************************************************
 *   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 "evausersetting.h"
#include <vector>
#include <qdatastream.h>
#include <qtextstream.h>
#include <qstringlist.h>
#include <qfile.h>
#include <qdir.h>
#include <klocale.h>

EvaUserSetting::EvaUserSetting(const int id)
{
	qqNum = id;
	isUserDirExisted=false;
	loadDefaultSettings();
	buddyListFileName = "user.dat";
	chatMsgFileName = "chat.msg";
	sysMsgFileName = "sys.msg";
	userProfileFileName = "user.profile";
}

EvaUserSetting::~EvaUserSetting()
{
}

const bool EvaUserSetting::saveBuddyList(std::list<std::string> groups, ContactInfo &myInfo, FriendList &list)
{
	if(!isDirExisted(getEvaUserDir())){
		QDir d;
		if(!d.mkdir(getEvaUserDir()))
			return false;
	}
	
	QString fullName = getEvaUserDir() + "/" + buddyListFileName;
	QFile file(fullName);
	if(file.exists()) file.remove();
	if(!file.open(IO_WriteOnly | IO_Raw )){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return false;
	}

	
	QDataStream stream(&file);
	
	// save group names
	std::list<std::string>::iterator itr;
	// save the number of customized groups (including buddy list)	
	stream<<groups.size();
	for(itr=groups.begin(); itr!=groups.end(); ++itr){
		stream<<itr->c_str();
	}
	
	std::list<QQFriend> flist = list.getAllFriends();
	std::list<QQFriend>::iterator iter;
	Q_UINT32 id;
	Q_UINT8  face;
	Q_UINT8  age;
	Q_UINT8  gender;
	std::string nick;
	Q_UINT8  extFlag;
	Q_UINT8  commonFlag;
	Q_UINT32 groupIndex;
	ContactInfo userDetails;
	std::string detailItem;
	
	// save all buddy details
	for(iter = flist.begin(); iter!= flist.end(); ++iter){
		id = iter->getQQ();
		face = iter->getFace();
		age = iter->getAge();
		gender = iter->getGender();
		nick = iter->getNick();
		extFlag = iter->getExtFlag();
		commonFlag = iter->getCommonFlag();
		groupIndex = iter->getGroupIndex();
		userDetails = iter->getUserInformation();
		
		stream<<id<<face<<age<<gender<<nick.c_str()<<extFlag<<commonFlag<<groupIndex;
		
		Q_UINT32 myCount = myInfo.count();
		stream<<myCount;
		for(int i=0; i<(int)myCount; i++){
			detailItem = myInfo.at(i);
			stream<<detailItem.c_str();
		}
				
		Q_UINT32 count = userDetails.count();
		stream<<count;
		for(int i=0; i<(int)count; i++){
			detailItem = userDetails.at(i);
			stream<<detailItem.c_str();
		}
	}
	file.close();
	return true;
}

const bool EvaUserSetting::loadBuddyList(std::list<std::string> &groupNames, ContactInfo &myInfo, FriendList &list)
{
	if(!isDirExisted(getEvaUserDir()))
		return false;
	
	QString fullName = getEvaUserDir() + "/" + buddyListFileName;
	QFile file(fullName);
	if(!file.open(IO_ReadOnly)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return false;
	}

	groupNames.clear();
	list.clearFriendList();
	
	Q_UINT32 numGroups=0;

	QDataStream stream(&file);
	
		
	// read in how many groups
	stream>>numGroups;
	std::string name;
	char *str = new char[512];
	// read all groups in
	for(uint i=0; i<numGroups; i++){
		stream>>str;
		name = str;
		groupNames.push_back(name);
	}	
	
	Q_UINT32 id;
	Q_UINT8  face;
	Q_UINT8  age;
	Q_UINT8  gender;
	std::string nick;
	Q_UINT8  extFlag;
	Q_UINT8  commonFlag;
	Q_UINT32 groupIndex;
	
	// read in all friends
	while(!stream.atEnd()){
		stream>>id;
		stream>>face;
		stream>>age;
		stream>>gender;
		stream>>str;
		nick = str;
		stream>>extFlag;
		stream>>commonFlag;
		stream>>groupIndex;
		Q_UINT32 size=0;
		std::string item;
		std::vector<std::string> strlist;
				
		stream>>size;
		for(uint i=0; i<size; i++){
			stream>>str;
			item = str;
			strlist.push_back(item);
		}		
		myInfo.setDetails(strlist);
		
		strlist.clear();
		stream>>size;
		for(uint i=0; i<size; i++){
			stream>>str;
			item = str;
			strlist.push_back(item);
		}
		QQFriend f(id, face);
		f.setAge(age);
		f.setGender(gender);
		f.setNick(nick);
		f.setExtFlag(extFlag);
		f.setCommonFlag(commonFlag);
		f.setGroupIndex(groupIndex);
		ContactInfo info;
		info.setDetails(strlist);
		f.setUserInformation(info);
		
		list.addFriend(f);
	}
	delete str;	
	return true;
}

const bool EvaUserSetting::saveMessage(const int buddy, const int sender, QString sNick, 
			const int receiver, QString rNick,
			const bool isNormal, 
			const QString message, 
			const QDateTime time, const char fontSize, 
			const bool u, const bool i, const bool b, 
			const char blue, const char green, const char red)
{
	if(!isDirExisted(getEvaUserDir())){
		QDir d;
		if(!d.mkdir(getEvaUserDir()))
			return false;
	}
	
	QString fullName = getEvaUserDir() + "/" + chatMsgFileName;
	QFile file(fullName);
	if(!file.open(IO_WriteOnly | IO_Raw | IO_Append)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return false;
	}

	
	QDataStream stream(&file);
	
	Q_UINT32 s_buddy = buddy;
	Q_UINT32 s_sender = sender;
	Q_UINT32 s_receiver = receiver;
	Q_UINT8  s_isNormal = isNormal?1:0;
	Q_UINT32 s_time = time.toTime_t();
	Q_UINT8  s_fontSize = fontSize;
	Q_UINT8  s_flag = (u?1:0)|( (i?1:0)<<1 ) | ( (b?1:0)<<2 );
	Q_UINT8  s_blue = blue;
	Q_UINT8  s_green = green;
	Q_UINT8  s_red = red;
	
	stream<<s_buddy;
	stream<<s_sender;
	stream<<sNick;
	stream<<s_receiver;
	stream<<rNick;
	stream<<s_isNormal;
	stream<<message;
	stream<<s_time;
	stream<<s_fontSize;
	stream<<s_flag;
	stream<<s_blue;
	stream<<s_green;
	stream<<s_red;
	
	file.close();
	return true;
}

std::list<EvaUserSetting::chatMessage> EvaUserSetting::getMessages( const int buddy, const int page)
{
	std::list<chatMessage>list;
	if(!isDirExisted(getEvaUserDir())){
		return list;
	}
	
	QString fullName = getEvaUserDir() + "/" + chatMsgFileName;
	QFile file(fullName);
	if(!file.open(IO_ReadOnly)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return list;
	}
	Q_UINT32 r_buddy;
	Q_UINT32 sender;
	QString  sNick;
	Q_UINT32 receiver;
	QString  rNick; 
	Q_UINT8  type; // 0 auto reply,  1 normal
	QString  message;
	Q_UINT32  intTime;
	QDateTime time;
	Q_UINT8   fontSize;
	Q_UINT8   flag; // start from right.  bit 0: u, bit 1: i, bit 2: b
	Q_UINT8   blue;
	Q_UINT8   green;
	Q_UINT8   red;
	
	QDataStream stream(&file);
	std::list<chatMessage>srclist;	
	while(!stream.atEnd()){
		stream>>r_buddy;
		stream>>sender;
		stream>>sNick;
		stream>>receiver;
		stream>>rNick;
		stream>>type;
		stream>>message;
		stream>>intTime;
		stream>>fontSize;
		stream>>flag;
		stream>>blue;
		stream>>green;
		stream>>red;
		if(r_buddy == (uint)buddy){	
			chatMessage m;
			m.sender = sender;
			m.sNick = sNick;
			m.receiver = receiver;
			m.rNick = rNick;
			m.type = type;
			m.message = message;
			time.setTime_t(intTime);
			m.time = time;
			m.fontSize = fontSize; 
			m.flag = flag; // start from right.  bit 0: u, bit 1: i, bit 2: b
			m.blue = blue;
			m.green = green;
			m.red = red;
			srclist.push_back(m);
		}
	}
	file.close();
	
	srclist.reverse();
	
	std::list<chatMessage>::iterator iter;	
	int current=0;
	int start = page * pageSize;
	int end = start + pageSize; // note that this value is always one more than we want
	for(iter=srclist.begin(); iter!=srclist.end(); iter++){
		if(current >= end) break;
		if(current>=start && current < end){
			list.push_back(*iter);
		}
		current++;
	}
	return list;
}

std::list<EvaUserSetting::chatMessage> EvaUserSetting::getMessages(const int buddy, const int page, 
							const QDateTime starttime, const QDateTime endtime)
{
	std::list<chatMessage>list;
	if(!isDirExisted(getEvaUserDir())){
		return list;
	}
	
	QString fullName = getEvaUserDir() + "/" + chatMsgFileName;
	QFile file(fullName);
	if(!file.open(IO_ReadOnly)){
		return list;
	}
	Q_UINT32 r_buddy;
	Q_UINT32 sender;
	QString  sNick;
	Q_UINT32 receiver;
	QString  rNick; 
	Q_UINT8  type; // 0 auto reply,  1 normal
	QString  message;
	Q_UINT32  intTime;
	QDateTime time;
	Q_UINT8   fontSize;
	Q_UINT8   flag; // start from right.  bit 0: u, bit 1: i, bit 2: b
	Q_UINT8   blue;
	Q_UINT8   green;
	Q_UINT8   red;

	int start = starttime.toTime_t();
	int end = endtime.toTime_t();
	
	std::list<chatMessage>srclist;
	QDataStream stream(&file);	
	while(!stream.atEnd()){
		stream>>r_buddy;
		stream>>sender;
		stream>>sNick;
		stream>>receiver;
		stream>>rNick;
		stream>>type;
		stream>>message;
		stream>>intTime;
		stream>>fontSize;
		stream>>flag;
		stream>>blue;
		stream>>green;
		stream>>red;
		if(r_buddy == (uint)buddy){
			if(intTime>=(uint)start && intTime < (uint)end){
				chatMessage m;
				m.sender = sender;
				m.sNick = sNick;
				m.receiver = receiver;
				m.rNick = rNick;
				m.type = type;
				m.message = message;
				time.setTime_t(intTime);
				m.time = time;
				m.fontSize = fontSize; 
				m.flag = flag; // start from right.  bit 0: u, bit 1: i, bit 2: b
				m.blue = blue;
				m.green = green;
				m.red = red;
				srclist.push_back(m);
			}
		}
	}
	file.close();

	srclist.reverse();
	
	std::list<chatMessage>::iterator iter;	
	int current=0;
	start = page * pageSize;
	end = start + pageSize; // note that this value is always one more than we want
	for(iter=srclist.begin(); iter!=srclist.end(); iter++){
		if(current >= end) break;
		if(current>=start && current < end){
			list.push_back(*iter);
		}
		current++;
	}	
	return list;
}

const bool EvaUserSetting::saveSysMessage(const uint8_t type, const int fromQQ, const int toQQ, const QString message)
{
	if(!isDirExisted(getEvaUserDir())){
		QDir d;
		if(!d.mkdir(getEvaUserDir()))
			return false;
	}
	
	QString fullName = getEvaUserDir() + "/" + sysMsgFileName;
	QFile file(fullName);
	if(!file.open(IO_WriteOnly | IO_Raw | IO_Append)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return false;
	}
	
	sysMessage m;
	m.type = type;
	m.from = fromQQ;
	m.to = toQQ;
	m.message = message;
// 	Q_UINT8  s_type = type;
// 	Q_UINT32 s_from = fromQQ;
// 	Q_UINT32 s_to = toQQ;
	
	QDataStream stream(&file);
	stream<<m.type;
	stream<<m.from;
	stream<<m.to;
	stream<<m.message;
	
	file.close();
	
	sysStack.push(m);
	return true;
}

std::list<EvaUserSetting::sysMessage> EvaUserSetting::getSysMessages( const int page) // page number starts from 0
{
	std::list<sysMessage>list;
	if(!isDirExisted(getEvaUserDir())){
		return list;
	}
	
	QString fullName = getEvaUserDir() + "/" + sysMsgFileName;
	QFile file(fullName);
	if(!file.open(IO_ReadOnly)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return list;
	}
	Q_UINT8 type;
	Q_UINT32 from;
	Q_UINT32 to;
	QString  message; 

	
	std::list<sysMessage>srclist;
	QDataStream stream(&file);
	while(!stream.atEnd()){
		stream>>type;
		stream>>from;
		stream>>to;
		stream>>message;
		
		sysMessage m;
		m.type = type;
		m.from = from;
		m.to = to;
		m.message = message;
		srclist.push_back(m);
	}
	file.close();

	srclist.reverse();
	
	std::list<sysMessage>::iterator iter;	
	int current=0;
	int start = page * pageSize;
	int end = start + pageSize; // note that this value is always one more than we want
	for(iter=srclist.begin(); iter!=srclist.end(); iter++){
		if(current >= end) break;
		if(current>=start && current < end){
			list.push_back(*iter);
		}
		current++;
	}
	return list;
}

EvaUserSetting::sysMessage EvaUserSetting::getLastSysMessage()
{
	sysMessage m;
	m.type = 0;
	m.from = 0;
	if(!sysStack.empty()){
		m = sysStack.top();
		sysStack.pop();
	}
	return m;
}

const bool EvaUserSetting::saveSettings()
{
	if(!isDirExisted(getEvaUserDir())){
		QDir d;
		if(!d.mkdir(getEvaUserDir()))
			return false;
	}
	
	QString fullName = getEvaUserDir() + "/" + userProfileFileName;
	QFile file(fullName);
	if(file.exists()) file.remove();
	if(!file.open(IO_WriteOnly | IO_Raw)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return false;
	}
	
	QTextStream stream(&file);
	stream<<"THEME_DIR:"<<themeDir<<endl;
	stream<<"SOUND_DIR:"<<soundDir<<endl;
	stream<<"FACE_SIZE:"<<faceSize.width()<<","<<faceSize.height()<<endl;
	stream<<"DISPLAY_QQ_BROADCAST:"<<(showQQBroadcast?"true":"false")<<endl;
	stream<<"DISPLAY_TIP_MESSAGE_TIP_WINDOW:"<<(showMessageTipWindow?"true":"false")<<endl;
	stream<<"DISPLAY_BUDDY_ONLINE_NOTIFY:"<<(showBudyOnlineNotifyWindow?"true":"false")<<endl;
	stream<<"DISPLAY_ONLINE_BUDDIES:"<<(showOnlineUsers?"true":"false")<<endl;
	stream<<"SEND_KEY:"<< (isSendKeyEnter?"true":"false") <<endl;
	stream<<"PLAY_SOUND:"<<(playSound?"true":"false")<<endl;
	
	stream<<"AUTO_REPLY_SELECTED_INDEX:"<<autoSelectedIndex<<endl;
	std::list<QString>::iterator iter;
	for(iter = autoList.begin(); iter!=autoList.end(); ++iter){
		stream<<"AUTO_REPLY:"<< (*iter)<<endl;
	}
	for(iter = quickList.begin(); iter!=quickList.end(); ++iter){
		stream<<"QUICK_REPLY:"<< (*iter)<<endl;
	}
	file.close();
	return true;
}

const bool EvaUserSetting::loadSettings()
{
	if(!isDirExisted(getEvaUserDir())){
		return false;
	}
	
	QString fullName = getEvaUserDir() + "/" + userProfileFileName;
	QDir d;
	if(!d.exists(fullName)){
		loadDefaultSettings();
		return true;
	}
	QFile file(fullName);
	if(!file.open(IO_ReadOnly)){
		//QString msg = qApp->translate("QFile",file.errorString());
		//emit exceptionEvent(msg);
		return false;
	}
	
	autoList.clear();
	quickList.clear();
	
	QString line;
	QStringList lineList;
	QTextStream stream(&file);
	while(!stream.atEnd()){
		line = stream.readLine().stripWhiteSpace();
		lineList = QStringList::split(":", line);
		if(lineList.size() != 2)
			continue;
		
		lineList[0].stripWhiteSpace();
		lineList[1].stripWhiteSpace();
		
		if(lineList[0] ==  "THEME_DIR"){
			themeDir = lineList[1];
		}
		
		if(lineList[0] ==  "SOUND_DIR"){
			soundDir = lineList[1];
		}
		
		if(lineList[0] ==  "FACE_SIZE"){
			QStringList size = QStringList::split(",",lineList[1]);
			int width, height;
			bool ok;
			width = size[0].toInt(&ok);
			if(!ok) width = 16;
			height = size[1].toInt(&ok);
			if(!ok) height = 16;
			faceSize = QSize(width, height);
			continue;
		}
		if(lineList[0] ==  "DISPLAY_QQ_BROADCAST"){
			if(lineList[1] == "false")
				showQQBroadcast = false;
			else 
				showQQBroadcast = true;
			continue;
		}
		if(lineList[0] ==  "DISPLAY_TIP_MESSAGE_TIP_WINDOW"){
			if(lineList[1] == "false")
				showMessageTipWindow = false;
			else 
				showMessageTipWindow = true;
			continue;
		}
		if(lineList[0] ==  "DISPLAY_BUDDY_ONLINE_NOTIFY"){
			if(lineList[1] == "false")
				showBudyOnlineNotifyWindow = false;
			else 
				showBudyOnlineNotifyWindow = true;
			continue;
		}
		if(lineList[0] ==  "DISPLAY_ONLINE_BUDDIES"){
			if(lineList[1] == "false")
				showOnlineUsers = false;
			else 
				showOnlineUsers = true;
			continue;
		}
		if(lineList[0] ==  "SEND_KEY"){
			if(lineList[1] == "false")
				isSendKeyEnter = false;
			else 
				isSendKeyEnter = true;
			continue;
		}
		if(lineList[0] ==  "PLAY_SOUND"){
			if(lineList[1] == "false")
				playSound = false;
			else 
				playSound = true;
			continue;
		}
		if(lineList[0] == "AUTO_REPLY_SELECTED_INDEX"){
			bool ok = false;			
			autoSelectedIndex = lineList[1].toInt(&ok);
			if(!ok)
				autoSelectedIndex = 0;
				
		}
		if(lineList[0] == "AUTO_REPLY"){
			autoList.push_back(lineList[1]);
		}		
		if(lineList[0] == "QUICK_REPLY"){
			quickList.push_back(lineList[1]);
		}
	}
	file.close();
	return true; 
}

void EvaUserSetting::loadDefaultSettings()
{
	faceSize = QSize(16,16);
	showQQBroadcast = true;
	showMessageTipWindow = true;
	showBudyOnlineNotifyWindow = true;
	showOnlineUsers = false;
	isSendKeyEnter = false;
	playSound = true;
	pageSize = 25;
	autoReply = true;
	themeDir = "";
	soundDir = "";
	autoSelectedIndex = 0;
	if(!autoList.size()){
		autoList.push_back(QString(i18n("sorry, I am working.")));
		autoList.push_back(QString(i18n("having dinner now./fa")));
		autoList.push_back(QString(i18n("I am not available now, sorry")));		
	}
	
	if(!quickList.size()){
		quickList.push_back(QString(i18n("oh.")));
		quickList.push_back(QString(i18n("ok, ok, I got u.")));
		quickList.push_back(QString(i18n("/jy ,really?")));
	}
}

const QString &EvaUserSetting::getSelectedAutoReply()
{
	int index = 0;
	std::list<QString>::iterator iter;
	for(iter=autoList.begin(); iter!=autoList.end(); ++iter){
		if(index == autoSelectedIndex) break;
		index++;		
	}
	return *iter;
}

const QString &EvaUserSetting::getQuickReplyMessageAt(const int index)
{
	int i = 0;
	std::list<QString>::iterator iter;
	for(iter=quickList.begin(); iter!=quickList.end(); ++iter){
		if(i == index) break;
		i++;
	}
	return *iter;
}

void EvaUserSetting::addAutoReplyMessage(const QString &message)
{
	autoList.push_back(message);
}

void EvaUserSetting::addQuickReplyMessage(const QString &message)
{
	quickList.push_back(message);
}

const std::list<QString> &EvaUserSetting::getAutoReplyList()
{
	return autoList;
}

const std::list<QString> &EvaUserSetting::getQuickReplyList()
{
	return quickList;
}

const QString EvaUserSetting::getUserHomeDir()
{
	return QDir::homeDirPath();
}

const QString EvaUserSetting::getEvaSettingDir()
{
	return getUserHomeDir()+"/.eva";
}

const QString EvaUserSetting::getEvaUserDir()
{
	return getEvaSettingDir() + "/" + QString::number(qqNum);
}
	
const bool EvaUserSetting::isDirExisted(const QString &dir)
{
	QDir d;
	if (d.exists(dir))
		return true;
	else
		return false;
}
