#ifndef KADU_STATUS_H
#define KADU_STATUS_H

#include <qobject.h>
#include <qpixmap.h>
#include <qstring.h>
#include <qstringlist.h>

/**
	\enum eUserStatus
	Opisuje stan statusu.
**/
enum eUserStatus
{
	Online, /*!< Dostępny */
	Busy, /*!< Zaraz wracam */
	Invisible, /*!< Ukryty */
	Offline, /*!< Niedostępny */
	Blocking /*!< Blokujący */
};

/**
	Klasa ta zawiera informacje o statusie kontaktu lub użytkownika Kadu, oraz metody
	służące do zmiany tego statusu.
	\class UserStatus
	\brief Klasa opisująca status.
**/
class UserStatus : public QObject
{
	Q_OBJECT

	private:
		bool Changed;

	protected:
		/**
			\var eUserStatus Stat
			Zawiera informację o aktualnym statusie w postaci enumerycznej.
		**/
		eUserStatus Stat;

		/**
			\var QString Description
			Zawiera aktualny opis.
		**/
		QString Description;

		/**
			\var bool FriendsOnly
			Zawiera informację o trybie "tylko dla znajomych".
		**/
		bool FriendsOnly;

	public:
		/**
			\fn UserStatus()
			Standardowy konstruktor.
		**/
		UserStatus();

		/**
			\fn UserStatus(const UserStatus &copyMe)
			Konstruktor kopiujący.
			\param copyMe obiekt który chcemy skopiować.
		**/
		UserStatus(const UserStatus &copyMe);

		/**
			\fn void operator = (const UserStatus &copyMe)
			Operator kopiujący.
			\param copyMe obiekt który chcemy skopiować.
		**/
		UserStatus &operator = (const UserStatus &copyMe);

		/**
			\fn bool operator == (const UserStatus &compare) const
			Operator porównujący. Sprawdza tożsamość obiektów.
			\param compare obiekt z którym chcemy porównać bierzący obiekt.
		**/
		bool operator == (const UserStatus &compare) const;

		/**
			\fn bool operator != (const UserStatus &compare) const
			Operator porównujący. Sprawdza różnicę pomiędzy obiektami.
			\param compare obiekt z którym chcemy porównać bierzący obiekt.
		**/
		bool operator != (const UserStatus &compare) const;

		/**
			\fn virtual UserStatus *copy() const
			Wykonuje kopię obiektu, którą później należy samodzielnie zniszczyć
		**/
		virtual UserStatus *copy() const;

		virtual ~UserStatus();

		/**
			\fn bool isOnline() const
			Sprawdza czy kontakt jest "dostępny".
			\return TRUE jeśli jest "dostępny", FALSE w przeciwnym wypadku.
		**/
		bool isOnline() const;

		/**
			\fn bool isBusy() const
			Sprawdza czy kontakt ma status "zaraz wracam".
			\return TRUE jeśli ma status "zaraz wracam", FALSE w przeciwnym wypadku.
		**/
		bool isBusy() const;

		/**
			\fn bool isInvisible() const
			Sprawdza czy kontakt jest "ukryty".
			\return TRUE jeśli jest "ukryty", FALSE w przeciwnym wypadku.
		**/
		bool isInvisible() const;

		/**
			\fn bool isOffline() const
			Sprawdza czy kontakt jest "niedostępny".
			\return TRUE jeśli jest "niedostępny", FALSE w przeciwnym wypadku.
		**/
		bool isOffline() const;

		/**
			\fn bool isBlocking() const
			Sprawdza czy kontakt jest "blokujący".
			\return TRUE jeśli jest "blokujący", FALSE w przeciwnym wypadku.
		**/
		bool isBlocking() const;

		/**
			\fn static bool isOffline(int index)
			Sprawdza czy status dany w postaci indeksowej jest statusem "niedostępny" lub jego
			odpowiednikiem z opisem.
			\return TRUE jeśli status oznacza "niedostępny", FALSE w przeciwnym wypadku.
		**/
		static bool isOffline(int index);

		/**
			\fn bool hasDescription() const
			Sprawdza czy status jest z opisem.
			\return TRUE gdy status jest z opisem, FALSE w przeciwnym wypadku.
		**/
		bool hasDescription() const;

		/**
			\fn bool isFriendsOnly() const
			Sprawdza czy status jest "tylko dla znajomych".
			\return TRUE jeśli jest "tylko dla znajomych", FALSE w przeciwnym wypadku.
		**/
		bool isFriendsOnly() const;

