/***************************************************************************
                          contactbase.h  -  description
                             -------------------
    begin                : Thu Jan 16 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 CONTACTBASE_H
#define CONTACTBASE_H

#include "../utils/richtextparser.h"
#include "msnstatus.h"

#include <QHash>


class MsnSwitchboardConnection;
class ApplicationList;
class MsnObject;



/// Supported ink transfer formats
/// Here because this include file is ubiquitous.
/// NOTE: In trunk it is in the network library.
enum InkFormat
{
  FORMAT_GIF    /// The transferred Ink data uses the GIF (Graphics Interchange Format) format
, FORMAT_ISF    /// The transferred Ink data uses the ISF (Ink Serialized Format) format
};


/**
 * @brief Base class of a contact, used for polymorphism with invited contacts.
 *
 * This class only stores the generic properties such as account handle, and friendly name.
 * The remaining information is available in the Contact or InvitedContact class.
 * The online state is determined with the getStatus() method, which is implemented in both derived classes.
 *
 * For proper handling of the peer-to-peer invitations,
 * this class also stores the MsnSwitchboardConnection sessions the contact is active in.
 * The ApplicationList contains all application invitations started with the contact.
 * These classes are controlled from the ChatMaster class.
 *
 * @author Mike K. Bennett
 * @ingroup Contact
 */
class ContactBase : public QObject
{
  Q_OBJECT

