#ifndef KADU_CHAT_H
#define KADU_CHAT_H

#include <qdatetime.h>
#include <qstring.h>
#include <qmainwindow.h>
#include <qvaluelist.h>

#include "config_file.h"
#include "custom_input.h"
#include "emoticons.h"
#include "gadu.h"
#include "usergroup.h"

class QAccel;
class QHBox;
class QMimeSourceFactory;
class QObject;
class QPushButton;

class Chat;
class ChatManager;
class ChatMessage;
class ChatStyle;
class ColorSelector;
class EmoticonSelector;
class KaduSplitter;
class KaduTextBrowser;
class OwnChatColors;
class UserBox;
class UserChatColors;

/** \typedef QValueList<Chat*> ChatList */
typedef QValueList<Chat*> ChatList;

/**
	Klasa tworząca okno rozmowy, rejestrująca przyciski,
	formatująca wiadomość itp.
	\class Chat
	\brief Okno rozmowy
**/

class Chat : public QMainWindow
{
	Q_OBJECT

	private:
		friend class ChatManager;

		QValueList<ChatMessage *> ChatMessages; /*!< wiadomości wpisane
							w oknie rozmowy */

		UserGroup *Users; /*!< lista użytkowników w danym oknie */
		int index;	/*!< nr okna (z chat menadżera) */
		QString title_buffer; /*!< tytuł okna */
		QTimer* title_timer;  /*!< zmienna przechowująca czas od ostatniego
					odświeżenia tytułu okna */
		QColor actcolor; /*!< zmienna przechowująca aktualny kolor */

		CustomInput* Edit; /*!< okno do wpisywania wiadomości */
		QMimeSourceFactory *bodyformat; /*!< zmienna ustawiająca format */
		EmoticonSelector* emoticon_selector; /*!< okienko do
							wyboru emotikonek */
		ColorSelector* color_selector; /*!< okienko do wyboru koloru */
		bool AutoSend; /*!< określa czy Return powoduje wysłanie wiadomości */
		bool ScrollLocked; /*!< blokuje przewijanie okna rozmowy */
		bool WaitingForACK;
		UserBox* userbox; /*!< lista kontaktów przydatna gdy jesteśmy w
						 konferencji */
		QString myLastMessage;/*!< zmienna przechowująca
					naszą ostatnią wiadomość */
		unsigned int myLastFormatsLength; /* ?? */
		void* myLastFormats; /* ?? */
		int seq; /* ?? */
		KaduSplitter *vertSplit, *horizSplit; /*!< obiekty oddzielające
							 kontrolki od siebie */
		int ParagraphSeparator; /*!< odstęp między kolejnymi wypowiedziami */

		QDateTime lastMsgTime; /*!< czas ostatniej wiadomości */

		//pomijanie nagłówków w wiadomościach
		QString PreviousMessage;           //pamiętamy od kogo była ostatnia wiadomość
		bool CfgNoHeaderRepeat; /*!< określa czy używamy usuwania nagłówków */
		int CfgHeaderSeparatorHeight; /*!< wysokość separatora nagłówków */
		int CfgNoHeaderInterval; /*!< interwał po jakim przywracany jest nagłówek */

		ChatStyle* Style; /*!< styl okna rozmowy */

		time_t LastTime;

		/**
			\fn void pruneWindow()
			Funkcja czyszcząca okno rozmowy
		**/
		void pruneWindow();

		KaduTextBrowser* body; /*!< historia rozmowy, proszę NIE dawać dostępu na zewnątrz do tej zmiennej */

	private slots:

		/**
			\fn void changeColor()
			Slot zmieniający kolor czcionki
		**/
		void changeColor(const QWidget* activating_widget);

		/**
			\fn void addMyMessageToHistory()
			Slot dodaje wysłaną wiadomość do historii rozmowy
		**/
		void addMyMessageToHistory();

		/**
			\fn void pageUp()
			Slot przewijający historię rozmowy w górę
		**/
		void pageUp();

		/**
			\fn void pageDown()
			Slot przewijający historię rozmowy w dół
		**/
		void pageDown();