		/**
			\fn QString description() const
			\return opis, o ile status jest z opisem, lub "" gdy opisu nie ma.
		**/
		QString description() const;

		/**
			\fn eUserStatus status() const
			\return status w postaci enumeracyjnej.
		**/
		eUserStatus status() const;

		/**
			\fn int index() const
			\return status w postaci indeksowej.
		**/
		int index() const;

		/**
			\fn static int index(eUserStatus stat, bool has_desc)
			Zamienia enumeracyjną postać statusu na indeksową.
			\param stat enumeracyjna postać statusu.
			\param has_desc informuje, czy jest to odmiana statusu z opisem.
			\return status w postaci indeksowej.
		**/
		static int index(eUserStatus stat, bool has_desc);

		/**
			\fn virtual QPixmap pixmap(bool mobile = false) const
			Zwraca ikonę reprezentującą ten status.
			\param mobile informuje czy ikona ma zawierać element telefonu komórkowego. Domyślnie FALSE.
			\return pixmapę reprezentującą ikonę.
		**/
		virtual QPixmap pixmap(bool mobile = false) const;

		/**
			\fn virtual QPixmap pixmap(const UserStatus &stat, bool mobile = false) const
			Zwraca ikonę reprezentującą dany status.
			\param stat status którego ikonę należy zwrócić
			\param mobile informuje czy ikona ma zawierać element telefonu komórkowego. Domyślnie FALSE.
			\return pixmapę reprezentującą ikonę.
		**/
		virtual QPixmap pixmap(const UserStatus &, bool mobile = false) const;

		/**
			\fn virtual QPixmap pixmap(eUserStatus stat, bool has_desc, bool mobile = false) const
			Zwraca ikonę reprezentującą dany status.
			\param stat status w postaci enumeracyjnej którego ikonę należy zwrócić
			\param has_desc informuje, czy jest to odmiana statusu z opisem.
			\param mobile informuje czy ikona ma zawierać element telefonu komórkowego. Domyślnie FALSE.
			\return pixmapę reprezentującą ikonę.
		**/
		virtual QPixmap pixmap(eUserStatus stat, bool has_desc, bool mobile = false) const;

		/**
			\fn static eUserStatus fromString(const QString& stat)
			Zamienia status z formy łańcucha znaków na postać enumeracyjną.
			\param stat łańcuch znaków reprezentujący nazwę statusu. Poprawne nazwy statusów to:
				\arg \c Online
				\arg \c Busy
				\arg \c Invisible
				\arg \c Blocking
			\return enumeracyjna postać statusu.
		**/
		static eUserStatus fromString(const QString& stat);

		/**
			\fn static QString toString(eUserStatus stat, bool has_desc)
			Zamienia status z postaci enumeracyjnej na formę łańcucha znaków.
			\param stat postać enumeracyjna statusu
			\param has_desc informuje, czy jest to odmiana statusu z opisem.
			\return enumeracyjna postać statusu.
		**/
		static QString toString(eUserStatus stat, bool has_desc);

		/**
			\fn QString toString(eUserStatus stat, bool has_desc)
			Zamienia status na formę łańcucha znaków.
			robi dokładnie tyle co UserStatus::toString(this->status(), this->hasDescription())
			\see toString(eUserStatus, bool)
			\return status w postaci napisu.
		**/
		QString toString() const;

		/**
			\fn static int count()
			\return liczbę wszystkich możliwych statusów, łącznie z "blokowany" oraz "niedostępny z opisem".
		**/
		static int count();

		/**
			\fn static int count()
			\return liczbę wszystkich możliwych statusów, które może zobaczyć użytkownik Kadu po ustawieniu danego,
				a więc wyłączając "blokowany" oraz "niedostępny z opisem".
		**/
		static int initCount();

		/**
			\fn static QString name(int nr)
			Zamienia dany status z postaci indeksowej na formę łańcucha znaków. Postać indeksowa musi mieścić się
			w liczbie zwróconej przez UserStatus::count() (musi być przynajmniej o 1 mniejsza od tej liczby).
			\return status w postaci łańcucha znaków.
		**/
		static QString name(int nr);

		/**
			\fn QString name() const
			Zamienia aktualny status z postaci indeksowej na formę łańcucha znaków.
			\return status w postaci łańcucha znaków.
		**/
		QString name() const;

		/**
			\fn void refresh()
			Odświeża aktualny status.
		**/
		void refresh();

