/***************************************************************************
 *   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.             *
 ***************************************************************************/

#ifndef EVALISTVIEW_H
#define EVALISTVIEW_H

#include <qlistview.h>
#include <qvaluestack.h>
#include <qsize.h>
#include <string>
#include <list>
#include <map>
#include <qtooltip.h>

class QTimer;
class QPixmap;
class EvaToolTip;
class EvaQunItem;
class QCustomEvent;

class EvaBuddyItem :  public QObject, public QListViewItem
{
	Q_OBJECT
public:
	enum Status {Online, Leave, Invisible, Offline };
	EvaBuddyItem( QListViewItem *parent, const QString &nick, const int id, const QString signature,
			QPixmap *on =0, QPixmap *off=0, EvaBuddyItem::Status status = EvaBuddyItem::Offline);
	~EvaBuddyItem();
	
	void updateNick(const QString &nick);
	void updateSignature(const QString &sig);
	void updateFacePixmaps(QPixmap *on, QPixmap *off);
	const QPixmap *pixmapOnline() const;
	const QPixmap *pixmapOffline() const;
	
	static QPixmap *pixmapNA() ;
	static void setPixmapNA(QPixmap *p) ;
	static QPixmap *pixmapMsg();
	static void setPixmapMsg(QPixmap *p);
	
	static QSize &getFaceSize() { return faceSize; }
	static void setFaceSize(const QSize size) { faceSize = size; }
	
	const int getQQ() const ;
	const Status getStatus() const;
	const int numOfUnreadMsgs() const ;
	
	const bool hasMessages() const;
	
	void refreshFace(bool isForcedToChange = false); 
	virtual QString key( int col, bool ascending) const;
	
	QString tip();
public slots:
	void slotChangeToOnline(bool isForcedToChange = false);
	void slotChangeToLeave(bool isForcedToChange = false);
	void slotChangeToOffline(bool isForcedToChange = false);
	void slotChangeToInvisible(bool isForcedToChange = false);
	void slotStartFlash();
	void slotStopFlash();

protected:
	virtual void customEvent( QCustomEvent *e);
private:
	void runScaleImageThread(QPixmap *p);
	void updateFace(QPixmap *pix);
	void updateText();
	QTimer *timer;
	Status status;
	QPixmap *pixOnline;
	QPixmap *pixOffline;
	QString nickName;
	QString mSignature;
	int qqNum;
	int numOfMessages;
	
	bool isMsgShown;
	static QPixmap *pixNA;
	static QPixmap *pixMsg;
	static QSize faceSize;
private slots:
	void slotTimeout();
};

class EvaGroupItem : public QObject, public QListViewItem
{
	Q_OBJECT
public:
	enum Type{ Normal, QunOrg, QunDiscuss};
	EvaGroupItem(QListView *parent, const QString &name, int index = 0);
	EvaGroupItem(QListViewItem *parent, const QString &name, Type t);
	~EvaGroupItem(){};
	
	void setOpen(bool o);
	const int getGroupIndex() const;
	void setGroupIndex(const int index) { groupIndex = index; }
	const QString &getGroupName() const;
	void setGroupName(const QString name); // note that this method dosen't update the number of onlines
	static void setPixmapOpen(QPixmap *p);
	static void setPixmapClose(QPixmap *p);
	static void setPixmapMsg(QPixmap *p);
	
	static QPixmap *pixmapOpen() ;
	static QPixmap *pixmapClose();
	static QPixmap *pixmapMsg();
	
	void addBuddy(EvaBuddyItem *item);
	EvaBuddyItem *addBuddy(const QString &nick, const int id, const QString signature, QPixmap *on =0, QPixmap *off=0, 
				EvaBuddyItem::Status status = EvaBuddyItem::Offline);
	void updateNick(const int id, const QString &nick);
	void updateSignature(const int id, const QString &sig);
	void updateFacePixmaps(const int id, QPixmap *on, QPixmap *off);
	const bool removeBuddy(const int id);   // completely deleted
	EvaBuddyItem *takeBuddy(const int id);  // disappear in this group, but item is still in memory
	const EvaBuddyItem *getBuddy(const int id); // won't disappear, just access the actuall item outside
	
	bool changeToOnline(const int id);
	bool changeToLeave(const int id);
	bool changeToOffline(const int id);
	bool changeToInvisible(const int id);
	bool startFlash(const int id);
	bool stopFlash(const int id);
	
	void showAll();
	void showOnlineOnly();
	void refreshFace();
	const int countOnlineFriends();
	void updateGroupTitle();
	