		/**
			\fn void imageReceivedAndSaved(UinType sender,uint32_t size,uint32_t crc32,const QString& path)
			Slot obsługujący odebranie i zapis obrazka
			\param sender osoba, która wysłała obrazek
			\param size rozmiar obrazka
			\param crc32 suma kontrolna obrazka
			\param path ścieżka do obrazka
		**/
		void imageReceivedAndSaved(UinType sender,uint32_t size,uint32_t crc32,const QString& path);

		/**
			\fn void connectAcknowledgeSlots();
			Slot podłączający potwierdzenie dostarczenia wiadomości
		**/
		void connectAcknowledgeSlots();

		/**
			\fn void disconnectAcknowledgeSlots();
			Slot odłączający potwierdzenie dostarczenia wiadomości
		**/
		void disconnectAcknowledgeSlots();

		void selectedUsersNeeded(const UserGroup*& user_group);

	protected:
		/**
			\fn virtual void closeEvent(QCloseEvent* e)
			Funkcja obsługująca zamknięcie okna
		**/
		virtual void closeEvent(QCloseEvent* e);

		/**
			\fn virtual void windowActivationChange(bool oldActive)
			Funkcja sterująca mruganiem napisu okna
		**/
		virtual void windowActivationChange(bool oldActive);

		/**
			\fn virtual void keyPressEvent(QKeyEvent* e)
			Funkcja obsługująca naciśnięcie przycisku
			\param e wskaźnik do obiektu obsługującego klawisze
		**/
		virtual void keyPressEvent(QKeyEvent* e);

		/**
			\fn virtual void keyReleaseEvent(QKeyEvent* e)
			Funkcja obsługująca zwolnienie przycisku
			\param e wskaźnik do obiektu obsługującego klawisze
		**/
		virtual void mouseReleaseEvent(QMouseEvent *e);
		
		bool keyPressEventHandled(QKeyEvent *);

	public:

		/**
			Konstruktor okna rozmowy
			\fn Chat(UserListElements usrs, QWidget* parent = 0, const char* name = 0)
			\param usrs lista kontaktów, z którymi prowadzona jest rozmowa
			\param parent rodzic okna
			\param name nazwa obiektu
		**/
		Chat(UserListElements usrs, QWidget* parent = 0, const char* name = 0);

		/**
			\fn ~Chat()
			Destruktor okna rozmowy
		**/
		~Chat();

		/**
			\fn void formatMessages(QValueList<ChatMessage *> &msgs)
			Formatuje wszystkie wiadomości na html'a,
			dodaje kolory tła i czcionek
			\param msgs lista wiadomości do sformatowania
		**/
		void formatMessages(QValueList<ChatMessage *> &msgs);
		/**
			\fn void formatMessage(ChatMessage& msg,
				const OwnChatColors* own_colors = NULL,
				const UserChatColors* user_colors = NULL,
				EmoticonsStyle style = (EmoticonsStyle)
					config_file.readNumEntry("Chat","EmoticonsStyle"));

			Formats message to html
			\param msg message to be formatted
			\param own_colors our chat colors
			\param user_colors user chat colors
			\param style emoticons style
		**/
		void formatMessage(ChatMessage& msg,
			const OwnChatColors* own_colors = NULL,
			const UserChatColors* user_colors = NULL,
			EmoticonsStyle style = (EmoticonsStyle)
				config_file.readNumEntry("Chat","EmoticonsStyle"));

		/**
			\fn void newMessage(const QString &protocolName, UserListElements senders, const QString &msg, time_t time)
			Dodaje wiadomość do okna
			\param protocolName nazwa protokołu
			\param senders lista użytkowników
			\param msg wiadomośc
			\param time czas
		**/
		void newMessage(const QString &protocolName, UserListElements senders, const QString &msg, time_t time);

		/**
			\fn void writeMessagesFromHistory(UserListElements senders, time_t time)
			Wpisuje do okna historię rozmowy
			\param senders lista użytkowników identyfikujących okno
			\param time ..
		**/
		void writeMessagesFromHistory(UserListElements senders, time_t time);

