/*
    kopetecontactlistview.h

    Kopete Contactlist GUI

    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002      by Nick Betcher <nbetcher@usinternet.com>
    Copyright (c) 2002      by Stefan Gehn <metz AT gehn.net>
    Copyright (c) 2002-2005 by Olivier Goffart <ogoffart @ kde.org>
    Copyright (c) 2004      by Richard Smith <kde@metafoo.co.uk>

    Kopete    (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>

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

#ifndef KOPETE_CONTACTLISTVIEW_H
#define KOPETE_CONTACTLISTVIEW_H

#include "kopetelistview.h"
#include "kopetemetacontact.h"

#include <tqpixmap.h>
#include <tqptrlist.h>
#include <tqstringlist.h>
#include <tqrect.h>
#include <tqtimer.h>
#include <tqguardedptr.h>

class KopeteMetaContactLVI;
class KopeteGroupViewItem;
class KopeteStatusGroupViewItem;
class KRootPixmap;
class TDEActionCollection;
class TDEAction;
class TDEListAction;
class TDEActionMenu;

class KopeteContactListViewPrivate;

namespace Kopete
{
class Contact;
class MetaContact;
class Group;
class MessageEvent;
}

/**
 * @author Duncan Mac-Vicar P. <duncan@kde.org>
 */
class KopeteContactListView : public Kopete::UI::ListView::ListView
{
	TQ_OBJECT
  

public:
	KopeteContactListView( TQWidget *parent = 0, const char *name = 0 );
	~KopeteContactListView();

	/**
	 * Init MetaContact related actions
	 */
	void initActions(TDEActionCollection*);

	/**
	 * Add a given group name and return it
	 */
	void addGroup( const TQString &groupName );

	/**
	 * Are we displaying as a tree view (true), or in a flat list (false)?
	 * @todo make this an enum
	 */
	bool showAsTree() { return mShowAsTree; }

public slots:
	/**
	 * Remove all KopeteMetaContactLVI of a metaContact
	 */
	void removeContact( Kopete::MetaContact *contact );

	/**
	 * Prompt the user for the group name (slot)
	 */
	void addGroup();

protected:
	virtual void contentsMousePressEvent( TQMouseEvent *e );

	virtual bool acceptDrag(TQDropEvent *e) const;

	/**
	 * Start a drag operation
	 * @return a KMultipleDrag containing: 1) A TQStoredDrag of type "application/x-qlistviewitem", 2) If the MC is associated with a KABC entry, i) a TQTextDrag containing their email address, and ii) their vCard representation.
	 */
	virtual TQDragObject *dragObject();

	/**
	 * Since KDE 3.1.1 ,  the original find Drop return 0L for afterme if the group is open.
	 * This woraround allow us to keep the highlight of the item, and give always a correct position
	 */
	virtual void findDrop(const TQPoint &pos, TQListViewItem *&parent, TQListViewItem *&after);

	/**
	 * The selected items have changed; update our actions to show what's possible.
	 */
	void updateActionsForSelection( TQPtrList<Kopete::MetaContact> contacts, TQPtrList<Kopete::Group> groups );

private slots:
	/**
	 * When an account is added, so we add it to the menu action
	 */
	void slotAddSubContactActionNewAccount(Kopete::Account*);
	/**
	 * When an account is destroyed, the child add subcontact action is deleted
	 * so we remove it from the menu action
	 */
	void slotAddSubContactActionAccountDeleted(const Kopete::Account *);

	void slotViewSelectionChanged();
	void slotListSelectionChanged();
	void slotContextMenu(TDEListView*,TQListViewItem *item, const TQPoint &point );
	void slotExpanded( TQListViewItem *item );
	void slotCollapsed( TQListViewItem *item );

	void slotSettingsChanged( void );
	void slotUpdateAllGroupIcons();
	void slotExecuted( TQListViewItem *item, const TQPoint &pos, int c );