  public:
    /**
     * @brief The values for the bitwise client capabilities flag returned by getCapabilities().
     *
     * This flag is used to advertise the features supported by a client.
     * It's sent with the <code>CHG</code> command at the MsnNotificationConnection.
     */
    enum MsnClientCapabilities
    {
      MSN_CAP_WIN_MOBILE     = 0x1,        ///< <code>0x1</code>, the client is a Windows Mobile device, display an phone icon overlay in buddy list.
      MSN_CAP_MSN8_USER      = 0x2,        ///< <code>0x2</code>, MSN 8 user??
      MSN_CAP_INK_GIF        = 0x4,        ///< <code>0x4</code>, the client supports handwritten messages in GIF format.
      MSN_CAP_INK_ISF        = 0x8,        ///< <code>0x8</code>, the client supports handwritten messages in ISF format.
      MSN_CAP_VIDEO_CHAT     = 0x10,       ///< <code>0x10</code>, the client supports video chats; the webcam is connected and shared.
      MSN_CAP_MULTI_PACKET   = 0x20,       ///< <code>0x20</code>, the client supports multi-packet MIME messages.
      MSN_CAP_MSN_MOBILE     = 0x40,       ///< <code>0x40</code>, the contact has a MSN Mobile device you can page them on  (MSN6 displays a yellow icon if they're offline. This is equivalent to the <code>BPR MOB Y</code> setting).
      MSN_CAP_MSN_DIRECT     = 0x80,       ///< <code>0x80</code>, the user has a MSN Direct device you can direct-page them on (equivalent to <code>BPR WWE</code> setting).
      MSN_CAP_WEB_CLIENT     = 0x200,      ///< <code>0x200</code>, the client is http://webmessenger.msn.com/.
      MSN_CAP_MSO_CLIENT     = 0x800,      ///< <code>0x800</code>, the client is Office Live client, or internal Microsoft client.
      MSN_CAP_LIVE_SPACE     = 0x1000,     ///< <code>0x1000</code>, the user has an Windows Live space.
      MSN_CAP_MCE_CLIENT     = 0x2000,     ///< <code>0x2000</code>, the client is a Windows Media Center client.
      MSN_CAP_DIRECT_IM      = 0x4000,     ///< <code>0x4000</code>, the client supports direct-im (chats without a switchboard connection)
      MSN_CAP_WINKS          = 0x8000,     ///< <code>0x8000</code>, the client supports Winks.
      MSN_CAP_SHARED_SEARCH  = 0x10000,    ///< <code>0x10000</code>, the client supports MSN shared search.
      MSN_CAP_BOT            = 0x20000,    ///< <code>0x20000</code>, this is set by the server if the account has been provisioned by MSN as being a Bot account (and thus have its limitations removed).
      MSN_CAP_VOICE_CLIPS    = 0x40000,    ///< <code>0x40000</code>, the client supports Voice Clips.
      MSN_CAP_SCHANNEL       = 0x80000,    ///< <code>0x80000</code>, the client supports SChannel to send secure messages.
      MSN_CAP_SIP_INVITE     = 0x100000,   ///< <code>0x100000</code>, the client supports unknown SIP-based communications.
      MSN_CAP_UNKN_2009      = 0x200000,   ///< <code>0x200000</code>, seen since WLM 2009, meaning unknown.
      MSN_CAP_FOLDER_SHARING = 0x400000,   ///< <code>0x400000</code>, the client supports folder sharing (sdrive)
      MSN_CAP_ONECARE        = 0x1000000,  ///< <code>0x1000000</code>, the client supports OneCare.
      MSN_CAP_P2P_TURN       = 0x2000000,  ///< <code>0x2000000</code>, the client supports TURN as P2P transport layer.
      MSN_CAP_P2P_UUN        = 0x4000000,  ///< <code>0x4000000</code>, the client supports bootstrapping P2P via UUN.
      MSN_CAP_MSN60          = 0x10000000, ///< <code>0x10000000</code>, the client supports the P2P protocol features of MSNC1 (introduced with MSN 6.0).
      MSN_CAP_MSN61          = 0x20000000, ///< <code>0x20000000</code>, the client supports the P2P protocol features of MSNC2 (introduced with MSN 6.1).
      MSN_CAP_MSN62          = 0x30000000, ///< <code>0x30000000</code>, the client supports the P2P protocol features of MSNC3 (introduced with MSN 6.2).
      MSN_CAP_MSN70          = 0x40000000, ///< <code>0x40000000</code>, the client supports the P2P protocol features of MSNC4 (introduced with MSN 7.0).
      MSN_CAP_MSN75          = 0x50000000, ///< <code>0x50000000</code>, the client supports the P2P protocol features of MSNC5 (introduced with MSN 7.5).
      MSN_CAP_MSN80          = 0x60000000, ///< <code>0x60000000</code>, the client supports the P2P protocol features of MSNC6 (introduced with WLM 8.0).
      MSN_CAP_MSN81          = 0x70000000, ///< <code>0x70000000</code>, the client supports the P2P protocol features of MSNC7 (introduced with WLM 8.1).
      MSN_CAP_MSN85          = 0x80000000, ///< <code>0x80000000</code>, the client supports the P2P protocol features of MSNC8 (introduced with WLM 8.5).
      MSN_CAP_MSN90beta      = 0x90000000, ///< <code>0x90000000</code>, the client supports the P2P protocol features of MSNC9 (introduced with WLM 9.0 beta).
      MSN_CAP_MSN2009        = 0xa0000000, ///< <code>0xa0000000</code>, the client supports the P2P protocol features of MSNC10 (introduced with WLM 2009).
    };


