/***************************************************************************
                          chatmaster.h  -  description
                             -------------------
    begin                : Sat Jan 18 2003
    copyright            : (C) 2003 by Mike K. Bennett
    email                : mkb137b@hotmail.com
 ***************************************************************************/

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

#include "../network/chatmessage.h"
#include "../network/chatinformation.h"
#include "../network/mimemessage.h"
#include "../contact/contactbase.h"

#include <QList>


// Forward declarations
class Application;
class ApplicationList;
class ChatInformation;
class ChatMessage;
class Chat;
class ChatWindow;
class Contact;
class ContactBase;
class CurrentAccount;
class MimeApplication;
class MimeMessage;
class P2PApplication;
class P2PMessage;
class MsnObject;
class MsnSwitchboardConnection;



/**
 * This class governs the chat windows, detecting when a chat
 * can be restarted in an open window and the like.
 *
 * @author Mike K. Bennett
 * @ingroup Chat
 */
class ChatMaster : public QObject
{
  Q_OBJECT

  friend class KMessTest;

  public: // Public methods
    // The constructor
                       ChatMaster(QObject *parent = 0);
    // The destructor
    virtual           ~ChatMaster();
    // Initialize the class
    bool               initialize();

  public slots: // Public slots
    // The connection has been established
    void               connected();
    // The user has disconnected, so close all open switchboard connections and disable the chats
    void               disconnected();
    // KMess is establishing a connection.
    void               connecting();
    // Raise an existing chat window
    void               raiseChat( Chat *chat, bool force );
    // Verify if a new chat can be opened and requests a switchboard
    void               requestChat( QString handle );
    // Deliver an application or offline message to the chat window (can be submitted by an Application or Offline-IM from MsnNotificationConnection).
    void               showSpecialMessage(const ChatMessage &message, const MsnSwitchboardConnection *switchboardChat = 0 );
    // Start a switchboard connection with the information gathered from the Notification connection
    MsnSwitchboardConnection *startSwitchboard( const ChatInformation &chatInfo );
    // Start a file transfer with the information from the Chat
    void               startFileTransfer( const QString &handle, const QString &filename );
    // Start a chat and send a file to the contact
    void               startChatAndFileTransfer( const QString &handle, const QString &filename );
    // Periodically update events. It's based on the pings sent by MsnNotificationConnection.
    void               timedUpdate();

  private slots: // Private slots
    // Start a chat with the information gathered from a switchboard connection
    Chat              *createChat( MsnSwitchboardConnection *switchboard, bool requestedByUser = false );
    // Create a new chat window or retrieve an existing one if tabbed chatting is enabled
    ChatWindow        *createChatWindow( Chat *chat );
    // Forward a new switchboard server request signal coming from an existing switchboard connection
    void               forwardRequestNewSwitchboard( QString handle );
    // Forward a request to add or remove a contact from the contactlist, which comes from the ContactFrame.
    void               forwardContactAdded( QString handle, bool isAdded );
    // Forward a request to block or unblock a contact, which comes from the ContactFrame.
    void               forwardContactBlocked( QString handle, bool isBlocked );
    // A chat is closing
    void               slotChatClosing( Chat *chat );
    // A chat was destroyed
    void               slotChatDestroyed( QObject *chatObject );
    // A chat window was destroyed
    void               slotChatWindowDestroyed(QObject *chatWindow);
    // A new application was created for a contact.
    void               slotConnectApplication(Application *application);
    // Determine what to do when a contact changed it's picture.
    void               slotContactChangedMsnObject( Contact *contact = 0 );
    // A contact joined to one of our switchboard sessions.
    void               slotContactJoinedChat( ContactBase *contact );
    // Deliver an application command to the correct application
    void               slotDeliverAppCommand(QString cookie, QString handle, QString command);
    // Deliver a message from a Application to the switchboard connection.
    void               slotDeliverMimeMessage(const MimeMessage &message, const QString &handle, bool privateChatRequired);
    // The switchboard or p2p application received a Ink message.
    void               slotGotInkMessage( const QString &inkData, const QString &handle, InkFormat format );
    // The switchboard received a Mime message
    void               slotGotMessage(const MimeMessage &message, const QString &handle);
    // The switchboard received a P2P message
    void               slotGotMessage(const P2PMessage &message, const QString &handle);
    // The switchboard received an msn object
    void               slotGotMsnObject(const QString &msnObjectData, const QString &handle);
    // A msn object (picture, wink, emoticon) was received for the contact.
    void               slotMsnObjectReceived(const QString &handle, const MsnObject &msnObject);
    // Delete an existing switchboard
    void               slotSwitchboardDelete( MsnSwitchboardConnection *closing, bool deleteObject = false );
    // The switchboard is ready to send more messages.
    void               slotSwitchboardReady();
    // Update the grouping of chats/tabs.
    void               updateChatGrouping();
    // Search the appropriate window for a chat.
    ChatWindow        *findWindowForChat( Chat *chat );