		/**
			\fn const UserGroup *users() const
			Zwraca listę numerów rozmowców.
		**/
		const UserGroup *users() const;

		/**
			\fn QValueList<ChatMessage*>& chatMessages()
			Daje dostęp do wiadomości aktualnie przechowywanych
			w oknie chat. Metody tej można użyć do zmiany treści
			lub właściwości którejś z wiadomości w odpowiedzi
			na jakieś zdarzenie.
		**/
		QValueList<ChatMessage*>& chatMessages();

		/**
			\fn void repaintMessages()
			Odświeża zawartość okna uwzględniając ewentualne
			zmiany dokonane w którejś wiadomości z listy
			uzyskanej za pomocą metody chatMessages(),
			dodanie nowych wiadomości lub usunięcie istniejących.
		**/
		void repaintMessages();

		/**
			\fn const QString& title() const
			Zwraca aktualny tytuł okna
		**/
		const QString& title() const;

		/**
			\fn CustonInput* edit()
			Zwraca wskaźnik do okna wpisywania wiadomości
		**/
		CustomInput* edit();

		/**
			\fn bool autoSend() const
			Zwraca wartość określającą, czy Return powoduje
			wysłanie wiadomości.
		**/
		bool autoSend() const;

		bool waitingForACK() const;

		virtual void dragEnterEvent(QDragEnterEvent *e);
		virtual void dropEvent(QDropEvent *e);
		virtual void dragMoveEvent(QDragMoveEvent *e);

		void scrollHistoryToBottom();
		virtual bool eventFilter(QObject *watched, QEvent *e);

	public slots:

		/**
			\fn void changeAppearance()
			Slot zmieniający kolory i czcionki w oknie
		**/
		void changeAppearance();

		/**
			\fn void refreshTitle()
			Slot ustawiający tytuł okna zgodnie z konfiguracją
		**/
		void refreshTitle();

		/**
			\fn void addEmoticon(QString)
			Slot dodaje ikonke do pola wpisywania wiadomości
			\param emot ikonka np. <lol>
		**/
		void addEmoticon(QString);

		/**
			\fn void scrollMessages(const QValueList<ChatMessage *> &)
			Slot dodaj wiadomości do okna
			\param messages lista wiadomości
		**/
		void scrollMessages(const QValueList<ChatMessage *> &);

		/**
			\fn void alertNewMessage()
			Slot informujący o nowej wiadomości
			mruganie jeśli okno jest nieaktywne
		**/
		void alertNewMessage();

		/**
			\fn void sendMessage()
			Slot wywoływany po naciśnięciu przycisku
			do wysyłania wiadomości
		**/
		void sendMessage();

		/**
			\fn void cancelMessage()
			Slot wywoływany po naciśnieciu przycisku anulowania
			wysyłaniu wiadomości
		**/
		void cancelMessage();

		/**
			\fn void writeMyMessage()
			Slot wpisujący wiadomość do okna
			\see sendMessage
		**/
		void writeMyMessage();

		/**
			\fn void changeTitle()
			Slot zmieniający tytuł
			\see setTitle
		**/
		void changeTitle();

		/**
			\fn void curPosChanged(int para, int pos)
			Slot wywoływany kiedy pozycja kursosa zmieniła się
			\param  para nie obslugiwane
			\param pos nie obslugiwane
		**/
		void curPosChanged(int para, int pos);

		/**
			\fn void specialKeyPressed(int key)
			Slot zostaje wywołany gdy naciśnięto specjalny klawisz (skrót)
			odpowiadający np KEY_BOLD
			\param key wartość naciśniętego specjalnego klawisza
		**/
		void specialKeyPressed(int key);

		/**
			\fn void colorChanged(const QColor& color)
			Slot zostaje wywołwany gdy użytkownik zmienił kolor czcionki
			którą będzie pisał
			\param color wartość zmienionego koloru
		**/
		void colorChanged(const QColor& color);

		/**
			\fn void colorSelectorAboutToClose()
			Slot zostaje wywołany przy zamykaniu okna wyboru ikonek
		**/
		void colorSelectorAboutToClose();

