#ifndef KADU_GROUPS_MANAGER_H
#define KADU_GROUPS_MANAGER_H

#include <qmap.h>
#include <qobject.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtimer.h>
#include <qvariant.h>

#include "usergroup.h"
#include "userlistelement.h"

class KaduTabBar;

/**
	Klasa służąca przede wszystkim zarządzaniu nazwanymi grupami kontaktów,
	ale także zarządza grupami typu: blokowani, blokujący, tylko z opisami, tylko dostępni, anonimowi
	\class GroupsManager
	\brief
**/
class GroupsManager : public QObject
{
	Q_OBJECT
	public:
		/**
			\fn static void initModule()
			inicjuje moduł zarządcy grup
		**/
		static void initModule();

		/**
			\fn static void closeModule()
			sprząta po module zarządcy grup
		**/
		static void closeModule();

		/**
			\fn UserGroup *group(const QString &name) const
			zwraca grupę kontaktów o nazwie name
			\param name nazwa grupy
			\return grupa kontaktów
		**/
		UserGroup *group(const QString &name) const;

		/**
			\fn UserGroup *addGroup(const QString &name)
			dodaje nową grupę kontaktów o nazwie name
			\param name nazwa grupy
			\return grupa kontaktów
		**/
		UserGroup *addGroup(const QString &name);

		/**
			\fn void removeGroup(const QString &name)
			usuwa grupę kontaktów o nazwie name
			\param name nazwa grupy
		**/
		void removeGroup(const QString &name);

		/**
			\fn void setTabBar(KaduTabBar *bar)
			ustawia pas zakładek, na którym klasa będzie operować oraz inicjuje
			wewnętrzne dane klasy
			\param bar pas zakładek, w którym będę umieszczane zakładki grup
		**/
		void setTabBar(KaduTabBar *bar);

		/**
			\fn QStringList groups() const
			\return lista grup
		**/
		QStringList groups() const;

		/**
			\fn bool groupExists(const QString &name)
			\param name nazwa grupy
			\return informacja czy grupa istnieje
		**/
		bool groupExists(const QString &name);

		/**
			\fn QString currentGroupName() const
			\return nazwa aktualnie wybranej grupy
		**/
		QString currentGroupName() const;

	public slots:

		/**
			\fn void setActiveGroup(const QString &name)
			ustawia aktywną grupę na name
			\param name nazwa grupy
		**/
		void setActiveGroup(const QString& group);

		/**
			\fn void refreshTabBar()
			odświeża pasek zakładek grup
		**/
		void refreshTabBar();

		/**
			\fn void refreshTabBarLater()
			odświeża pasek zakładek grup, ale po zakończeniu bieżacych operacji
		**/
		inline void refreshTabBarLater() { refreshTimer.start(0, true); }

		/**
			\fn void changeDisplayingBlocking()
			włącza lub wyłącza wyświetlanie kontaktów blokujących
			w głównej liście kontaktów w zależności od poprzedniego stanu
		**/
		void changeDisplayingBlocking();

		/**
			\fn void changeDisplayingBlocked()
			włącza lub wyłącza wyświetlanie kontaktów blokowanych
			w głównej liście kontaktów w zależności od poprzedniego stanu
		**/
		void changeDisplayingBlocked();

		/**
			\fn void changeDisplayingOffline()
			włącza lub wyłącza wyświetlanie kontaktów niedostępnych
			w głównej liście kontaktów w zależności od poprzedniego stanu
		**/
		void changeDisplayingOffline();

		/**
			\fn void changeDisplayingWithoutDescription()
			włącza lub wyłącza wyświetlanie kontaktów o statusach bez opisu
			w głównej liście kontaktów w zależności od poprzedniego stanu
		**/
		void changeDisplayingWithoutDescription();

	private slots:
		void userDataChanged(UserListElement elem, QString name, QVariant oldValue,
							QVariant currentValue, bool massively, bool last);
		void userAddedToMainUserlist(UserListElement elem, bool massively, bool last);

		void userAdded(UserListElement elem, bool massively, bool last);
		void userRemoved(UserListElement elem, bool massively, bool last);