	void addQun(EvaQunItem *item) ;
	void addQun(QString name, const int id, QPixmap *pic = 0);
	void updateQun(QString name, const int id, QPixmap *pic=0);
	bool removeQun(const int id);
	bool clearQunGroup();
	bool hasQun(const int id);
	QString tip(); 
	const Type getType() const { return type; }
	void setType(const Type t) { type = t; }
	virtual QString key( int col, bool ascending) const;
protected:
	virtual void okRename(int col);
	virtual void cancelRename(int col);
private:
	EvaBuddyItem *findBuddy(const int id);
	EvaQunItem *findQun(const int id);
	const int messagsCount();
	static QPixmap *pixOpened;
	static QPixmap *pixClosed;
	QString groupName;
	int groupIndex;
	QTimer *timer;
	bool isMsgShown;
	static QPixmap *pixMsg;
	int numOnlineFriends;
	Type type;
private slots:
	void slotTimeout();
};

class EvaListView : public QListView 
{
	Q_OBJECT
public:
	EvaListView( QWidget *parent=0, const char *name =0, WFlags f= 0);
	~EvaListView();
	
	void setupPixmaps(QPixmap *gOpen, QPixmap *gClose, QPixmap *bNA, QPixmap *bMsg);
	bool addGroup(const QString &name, const int index);
	void changeGroupTo(const int id, const int index);
	void deleteGroup(const int index);
	bool addBuddy(const QString &nick, const int id, const QString signature, const int index= 0, 
			QPixmap *on =0, QPixmap *off=0, EvaBuddyItem::Status status = EvaBuddyItem::Offline);
	void updateNick(const int id, const QString &nick);
	void updateSignature(const int id, const QString &sig);
	void updateFacePixmaps(const int id, QPixmap *on, QPixmap *off);
	const std::list<std::string> getGroupNames(); // note that the string is encoded by "GB18030"
	const int getNumOfGroups() const;
	const std::map<int, int> getGroupedBuddy(); // the first is QQ, the second is group index
	
	const bool hasGroup(const int index);
	const bool hasBuddy(const int id);

	EvaGroupItem *findGroup(const int index);  // index is group index
	EvaGroupItem *findGroupByID(const int id); // id is QQ number
	
	bool changeToOnline(const int id);
	bool changeToLeave(const int id);
	bool changeToOffline(const int id);
	bool changeToInvisible(const int id);
	bool startFlash(const int id);
	bool stopFlash(const int id);
	bool startQunFlash(const int id);
	bool stopQunFlash(const int id);
		
	bool removeBuddy(const int id);
	void showAll();
	void showOnlineOnly();
	void refreshFace(const QSize &size);
	void setFaceSize(const QSize &size);
	
	void addQun(QString &name, const int id, QPixmap *pic);
	void updateQun(QString &name, const int id, QPixmap *pic);
	void removeQun(const int id);
	void clearQunList();
	void updateAllGroupTitles();
public slots:
	void clear();
signals:
	void groupChanged(int, int); // qq number, group index;
	void deleteMeFrom(int);  // ask server to delete me in someone's friend list
	void requestAddBuddy(const int);
protected:
	virtual void keyPressEvent( QKeyEvent *e );
	virtual void startDrag();
	virtual void dragEnterEvent(QDragEnterEvent *event);
	virtual void dropEvent(QDropEvent *event);
private:
	EvaBuddyItem *getBuddyRef(const int id);
	EvaGroupItem *updateGroupTitle(EvaBuddyItem *buddy, bool isGetGroupRefOnly = false);
	void closeAllGroups();
	std::map<const int, EvaBuddyItem *> buddyMap;
	int dId, dGroup;
	EvaToolTip *mToolTip;
	bool isShowOnlineOnly;
};

class EvaToolTip : public QToolTip
{
public:
	EvaToolTip(QListView *listView, QToolTipGroup *group = 0);
	virtual ~EvaToolTip();
protected:
	void maybeTip(const QPoint &p);
private:
	QListView *mListView;
};

class EvaQunItem :  public QObject, public QListViewItem
{
	Q_OBJECT
public:
	EvaQunItem( QListViewItem *parent, const QString &name, const int qunID, QPixmap *pic);
	static void setPixmapMsg( QPixmap *pic) { pixMsg = pic; }
	
	void setQunName(const QString &name);
	void setQunID(const int id) { qunID = id; }
	void setQunPix(QPixmap *pix);
	
	const QString &getQunName() const { return qunName; }
	const int getQunID() const { return qunID; }
	
	const bool hasMessages() const;
	QString tip(); 
public slots:
	void slotStartFlash();
	void slotStopFlash();
private:
	EvaGroupItem *groups;
	EvaGroupItem *discuss;
	QTimer *timer;
	bool isMsgShown;
	int qunID;
	QString qunName;
	QPixmap *qunPic;
	static QPixmap *pixMsg;
private slots:
	void slotTimeout();
};

#endif 
