/***************************************************************************
                          application.h  -  description
                             -------------------
    begin                : Thu Mar 20 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 APPLICATION_H
#define APPLICATION_H

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

// Forward declarations
class MimeMessage;

/**
 * The base class of chat applications, such as file transfer and meetings.
 * This class only provide the essentials like accept/cancel notifications.
 *
 * External users of this class only have to use the start() and gotMessage()
 * methods. The start() method causes KMess to send an invitation, and the
 * messages received after that should be passed to the gotMessage() method.
 * The gotMessage() method also detects whether KMess received an invitation.
 *
 *
 * The following paragraphs are worth reading if you're a new KMess developer:
 *
 * To support both MSN4 "Mime-style" and MSN6 "P2P-style" invitations,
 * two classes derive from this base class: The MimeApplication and
 * P2PApplication class. Those two classes implement the missing
 * gotMessage() and sendCancelMessage() methods.
 *
 * To implement your own application handler (like file transfers,
 * voice and webcam conversations), create a new class which derives
 * from either 'MimeApplication' or 'P2PApplication' and implements the
 * contactStarted* and userStarted* methods.
 *
 * The contactStarted* methods provide a framework to implement the nessesairy
 * dialogs for sessions started by the other contact ("chat buddy").
 *
 * The userStarted* methods provide a framework to implement the nessesairy
 * dialogs for sessions started by the user itself ("KMess user")
 *
 * Also note how each Application subclass implements a "static QString getAppId()"
 * method to return the Application GUID. This GUID is used in the invitation message.
 *
 * @author Mike K. Bennett, Diederik van der Boor (mime/p2p stuff)
 */
class Application : public QObject
{
  Q_OBJECT

  public:

    enum ApplicationMode
    {
      APP_MODE_NORMAL,        // Normal mode (all messages should appear in the Chat Window)
      APP_MODE_BACKGROUND,    // Background mode (status messages shouldn't appear)
      APP_MODE_ERROR_HANDLER  // Application instance is started to handle an error.
    };

    // The constructor
                           Application(const QString& localIp);
    // The destructor
    virtual               ~Application();
    // Return the application's identifying cookie
    const QString&         getCookie() const;
    // A command for the application was received (i.e. "Accept" or "Reject")
    void                   gotCommand(QString command);
    // A message for the application was received
    virtual void           gotMessage(const MimeMessage& message) = 0;
    // Read the current mode of the application
    int                    getMode() const;
    // Set the current mode of the application
    void                   setMode(ApplicationMode mode);
    // Start the application
    void                   start();
    // The user cancelled the session
    virtual void           userAborted();


  protected: // Protected methods

    // Reasons why invitations get cancelled.
    enum ApplicationCancelReason
    {
      CANCEL_INVITATION,           // User cancelled the invitation (aka rejected)
      CANCEL_SESSION,              // User cancelled the session (real cancel)
      CANCEL_NOT_INSTALLED,        // Requested service is not installed
      CANCEL_TIMEOUT,              // Timeout waiting for contact to accept / send data
      CANCEL_FAILED,               // Failed to initialize the session / start the app

      CANCEL_INVALID_SLP_CONTENT_TYPE  // Got an invalid content-type, abort the session (P2P only)
    };

    // The contact cancelled the session
    void                   contactAborted(const QString &message = 0);
    // The contact rejected the invitation
    void                   contactRejected(const QString &message = 0);
    // Step one of a contact-started chat: the contact invites the user
    virtual void           contactStarted1_ContactInvitesUser(const MimeMessage& message);
    // Step two of a contact-started chat: the user accepts
    virtual void           contactStarted2_UserAccepts();
    // Step three of a contact-started chat: the contact confirms the accept
    virtual void           contactStarted3_ContactConfirmsAccept(const MimeMessage& message);
    // Close the appliation (asks switchboard to delete this object)
    void                   endApplication(const QString &reason = 0);
    // Return a cancel message to display
    virtual QString        getCancelMessage() const;
    // Free a used port
    static void            freePort(const int& port);
    // Generate a random invitation or authorization cookie.
    QString                generateCookie() const;
    // Return the external IP address
    const QString&         getExternalIp() const;
    // Return the local IP address
    const QString&         getLocalIp() const;
    // Read the "user started this app" state.
    bool                   isUserStartedApp() const;
    // Return true if the user should press accept/cancel soon.
    bool                   isWaitingForUser() const;
    // Let the user accept or reject the application
    void                   offerAcceptOrReject(const QString& appHtml);
    // Let the user cancel the application
    void                   offerCancel(const QString& appHtml);
    // Send a cancel message
    virtual void           sendCancelMessage(const ApplicationCancelReason cancelReason) = 0;
    // Set the cookie from an INVITE command
    void                   startByInvite(const QString &invitationCookie);
    // The user rejected the invitation
    void                   userRejected();
    // Step one of a user-started chat: the user invites the contact
    virtual void           userStarted1_UserInvitesContact();
    // Step two of a user-started chat: the contact accepts
    virtual void           userStarted2_ContactAccepts(const MimeMessage& message);
    // Step three of a user-started chat: the user prepares for the session
    virtual void           userStarted3_UserPrepares();

  private: // Private attributes
    // The applications identifying cookie
    QString                cookie_;
    // The local IP address
    QString                localIp_;
    // The current mode
    ApplicationMode        mode_;
    // A list of used ports
//    static QStringList     usedPorts_;
//    static int             usedPorts_[10];
    // Whether or not the user accepted the invitation already
    bool                   userAccepted_;
    // Whether or not the user started the app
    bool                   userStartedApp_;
    // True if waiting for the user to accept
    bool                   waitingForUser_;

  signals: // Signals
    // Signal that this application wants to display an initialization message
    void                   appInitMessage(QString html);
    // Signal that this application wants to display an activity message
    void                   appMessage(QString html);
    // Signal that this application's activity has ended and that it should be deleted.
    void                   deleteMe(Application *object);
    // Signal that a file was successfully transferred
    void                   fileTransferred(QString filename);
    // Give the switchboard a message to send to the server.
    void                   putMsg(const MimeMessage &message);
    // Transmit an error message to the chat window.
    void                   systemMessage(QString message);
};

#endif