		/**
			\fn virtual QString protocolName() const;
			Zwraca identyfikator protokołu.
		**/
		virtual QString protocolName() const;

	public slots:
		/**
			\fn void setOnline(const QString& desc = "")
			Ustawia status na "dostępny" z ewentualnym opisem.
			\param desc opcjonalny opis. Domyślnie brak.
		**/
		void setOnline(const QString& desc = QString::null);

		/**
			\fn void setBusy(const QString& desc = "")
			Ustawia status na "zaraz wracam" z ewentualnym opisem.
			\param desc opcjonalny opis. Domyślnie brak.
		**/
		void setBusy(const QString& desc = QString::null);

		/**
			\fn void setInvisible(const QString& desc = "")
			Ustawia status na "ukryty" z ewentualnym opisem.
			\param desc opcjonalny opis. Domyślnie brak.
		**/
		void setInvisible(const QString& desc = QString::null);

		/**
			\fn void setOffline(const QString& desc = "")
			Ustawia status na "niedostępny" z ewentualnym opisem.
			\param desc opcjonalny opis. Domyślnie brak.
		**/
		void setOffline(const QString& desc = QString::null);

		/**
			\fn void setBlocking()
			Ustawia tryb blokujący statusu.
		**/
		void setBlocking();

		/**
			\fn void setDescription(const QString& desc = "")
			Ustawia opis dla statusu.
			\param desc opcjonalny opis. Domyślnie pusty.
		**/
		void setDescription(const QString& desc = QString::null);

		/**
			\fn void setStatus(const UserStatus& stat)
			Ustawia status na dany.
			\param stat status który chcemy ustawić
		**/
		void setStatus(const UserStatus& stat);

		/**
			\fn void setStatus(eUserStatus stat, const QString& desc = "")
			Ustawia status na dany.
			\param stat enumeracyjna postać statusu.
				\arg \c Online - Dostępny
				\arg \c Busy - Zaraz wracam
				\arg \c Invisible - Ukryty
				\arg \c Blocking - Blokujący
				\arg \c Offline - Nidostępny
			\param desc opcjonalny opis. Domyślnie brak.
		**/
		void setStatus(eUserStatus stat, const QString& desc = QString::null);

		/**
			\fn void setIndex(int index, const QString& desc = "")
			Ustawia status na dany.
			\param index indeksowa postać statusu.
			\note parzyste indeksy odpowiadają statusom bez opisów.
			\param desc opcjonalny opis. Domyślnie pusty.
		**/
		void setIndex(int index, const QString& desc = QString::null);

		/**
			\fn void setFriendsOnly(bool f)
			Ustawia tryb "tylko dla znajomych".
			\param f wartość logiczna informująca o tym, czy status ma mieć włączony ten tryb, czy nie.
		**/
		void setFriendsOnly(bool f);

	signals:
		/**
			\fn void goOnline(const QString& desc)
			Sygnał emitowany, gdy status jest zmieniany na "dostępny".
			\param desc Opcjonalny opis. Może mieć wartość "" jeśli status jest bezopisowy.
		**/
		void goOnline(const QString& desc);

		/**
			\fn void goBusy(const QString& desc)
			Sygnał emitowany, gdy status jest zmieniany na "zaraz wracam".
			\param desc Opcjonalny opis. Może mieć wartość "" jeśli status jest bezopisowy.
		**/
		void goBusy(const QString& desc);

		/**
			\fn void goInvisible(const QString& desc)
			Sygnał emitowany, gdy status jest zmieniany na "ukryty".
			\param desc Opcjonalny opis. Może mieć wartość "" jeśli status jest bezopisowy.
		**/
		void goInvisible(const QString& desc);

		/**
			\fn void goOffline(const QString& desc)
			Sygnał emitowany, gdy status jest zmieniany na "niedostępny".
			\param desc Opcjonalny opis. Może mieć wartość "" jeśli status jest bezopisowy.
		**/
		void goOffline(const QString& desc);

		/**
			\fn void goBlocking()
			Sygnał jest emitowany, kiedy tryb blokujący zostaje włączony w tym statusie.
		**/
		void goBlocking();

		/**
			\fn void changed(const UserStatus& status)
			Sygnał jest emitowany, gdy status został zmieniony na którykolwiek.
			\param status status, na który dokonano zmiany
			\param oldStatus status, z którego dokonano zmiany
		**/
		void changed(const UserStatus &status, const UserStatus &oldStatus);
};

extern QStringList defaultdescriptions;

#endif