	void slotAddedToGroup( Kopete::MetaContact *mc, Kopete::Group *to );
	void slotRemovedFromGroup( Kopete::MetaContact *mc, Kopete::Group *from );
	void slotMovedToGroup( Kopete::MetaContact *mc, Kopete::Group *from, Kopete::Group *to );

	/**
	 * A meta contact was added to the contact list - update the view
	 */
	void slotMetaContactAdded( Kopete::MetaContact *mc );
	void slotMetaContactDeleted( Kopete::MetaContact *mc );
	void slotMetaContactSelected( bool sel );

	void slotGroupAdded(Kopete::Group *);

	void slotContactStatusChanged( Kopete::MetaContact *mc );

	void slotDropped(TQDropEvent *e, TQListViewItem *parent, TQListViewItem*);

	void slotShowAddContactDialog();
	void slotNewMessageEvent(Kopete::MessageEvent *);

	/**
	 * Handle renamed items by renaming the meta contact
	 */
	void slotItemRenamed( TQListViewItem *item );

	/** Actions related slots **/
	void slotSendMessage();
	void slotStartChat();
	void slotSendFile();
	void slotSendEmail();
	void slotMoveToGroup();
	void slotCopyToGroup();
	void slotRemove();
	void slotRename();
	void slotAddContact();
	void slotAddTemporaryContact();
	void slotProperties();
	void slotUndo();
	void slotRedo();

	void slotTimeout();

private:
	bool mShowAsTree;

	// TODO: do we really need to store these?
	TQPtrList<KopeteMetaContactLVI> m_selectedContacts;
	TQPtrList<KopeteGroupViewItem> m_selectedGroups;

	bool mSortByGroup;
	KRootPixmap *root;

	TQRect m_onItem;

	TQPoint m_startDragPos;

	/* ACTIONS */
	TDEAction *actionSendMessage;
	TDEAction *actionStartChat;
	TDEAction *actionSendFile;
	TDEAction *actionSendEmail;
	TDEListAction *actionMove;
	TDEListAction *actionCopy;
	TDEAction *actionRename;
	TDEAction *actionRemove;
	TDEAction *actionAddTemporaryContact;
	TDEAction *actionProperties;
	TDEAction *actionUndo;
	TDEAction *actionRedo;

	KopeteContactListViewPrivate *d;

	void moveDraggedContactToGroup( Kopete::MetaContact *contact, Kopete::Group *from, Kopete::Group *to );
	void addDraggedContactToGroup( Kopete::MetaContact *contact, Kopete::Group *group );
	void addDraggedContactToMetaContact( Kopete::Contact *contact, Kopete::MetaContact *parent );
	void addDraggedContactByInfo( const TQString &protocolId, const TQString &accountId,
		const TQString &contactId, TQListViewItem *after );

public:
	struct UndoItem;
	UndoItem *m_undo;
	UndoItem *m_redo;
	void insertUndoItem(UndoItem *u);
	TQTimer undoTimer;

public:
	// This is public so the chatwinodw can handle sub actions
	// FIXME: do we not believe in accessor functions any more?
	TDEActionMenu *actionAddContact;
	TQMap<const Kopete::Account *, TDEAction *> m_accountAddContactMap;
};

struct KopeteContactListView::UndoItem
{
	enum Type { MetaContactAdd, MetaContactRemove , MetaContactCopy , MetaContactRename, MetaContactChange, ContactAdd, GroupRename } type;
	TQStringList args;
	TQGuardedPtr<Kopete::MetaContact> metacontact;
	TQGuardedPtr<Kopete::Group> group;
	UndoItem *next;
	bool isStep;
	Kopete::MetaContact::PropertySource nameSource;

	UndoItem() : isStep(true) {}
	UndoItem(Type t, Kopete::MetaContact *m=0L ,Kopete::Group *g=0L)
	{
		isStep=true;
		type=t;
		metacontact=m;
		group=g;
		next=0L;
	}
};


#endif