		/**
			\fn void messageBlockedSlot(int seq, UinType uin)
			Slot zostaje wywołany gdy nasza wiadomość została zablokowana
			przez serwer
			\param seq
			\param uin
		**/
		void messageBlockedSlot(int seq, UinType uin);

		/**
			\fn void messageBoxFullSlot(int seq, UinType uin)
			Slot zostaje wywołany gdy skrzynka na wiadomości
			została zapełniona
			\param seq
			\param uin
		**/
		void messageBoxFullSlot(int seq, UinType uin);

		/**
			\fn void messageNotDeliveredSlot(int seq, UinType uin)
			Slot zostaje wywołany gdy wiadomość nie została dostarczona
			\param seq
			\param uin
		**/
		void messageNotDeliveredSlot(int seq, UinType uin);

		/**
			\fn void messageAcceptedSlot(int seq, UinType uin)
			Slot zostaje wywołany gdy wiadomość została poprawnie wysłana
			\param seq
			\param uin
		**/
		void messageAcceptedSlot(int seq, UinType uin);

		/**
			\fn void clearChatWindow()
			Slot czyszczący okno rozmowy
		**/
		void clearChatWindow();

		/**
			\fn void setAutoSend(bool auto_send)
			Ustaw autowysylanie
		**/
		void setAutoSend(bool auto_send);

		/**
			\fn void setScrollLocked(bool locked)
			Ustaw blokade przewijania
		**/
		void setScrollLocked(bool locked);

		/**
			\fn void emoticonSelectorClicked()
			Slot wyświetlający okno z wyborem emotikonek
		**/
		void openEmoticonSelector(const QWidget* activating_widget);

		/**
			\fn void insertImage()
			Slot wklejający obrazek do okna rozmowy (wybór obrazka)
		**/
		void insertImage();

	signals:
		/**
			\fn void messageSendRequested(Chat* chat)
			Sygnal jest emitowany gdy uzytkownik wyda polecenie
			wyslania wiadomosci, np klikajac na guzik "wyslij".
			\param chat wskaźnik do okna które emituje sygnał
		**/
		void messageSendRequested(Chat* chat);

		/**
			\fn void messageFiltering(const UserGroup *users, QCString& msg, bool& stop)
			Sygnal daje mozliwosc operowania na wiadomosci
			ktora ma byc wyslana do serwera juz w jej docelowej
			formie po konwersji z unicode i innymi zabiegami.
			Tresc wiadomosci mozna zmienic podmieniajac wskaznik
			msg na nowy bufor i zwalniajac stary (za pomoca free).
			Mozna tez przerwac dalsza jej obrobke ustawiajac
			wskaznik stop na true.
			\param users lista użytkowników
			\param msg wiadomość
			\param stop zakończenie dalszej obróbki sygnału
		**/
		void messageFiltering(const UserGroup *users, QCString &msg, bool &stop);

		/**
			\fn void messageSent(Chat* chat)
			Sygnal jest emitowany gdy zakonczy sie proces
			wysylania wiadomosci i zwiazanych z tym czynnosci.
			Oczywiscie nie wiemy czy wiadomosc dotarla.
			\param chat wskaźnik do okna rozmowy,
			 które emitowało sygnał
		**/
		void messageSent(Chat* chat);

		/**
			\fn void messageSentAndConfirmed(UserListElements receivers, const QString& message)
			This signal is emited when message was sent
			and it was confirmed.
			When confirmations are turned off signal is
			emited immediately after message was send
			just like messageSent() signal.
			\param receivers list of receivers
			\param message the message
		**/
		void messageSentAndConfirmed(UserListElements receivers, const QString& message);

		/**
			\fn void fileDropped(const UserGroup *users, const QString& fileName)
			Sygnał jest emitowany, gdy w oknie Chat
			upuszczono plik.
			\param users lista użytkowników
			\param fileName nazwa pliku
		**/
		void fileDropped(const UserGroup *users, const QString &fileName);

		/**
			\fn void windowActivationChanged(bool b, const UserGroup* users)
			\param b ??
			\param users lista użytkowników
		**/
		void windowActivationChanged(bool b, const UserGroup *users);
};

#endif