		void tabSelected(int id);

		void onApplyTabGeneral();

	private:
		GroupsManager();
		~GroupsManager();
		QMap<QString, UserGroup *> Groups;
		KaduTabBar *GroupBar;
		int lastId;
		QString currentGroup;
		bool showBlocked;
		bool showBlocking;
		bool showOffline;
		bool showWithoutDescription;
		QTimer refreshTimer;
};
extern GroupsManager *groups_manager;

/**
	\class UsersWithDescription
	Klasa grupująca kontakty o statusie z opisem,
	automatycznie synchronizująca się z główną listą kontaktów
**/
class UsersWithDescription : public UserGroup
{
	Q_OBJECT
	public:
		UsersWithDescription();
		virtual ~UsersWithDescription();
	private slots:
		void statusChangedSlot(UserListElement elem, QString protocolName,
							const UserStatus &oldStatus, bool massively, bool last);
};
extern UsersWithDescription *usersWithDescription;

/**
	\class OnlineUsers
	Klasa grupująca kontakty o statusie "dostępny" lub "zajęty",
	automatycznie synchronizująca się z główną listą kontaktów
**/
class OnlineUsers : public UserGroup
{
	Q_OBJECT
	public:
		OnlineUsers();
		virtual ~OnlineUsers();
	private slots:
		void statusChangedSlot(UserListElement elem, QString protocolName,
							const UserStatus &oldStatus, bool massively, bool last);
};
extern OnlineUsers *onlineUsers;

/**
	\class BlockedUsers
	Klasa grupująca kontakty, które są blokowane,
	automatycznie synchronizująca się z główną listą kontaktów
**/
class BlockedUsers : public UserGroup
{
	Q_OBJECT
	public:
		BlockedUsers();
		virtual ~BlockedUsers();
	private slots:
		void protocolUserDataChangedSlot(QString protocolName, UserListElement elem,
							QString name, QVariant oldValue, QVariant currentValue,
							bool massively, bool last);
};
extern BlockedUsers *blockedUsers;

/**
	\class BlockingUsers
	Klasa grupująca kontakty o statusie blokującym,
	automatycznie synchronizująca się z główną listą kontaktów
**/
class BlockingUsers : public UserGroup
{
	Q_OBJECT
	public:
		BlockingUsers();
		virtual ~BlockingUsers();
	private slots:
		void statusChangedSlot(UserListElement elem, QString protocolName,
							const UserStatus &oldStatus, bool massively, bool last);
};
extern BlockingUsers *blockingUsers;

/**
	\class AnonymousUsers
	Klasa grupująca kontakty anonimowe,
	automatycznie synchronizująca się z główną listą kontaktów
**/
class AnonymousUsers : public UserGroup
{
	Q_OBJECT
	public:
		AnonymousUsers();
		virtual ~AnonymousUsers();
	private slots:
		void userDataChangedSlot(UserListElement elem,
							QString name, QVariant oldValue, QVariant currentValue,
							bool massively, bool last);
		void userAdded(UserListElement elem, bool massively, bool last);
		void removingUser(UserListElement elem, bool massively, bool last);
};
extern AnonymousUsers *anonymousUsers;

/**
	\class AnonymousUsersWithoutMessages
	Klasa grupująca kontakty anonimowe, nie mające wiadomości do odebrania
	automatycznie synchronizująca się z główną listą kontaktów
**/
class AnonymousUsersWithoutMessages : public UserGroup
{
	Q_OBJECT
	public:
		AnonymousUsersWithoutMessages();
		virtual ~AnonymousUsersWithoutMessages();
	private slots:
		void messageFromUserAdded(UserListElement elem);
		void messageFromUserDeleted(UserListElement elem);

		void userDataChangedSlot(UserListElement elem,
							QString name, QVariant oldValue, QVariant currentValue,
							bool massively, bool last);
		void userAdded(UserListElement elem, bool massively, bool last);
		void removingUser(UserListElement elem, bool massively, bool last);
};
extern AnonymousUsersWithoutMessages *anonymousUsersWithoutMessages;

#endif
