#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 QString pixmap(bool mobile = false) const
			Zwraca nazwę ikonki reprezentującej ten status.
			\param mobile informuje czy ikona ma zawierać element telefonu komórkowego. Domyślnie FALSE.
			\return nazwa pixmapy reprezentującej ikonę.
		**/
		virtual QString pixmapName(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 QString pixmap(bool mobile = false) const
			Zwraca nazwę ikonki reprezentującej 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 nazwa pixmapy reprezentującej ikonę.
		**/
		virtual QString pixmapName(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 virtual QString pixmap(bool mobile = false) const
			Zwraca nazwę ikonki 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 nazwa pixmapy reprezentującej ikonę.
		**/
		virtual QString pixmapName(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
