/***************************************************************************
 *                                                                         *
 *   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 NOTIFICATION_H
#define NOTIFICATION_H

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

#include "userlist.h"

#include "../notify/notification.h"

class QTimer;

/**
	@class Notification
	@author Rafał 'Vogel' Malinowski
	@brief Klasa informująca użytkownika o zajściu pewnego zdarzenia.

	Zdarzenia identyfikowane są poprzez nazwy. Każde zdarzenie musi zostać zarejestrowane
	przed użyciem w klasie Notify a takze wyrejestrowane w przypadku wyładowania modułu,
	który wywoływał dane zdarzenie.

	Do każdego zdarzenia może być przypisana ikona, lista kontaktów oraz lista akcji, które użytkownik
	może podjąć w odpowiedzi na zdarzenie. Przykładowo, zdarzenie polegające na odebraniu wiadomości od
	anonimowego kontaktu, z którym nie prowadzimy aktualnie rozmowy może mieć postać:

	<ul>
		<li>nazwa: newChatWithAnonymous</li>
		<li>ikona: chat</li>
		<li>lista kontaktów: kontakt, który rozpoczął rozmowę</li>
		<li>akcja: odbierz komunikat</li>
		<li>akcja: ignoruj komunikat</li>
	</ul>

	Akcje użytkownika implementowane są w obiektach potomnych w postaci w postaci slotów.
	Domyślnie zaimplementowane są dwa sloty wirtualne: callbackAccept i callbackDiscard,
	odpowiadające zaakceptowaniu i odrzuceniu zdarzenia.

	Dodanie nowych akcji polega na dodaniu nowych slotów do klas potomnych. Aktywacja
	akcji (także tych dwóch domyślnych) dokonuje sie poprzez metodę addCallback(caption, slot),
	na przykład:

	<code>
		addCallback(tr("Odbierz rozmowę"), SLOT(callbackAccept()));
		addCallback(tr("Ignoruj rozmowę"), SLOT(callbackDiscard()));
	</code>

	Obiekty mogą automatycznie podejmować akcje domyślne po przekroczeniu pewnego
	okresu czasu:

	<code>
		setDefaultCallback(2000, SLOT(callbackAccept()));
	</code>

	Można takze anulować akcję domyślną:

	<code>
		clearDefaultCallback();
	</code>

	Notyfikacja, co do której pewna akcja została wykonana, wywołuje sygnał closed().
 **/
class Notification : public QObject {
	Q_OBJECT

private:

	QString Type;
	UserListElements Ule;

	QString Title;
	QString Text;
	QString Details;
	QString Icon;

	QValueList<QPair<QString, const char *> > Callbacks;
	QTimer *DefaultCallbackTimer;

	int ReferencesCount;
	bool Closing;

public:

	/**
		Tworzy nową notfikację o zadanym typie, ikonie i zadanej asocjacji z kontaktami.
		Klasy potome zazwyczaj mają własne kontruktory, które wypełniają automatycznie
		parametry tego konstruktora.

		@arg type typ zdarzenia
		@arg icon nazwa ikony zdarzenia
		@arg userListElements lista kontaktów powiązana ze zdarzeniem
	 **/
	Notification(const QString &type, const QString &icon, const UserListElements &userListElements);
	virtual ~Notification();

	/**
		Wywoływane przez notyfikator, który zajmuje się danym zdarzeniem.
	 **/
	void acquire();
	/**
		Wywoływane przez notyfikator, który przestaje zajmować się danym zdarzeniem.
		Gdy żaden notyfikator nie zajmuje się danym zdarzeniem, zdarzenie jest zwalniane.
		Występuje to na przykład w przypadku modułów dźwiękowych czy modułu hints, gdy
		dymek zniknie po upływie określonego czasu a nie przez zdarzenie wywołane przez użytkownika.
	 **/
	void release();

	/**
		Zamyka zdarzenie. Wywołuje sygnał closed() i usuwa obiekt.
	 **/
	void close();

	/**
		Usuwa akcje użytkownika
	 **/
	void clearCallbacks();
	/**
		Dodaje akcje użytkownika.

		@arg caption wyświetlana nazwa akcji
		@arg slot slot wywoływany w przypadku wybrania przez użytkownika danej akcji
	 **/
	void addCallback(const QString &caption, const char *slot);

	/**
		Ustawia akcję domyślną.

		@arg timeout liczba milisekund, jaka musi upłynąć przed wykonaniem domyślnej akcji
		@arg slot slot wywoływany w przypadku upłynięcia czasu
	 **/
	void setDefaultCallback(int timeout, const char *slot);

	/**
		Typ zdarzenia.

		@return typ zdarzenia
	 **/
	QString type() const;
	/**
		Lista kontaktów powiązana ze zdarzeniem/

		@return lista kontaktów powiązana ze zdarzeniem
	 **/
	const UserListElements &userListElements() const;

	/**
		Ustawia tytuł zdarzenia.
	 **/
	void setTitle(const QString &title);
	/**
		Tytuł zdarzenia.

		@return tytuł zdarzenia
	 **/
	QString title() const;

	/**
		Ustawia treść zdarzenia.
	 **/
	void setText(const QString &text);
	/**
		Treść zdarzenia.

		@return treść zdarzenia
	 **/
	QString text() const;

	/**
		Ustawia szczegóły zdarzenia (jak na przykład tekst wiadomości).
	 **/
	void setDetails(const QString &details);
	/**
		Szczegóły zdarzenia
	 **/
	QString details() const;

	/**
		Ustawia ikonę zdarzenia.
	 **/
	void setIcon(const QString &icon);
	/**
		Ikona zdarzenia.

		@return ikona zdarzenia
	 **/
	QString icon() const;

	/**
		Lista akcji.

		@return lista akcji
	 **/
	const QValueList<QPair<QString, const char *> > & getCallbacks();

public slots:
	/**
		Domyślny slot wywoływany w przypadku zaakceptowania zdarzenia.
	 **/
	virtual void callbackAccept();
	/**
		Domyślny slot wywoływany w przypadku odrzucenia zdarzenia.
	 **/
	virtual void callbackDiscard();

	/**
		Slot anulujący domyślną akcję - wywoływany ręcznie przy wyborze dowolnej innej akcji.
	 **/
	void clearDefaultCallback();

signals:
	/**
		Sygnał wysylany przy zamykaniu zdarzenia, po wyborze przez użytkownika dowolnej akcji.
	 **/
	void closed(Notification *);

};

#endif // NOTIFICATION_H