  public: // Public methods
    // The destructor
    virtual             ~ContactBase();
    // Add a custom emoticon definition
    void                 addEmoticonDefinition(const QString &emoticonCode, const QString &msnObjectDataHash);
    // Add a custom emoticon definition
    void                 addEmoticonFile(const QString &msnObjectDataHash, const QString &filename);
    // Register the contact as participant in the chat session
    void                 addSwitchboardConnection( const MsnSwitchboardConnection *connection );
    // Initialize an application list for the contact.
    ApplicationList     *createApplicationList();
    // Set the application name based on the capabilities
    void                 detectClientName( uint capabilities, const MsnObject *msnObject );
    // Return the application list of the contact
    ApplicationList     *getApplicationList() const;
    // Return the capablities of the client the contact uses.
    uint                 getCapabilities() const;
    // Return the name of the client used by the contact
    const QString &      getClientName( bool getFullNameIfAvailable = true ) const;
    // Return the default contact picture path
    QString              getContactDefaultPicturePath() const;
    // Return the path to the contact's picture
    virtual const QString  getContactPicturePath() const = 0;
    // Return the list of custom emoticons to ignore.
    const QStringList   &getEmoticonBlackList() const;
    // Return the custom emoticon code for an msn object
    QString              getEmoticonCode(const QString &msnObjectDataHash) const;
    // Return the custom emoticon search pattern.
    const QRegExp &      getEmoticonPattern() const;
    // Return the custom emoticon hashes.
    const QHash<QString,QString> & getEmoticonHashes() const;
    // Return the custom emoticon replacements.
    const QHash<QString,QString> & getEmoticonReplacements() const;
    // Return the contact's friendly name
    virtual const QString&      getFriendlyName( FormattingMode mode = STRING_CLEANED ) const;
    // Return the contact's handle
    const QString&       getHandle() const;
    // Return the search pattern for pending custom emoticons.
    const QRegExp &      getPendingEmoticonPattern() const;
    // Return the contact's status
    virtual Status       getStatus() const = 0;
    // Return the list of switchboard connections
    const QList<const MsnSwitchboardConnection*> getSwitchboardConnections() const;
    // Returns whether the contact has an application list initialized.
    bool                 hasApplicationList() const;
    // Returns whether the contact has capability
    bool                 hasCapability( MsnClientCapabilities flag ) const;
    // Returns whether the contact's client supports the given MSNP2P version
    bool                 hasP2PSupport( MsnClientCapabilities minimalVersion = MSN_CAP_MSN60 ) const;
    // Return true if the contact is offline
    bool                 isOffline() const;
    // Return true if the contact is online
    bool                 isOnline() const;
    // Add or remove a custom emoticon from the black list
    bool                 manageEmoticonBlackList( bool add, const QString &emoticonCode );
    // Unregister the contact as participant, contact has left the chat.
    void                 removeSwitchboardConnection( const MsnSwitchboardConnection *connection, bool userInitiated = false );
    // Set the capabilities flag of the contact's msn client.
    void                 setCapabilities(uint capabilities);
    // Set the full name of the client used by the contact
    void                 setClientFullName( const QString &clientFullName );

  protected: // Protected methods
    // The constructor
                         ContactBase( const QString& handle, const QString& friendlyName, uint capabilities = 0);
    // Set the full name of the client used by the contact
    const QString &      getClientFullName() const;
    // Save the simple name of the client used by the contact
    void                 setClientName( const QString &clientName );


  private slots:
    // The application list completed aborting it's applications.
    void                 slotApplicationListAborted();

  protected: // Protected attributes
    // The capabilities of the client
    uint                 capabilities_;
    // The name of the client application
    QString              clientName_;
    // The third party client name field
    QString              clientFullName_;
    // The custom emoticons for the contact.
    QHash<QString,QString> customEmoticons_;
    // The custom emoticon mappings from shortcut to hash.
    QHash<QString,QString> customHashes_;
    // The list of custom emoticons to ignore for this contact
    QStringList          emoticonBlackList_;
    // The emoticon regexp
    QRegExp              emoticonRegExp_;
    // The contact's friendly name
    FormattedString      friendlyName_;
    // The contact's handle
    QString              handle_;
    // The pending custom emoticons for the contact.
    QHash<QString,QString> pendingEmoticons_;
    // The regexp for pending custom emoticons
    QRegExp              pendingRegExp_;
    // The contact's online status
    QString              status_;


  private:  // private properties
    // The list of peer-to-peer application invitations.
    ApplicationList                   *applicationList_;
    // The list of chat sessions the contact participates in.
    QList<const MsnSwitchboardConnection*> chatSessions_;

  private:  // private methods
    // Regenerate the pending emoticon regexp, because it was changed
    void                 regeneratePendingEmoticonPattern();

  signals: // Public signals
    // Signal that the contact's friendly name changed
    void                 changedFriendlyName();
    // Signal that the contact's picture path has changed
    void                 changedPicture();
    // signal that the contact's status changed
    void                 changedStatus();
    // Signal that the contact left all chats
    void                 leftAllChats( ContactBase *contact );
};

#endif