  private:  // private methods
    // Create and register a new switchboard
    MsnSwitchboardConnection *createSwitchboardConnection( MsnSwitchboardConnection *replace = 0, QString handle = QString() );
    // Check whether the contact is in any of the existing chat windows.
    bool               isContactInChat( const QString &handle );
    // Display an MSN Object that was received.
    void               showMsnObject(const QString &handle, const MsnObject &msnObject, Chat *chatWindow);
    // Configure and start the mime application object.
    void               startApplication( MimeApplication *application );
    // Configure and start the P2P application object.
    void               startApplication( P2PApplication *application );
    // Start the transfer of the contact's picture
    void               startMsnObjectDownload(const QString &handle, const MsnObject *msnObject, Chat *chatWindow);
    // Return the application list for a given contact
    ApplicationList   *getApplicationList(const QString &handle);
    // Return the chat tab which uses the given switchboard connection
    Chat              *getChatBySwitchboard(const MsnSwitchboardConnection *connection);
    // Return the chat window which uses the given switchboard connection
    ChatWindow        *getChatWindowBySwitchboard(const MsnSwitchboardConnection *connection);
    // Return the chat window where we're having an conversation with the given contact.
    Chat              *getContactsChat( const QString &handle, bool privateChat );
    // Return the chat window where we're having a conversation with the given contacts.
    Chat              *getContactsChat( const QStringList &handles, bool privateChat );
    // Return the chat connection where we're having an conversation with the given contact.
    MsnSwitchboardConnection *getContactSwitchboardConnection( const QString &handle, bool doRequirePrivateChat );
    // Append the message to the queue, waiting to be delivered
    void               queueMessage( const MimeMessage &message, const QString &handle, bool privateChatRequired );
    // Send all pending mime messages for the contact.
    void               sendPendingMimeMessages( const QString &handle, MsnSwitchboardConnection *connection );

  private: // Private attributes
    struct PendingMimeMessage
    {
      QString     handle;
      MimeMessage message;
      bool        privateChatRequired;
    };

    // The pointers to the currently active chats
    QList<Chat*>       chats_;
    // The pointers to the chat windows
    QList<ChatWindow*> chatWindows_;
    // The pointers to chats which are closing
    QList<Chat*>       closingChats_;
    // Current account reference
    CurrentAccount    *currentAccount_;
    // Whether or not the object was initialized
    bool               initialized_;
    // The list of contacts whose DPs must be downloaded
    QStringList        pendingDisplayPictures_;
    // A list of mime messages that should be sent to the contact when connection is reestablished
    QList<PendingMimeMessage*> pendingMimeMessages_;
    // A list of requested chat with one contact ( handle )
    QStringList        requestedChats_;
    // The pointers to the switchboard server connections
    QList<MsnSwitchboardConnection*> switchboardConnections_;
    // The current tabbed chat setting
    int                chatTabbedMode_;

  signals: // Public signals
    // Ask the Notification connection to add a contact
    void               addContact( QString handle );
    // Ask the Notification connection to allow a contact
    void               allowContact( QString handle );
    // Ask the Notification connection to block a contact
    void               blockContact( QString handle );
    // Signal the presence of a new incoming chat message
    void               newChatMessage( const ChatMessage &message, Chat *chatWindow );
    // Ask the Notification connection to remove a contact
    void               removeContact( QString handle, bool block );
    // Ask the Notification connection to initiate a new switchboard connection with the contact
    void               requestSwitchboard( QString handle, ChatInformation::ConnectionType type );
    // Ask the Notification connection to unblock a contact
    void               unblockContact( QString handle );
    // Signal for ChatMessageView to replace an application's accept/reject/cancel links with another text
    void               updateApplicationMessage( const QString &messageId, const QString &newMessage );
    // Signal a reconnect request.
    void               reconnect();
};

#endif
