/*
 * psiotrplugin.h
 *
 * Off-the-Record Messaging plugin for Psi
 * Copyright (C) 2007-2011  Timo Engel (timo-e@freenet.de)
 *                    2011  Florian Fieber
 *
 * This program was originally written as part of a diplom thesis
 * advised by Prof. Dr. Ruediger Weis (PST Labor)
 * at the Technical University of Applied Sciences Berlin.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#ifndef PSIOTRPLUGIN_H_
#define PSIOTRPLUGIN_H_

#include <QMessageBox>
#include <QObject>
#include <QQueue>

#include "accountinfoaccessor.h"
#include "applicationinfoaccessor.h"
#include "contactinfoaccessor.h"
#include "encryptionsupport.h"
#include "eventcreatinghost.h"
#include "eventcreator.h"
#include "eventfilter.h"
#include "iconfactoryaccessor.h"
#include "optionaccessinghost.h"
#include "optionaccessor.h"
#include "otrmessaging.h"
#include "plugininfoprovider.h"
#include "psiaccountcontroller.h"
#include "psiplugin.h"
#include "stanzafilter.h"
#include "stanzasender.h"
#include "stanzasendinghost.h"
#include "toolbariconaccessor.h"

class ApplicationInfoAccessingHost;
class PsiAccountControllingHost;
class AccountInfoAccessingHost;
class ContactInfoAccessingHost;
class IconFactoryAccessingHost;

class QDomElement;
class QString;
class QAction;

namespace psiotr {

class PsiOtrClosure;

//-----------------------------------------------------------------------------

class PsiOtrPlugin : public QObject,
                     public PsiPlugin,
                     public PluginInfoProvider,
                     public EventCreator,
                     public OptionAccessor,
                     public StanzaSender,
                     public ApplicationInfoAccessor,
                     public PsiAccountController,
                     public StanzaFilter,
                     public ToolbarIconAccessor,
                     public AccountInfoAccessor,
                     public ContactInfoAccessor,
                     public IconFactoryAccessor,
                     public OtrCallback,
                     public EncryptionSupport {
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "com.psi-plus.PsiOtrPlugin" FILE "psiplugin.json")
    Q_INTERFACES(PsiPlugin PluginInfoProvider EventCreator OptionAccessor StanzaSender ApplicationInfoAccessor
                     PsiAccountController StanzaFilter ToolbarIconAccessor AccountInfoAccessor ContactInfoAccessor
                         IconFactoryAccessor EncryptionSupport)

public:
    PsiOtrPlugin();
    ~PsiOtrPlugin();

    // PsiPlugin
    virtual QString  name() const;
    virtual QWidget *options();
    virtual bool     enable();
    virtual bool     disable();
    virtual void     applyOptions();
    virtual void     restoreOptions();

    // PluginInfoProvider
    virtual QString pluginInfo();

    // EventCreator
    virtual void setEventCreatingHost(EventCreatingHost *host);

    // OptionAccessor
    virtual void setOptionAccessingHost(OptionAccessingHost *host);
    virtual void optionChanged(const QString &option);

    // StanzaSender
    virtual void setStanzaSendingHost(StanzaSendingHost *host);

    // ApplicationInfoAccessor
    virtual void setApplicationInfoAccessingHost(ApplicationInfoAccessingHost *host);

    // PsiAccountController
    virtual void setPsiAccountControllingHost(PsiAccountControllingHost *host);

    // StanzaFilter
    virtual bool incomingStanza(int accountIndex, const QDomElement &xml);
    virtual bool outgoingStanza(int accountIndex, QDomElement &xml);

    // ToolbarIconAccessor
    virtual QList<QVariantHash> getButtonParam();
    virtual QAction            *getAction(QObject *parent, int accountIndex, const QString &contact);

    // AccountInfoAccessor
    virtual void setAccountInfoAccessingHost(AccountInfoAccessingHost *host);

    // ContactInfoAccessor
    virtual void setContactInfoAccessingHost(ContactInfoAccessingHost *host);

    // IconFactoryAccessingHost
    virtual void setIconFactoryAccessingHost(IconFactoryAccessingHost *host);

    // EncryptionSupport
    virtual bool decryptMessageElement(int account, QDomElement &message);
    virtual bool encryptMessageElement(int account, QDomElement &message);

    // OtrCallback
    virtual QString dataDir();
    virtual void    sendMessage(const QString &account, const QString &contact, const QString &message);
    virtual bool    isLoggedIn(const QString &account, const QString &contact);
    virtual void    notifyUser(const QString &account, const QString &contact, const QString &message,
                               const OtrNotifyType &type);

    virtual bool displayOtrMessage(const QString &account, const QString &contact, const QString &message);
    virtual void stateChange(const QString &account, const QString &contact, OtrStateChange change);

    virtual void receivedSMP(const QString &account, const QString &contact, const QString &question);
    virtual void updateSMP(const QString &account, const QString &contact, int progress);

    virtual void stopMessages();
    virtual void startMessages();

    virtual QString humanAccount(const QString &accountId);
    virtual QString humanAccountPublic(const QString &accountId);
    virtual QString humanContact(const QString &accountId, const QString &contact);

    /**
     * Displays a rich text system message for (account, contact)
     */
    bool appendSysMsg(const QString &account, const QString &contact, const QString &message, const QString &icon = "");

    // Helper methods
    /**
     * Returns the index of the account identified by accountId or -1
     */
    int getAccountIndexById(const QString &accountId);

    /**
     * Returns the name of the account identified by accountId or ""
     */
    QString getAccountNameById(const QString &accountId);

    /**
     * Returns the Jid of the account identified by accountId or "-1"
     */
    QString getAccountJidById(const QString &accountId);

private slots:
    void eventActivated();

private:
    /**
     * Returns full Jid for private contacts,
     * bare Jid for non-private contacts.
     */
    QString getCorrectJid(int accountIndex, const QString &fullJid);

    bool                                            m_enabled;
    OtrMessaging                                   *m_otrConnection;
    QHash<QString, QHash<QString, PsiOtrClosure *>> m_onlineUsers;
    OptionAccessingHost                            *m_optionHost;
    StanzaSendingHost                              *m_senderHost;
    ApplicationInfoAccessingHost                   *m_applicationInfo;
    PsiAccountControllingHost                      *m_accountHost;
    AccountInfoAccessingHost                       *m_accountInfo;
    ContactInfoAccessingHost                       *m_contactInfo;
    IconFactoryAccessingHost                       *m_iconHost;
    EventCreatingHost                              *m_psiEvent;
    QQueue<QMessageBox *>                           m_messageBoxList;
};

//-----------------------------------------------------------------------------

} // namespace psiotr

#endif
