/***************************************************************************
                          msnswitchboardconnection.h  -  description
                             -------------------
    begin                : Fri Jan 24 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 MSNSWITCHBOARDCONNECTION_H
#define MSNSWITCHBOARDCONNECTION_H

#include <qfont.h>
#include <qstringlist.h>
#include <qvaluelist.h>
#include <qstring.h>
#include <qcstring.h>
#include <qpair.h>

#include "msnconnection.h"
#include "mimemessage.h"

// Forward declarations
class Application;
class MimeApplication;
class P2PApplication;
class VoiceConversation;
class ChatInformation;
class KMessTest;
class MsnObject;
class P2PMessage;
class Contact;


/**
 * A connection to a switchboard server, over which chats are conducted.
 * @author Mike K. Bennett
 */
class MsnSwitchboardConnection : public MsnConnection
{
  Q_OBJECT

  friend class KMessTest;

  public:
    // The supported applications
    enum ApplicationType { GNOMEMEETING, FILETRANSFER, MSNREMOTEDESKTOP, VOICECONVERSATION };
    // The constructor
                         MsnSwitchboardConnection();
    // The destructor
                        ~MsnSwitchboardConnection();
    // Close the connection, only for emergaincy situations
    void                 closeConnection();
    // Clean up, close the connection, destroy this object
    void                 closeConnectionLater(bool autoDelete = false);
    // Get the switchboard to make a list of the contacts in the chat
    QString              getCaption();
    // Make a list of the contacts in the chat
    QStringList          getContactList() const;
    // Initialize the object
    bool                 initialize();
    // Invite a contact into the chat
    void                 inviteContact(QString handle);
    // Check if all contacts left
    bool                 isEmpty() const;
    // Check if only the given contact is in the chat
    bool                 isExclusiveChatWithContact(const QString& handle) const;
    // Start an application
    void                 startApp(ApplicationType type);
    // Start a chat
    void                 startChat(ChatInformation *chatInfo);
    // Start a file transfer (determines which transfer method will be used)
    void                 startFileTransfer(const QString &handle);
    // Start a P2P transfer to retreive a contact's picture.
    void                 startPictureDownload(Contact *contact);

  public slots: // Public slots
     // Give the application with the given cookie the command.
    void                 giveAppCommand(QString cookie, QString command);
    // Send a message to the contact(s)
    void                 sendChatMessage(QString text);
    // The user is typing so send a typing message
    void                 sendTypingMessage();

  protected slots: // Protected slots
    // The socket connected, so send the version command.
    void                 connectionSuccess();

  private: // Private methods
    // Remove the applications in a proper way
    void                 abortApplications();
    // Make the neccessary mimeapplication connections.
    void                 connectApplication(MimeApplication *app);
    // Make the neccessary p2papplication connections.
    void                 connectApplication(P2PApplication *app);
    // Do what's required when a contact joins the chat
    void                 contactJoined(QString& handle, QString& friendlyName);
    // Remove a contact from the list of contacts in the chat
    void                 contactLeft(const QString& handle);
    // Convert an html format (#RRGGBB) color to an msn format (BBGGRR) color
    void                 convertHtmlColorToMsnColor(QString &color) const;
    // Convert and msn format color (BBGGRR) to an html format (#RRGGBB) color
    void                 convertMsnColorToHtmlColor(QString &color) const;
    // Create an application of the given type
    Application*         createApplication(const QString &sendingContact, const MimeMessage &message);
    // A function to initialize the correct P2PApplication handler class.
    P2PApplication      *createApplication(const QString &sendingContact, const P2PMessage &message);
    // Detach all contacts from this switchboard, so others can take ownership
    void                 detachContacts();
    // Return the application with the given cookie.
    Application*         getApplication(QString cookie) const;
    // Get a contact's friendly name from the contact list
    QString              getContactFriendlyNameByHandle(const QString &handle);
    // Get the font and color from a message
    void                 getFontAndColorFromMessage(QFont &font, QString &color, const MimeMessage &message) const;
    // Get a font from the message
    void                 getFontFromMessageFormat(QFont &font, const MimeMessage& message) const;
    // Get an html font color from the message
    void                 getFontColorFromMessageFormat(QString &color, const MimeMessage& message) const;
    // Extract some information from a font message (i.e. "EF=UIB;" extract the "UIB" )
    QString              getFontValueFromMessageFormat(const QString& field, const QString& message) const;
    // Find an voice conversation object from the application list and return it.
    VoiceConversation   *getVoiceConversation() const;
    // Received a positive delivery message.
    void                 gotAck(const QStringList& command);
    // Received notification that a contact is no longer in session.
    void                 gotBye(const QStringList& command);
    // Received the initial roster information for new contacts joining a session.
    void                 gotIro(const QStringList& command);
    // Received notification of a new client in the session.
    void                 gotJoi(const QStringList& command);
    // Received a negative acknowledgement of the receipt of a message.
    void                 gotNak(const QStringList& command);
    // Received notification of the termination of a client-server session.
    void                 gotOut(const QStringList& command);
    // Received a client-server authentication message.
    void                 gotUsr(const QStringList& command);
    // Check if a certain contact is in the chat
    bool                 isContactInChat(const QString& handle) const;
    // Parse a regular command
    void                 parseCommand(const QStringList& command);
    // Parse a message command
    void                 parseMessage(const QStringList& command, const MimeMessage &message);
    // Parse an application message
    void                 parseMimeAppMessage(const QString &sendingContact, const MimeMessage &message);
    // Parse a P2P message (finds the correct P2PApplication object, and delegates the message)
    void                 parseP2PAppMessage(const QString &sendingContact, const P2PMessage &message);
    // Send a reject message for the given application
    void                 rejectMimeApplication(const QString& cookie, bool notInstalled = false);
    // Send a message to the contact(s), or leave it pending until a connection is restored
    void                 sendMimeMessageWhenReady(AckType ackType, const MimeMessage &message);
    // Send messages that weren't sent because a contact had to be re-called
    void                 sendPendingMessages();
    // Store a message for later acknowledgement
    void                 storeMessageForAcknowledgement(int ack, AckType ackType, const MimeMessage& message);
    // The generic implementation for terminateMimeApplication() / terminateP2PApplication()
    void                 terminateApplication(Application *app);

