/***************************************************************************
 *   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 EvaBuddyItem :  public QObject, public QListViewItem
{
	Q_OBJECT
public:
	enum Status {Online, Leave, Invisible, Offline };
	EvaBuddyItem( QListViewItem *parent, const QString &nick, const int id, 
			QPixmap *on =0, QPixmap *off=0, EvaBuddyItem::Status status = EvaBuddyItem::Offline);
	~EvaBuddyItem();
	
	void updateNick(const QString &nick);
	const QPixmap *pixmapOnline() const;
	const QPixmap *pixmapOffline() const;
	void setPixmapOnline( QPixmap *p);
	void setPixmapOffline( QPixmap *p) ;
	
	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(); 
	
	QString tip();
public slots:
	void slotChangeToOnline();
	void slotChangeToLeave();
	void slotChangeToOffline();
	void slotChangeToInvisible();
	void slotStartFlash();
	void slotStopFlash();

private:
	void updateFace(QPixmap *pix);
	QString key( int col, bool ascending) const;
	QTimer *timer;
	Status status;
	QPixmap *pixOnline;
	QPixmap *pixOffline;
	QString nickName;
	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:
	EvaGroupItem(QListView *parent, const QString &name, int index = 0);
	~EvaGroupItem(){};
	
	void setOpen(bool o);
	const int getGroupIndex() const;
	void setGroupIndex(const int index) { groupIndex = index; }
	const QString &getGroupName() const;
	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);
	void addBuddy(const QString &nick, const int id, QPixmap *on =0, QPixmap *off=0, EvaBuddyItem::Status status = EvaBuddyItem::Offline);
	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();
	QString tip(); 
protected:
	virtual void okRename(int col);
	virtual void cancelRename(int col);
private:
	QString key( int col, bool ascending) const;
	EvaBuddyItem *findBuddy(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;
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 int index= 0, 
			QPixmap *on =0, QPixmap *off=0, EvaBuddyItem::Status status = EvaBuddyItem::Offline);
	const std::list<std::string> getGroupNames(); // note that the string is encoded by "GBK"
	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) const;

	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 removeBuddy(const int id);
	void showAll();
	void showOnlineOnly();
	void refreshFace(const QSize &size);
	void setFaceSize(const QSize &size);
signals:
	void groupChanged(int, int); // qq number, group index;
	void deleteMeFrom(int);  // ask server to delete me in someone's friend list
	void requestAddBuddy(int);
protected:
	virtual void keyPressEvent( QKeyEvent *e );
	virtual void startDrag();
	virtual void dragEnterEvent(QDragEnterEvent *event);
	virtual void dropEvent(QDropEvent *event);
private:
	void closeAllGroups();
	int dId, dGroup;
	EvaToolTip *mToolTip;
};

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

#endif 