  private slots: // Private slots
    // A contact changed their msn object
    void                 contactChangedMsnObject(Contact *contact);
    // A file was received by an application
    void                 fileTransferred(QString filename);
    // Forward an application message by reemitting it as a signal.
    void                 forwardAppInitMessage(QString message);
    // Forward an application message by reemitting it as a signal.
    void                 forwardAppMessage(QString message);
    // Forward an system message
    void                 forwardSystemMessage(QString message);
    // Send an p2p message to the server.
    void                 pictureReceived(const QString &handle, const QString &msnObject);
    // Send an application message to the server.
    void                 putMimeApplicationMsg(const MimeMessage &message);
    // Send an p2p message to the server.
    void                 putP2PApplicationMsg(const MimeMessage &message);
    // Remove and delete the given application.
    void                 terminateMimeApplication(Application *app);
    // Remove and delete the give session.
    void                 terminateP2PApplication(Application *app);

  private: // Private attributes
    // Whether this object is aborting all it's applications
    bool                 abortingApplications_;
    // String lists to store messages and their ack numbers for confirmation of receipt
    QValueList<QString>  acks_, messages_;
    // Whether this object should be deleted after finishing closeConnectionLater()
    bool                 autoDeleteLater_;
    // The stored chat information
    ChatInformation     *chatInfo_;
    // Whether this object is closing it's connection using closeConnectionLater()
    bool                 closingConnection_;
    // Whether there are contacts in this chat, despite the default one that is left in contactsInChat_
    bool                 contactsConnected_;
    // A list of the contacts in the chat
    QValueList<QString>  contactsInChat_;
    // Whether or not the object has been initialized
    bool                 initialized_;
    // A list of pointers to the open applications.
    QPtrList<MimeApplication> mimeApplications_;
    // A list of pointers to all open p2p transfers.
    QPtrList<P2PApplication>  p2pApplications_;
    // A list of messages that should be sent to the contact when connection is reestablished
    QPtrList< QPair<AckType,MimeMessage> > pendingMessages_;

  signals: // Public signals
    // Signal that all applications are aborted
    void                 applicationsAborted();
    // Signal that a contact joined (or was already in) the chat
    void                 contactJoinedChat( QString handle, QString friendlyName );
    // Signal that a contact left the chat
    void                 contactLeftChat( QString handle );
    // Signal that a contact is typing
    void                 contactTyping( QString handle, QString friendlyName );
    // Signal a chat message
    void                 chatMessage( QString handle, QString name, QString text, QFont font, QString color, QString nameColor );
    // Send a status message about the connection
    void                 systemMessage( QString message );
    // Show a forwarded application message.
    void                 showAppMessage(QString message);
};

#endif
