/*************************************************************************
 * Copyright <2007 - 2013>  <Michael Zanetti> <mzanetti@kde.org>         *
 *                                                                       *
 * 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) version 3 or any later version        *
 * accepted by the membership of KDE e.V. (or its successor approved     *
 * by the membership of KDE e.V.), which shall act as a proxy            *
 * defined in Section 14 of version 3 of the license.                    *
 *                                                                       *
 * 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 <http://www.gnu.org/licenses/>. *
 *************************************************************************/

#ifndef OTRLCHATINTERFACE_H
#define OTRLCHATINTERFACE_H

/**
  * @author Michael Zanetti
  */

#include <qstring.h>
#include <qthread.h>
#include <qmutex.h>
#include <qmetatype.h>
#include <qtimer.h>

#include <kopete_export.h>
#include <kopetechatsession.h>
#include <kopeteplugin.h>

#include "authenticationwizard.h"

extern "C" {
#include <libotr/privkey.h>
#include <libotr/proto.h>
#include <libotr/message.h>
#include <libotr/userstate.h>
}

Q_DECLARE_METATYPE(otrl_instag_t)

class KeyGenThread;

class KOPETE_OTR_SHARED_EXPORT OtrlChatInterface : public QObject
{
    Q_OBJECT
public:
    ~OtrlChatInterface();
    static OtrlChatInterface *self();

    int decryptMessage(Kopete::Message &message);
    int encryptMessage(Kopete::Message &message);
    QString getDefaultQuery(const QString &accountId);
    void disconnectSession(Kopete::ChatSession *chatSession);
    void setPolicy(OtrlPolicy policy);
    bool shouldDiscard(const QString &message);
    OtrlUserState getUserstate();
    int privState(Kopete::ChatSession *session);
    bool isVerified(Kopete::ChatSession *session);
    void checkFilePermissions(const QString &file);
    QString fingerprint(Kopete::ChatSession *session);
    void verifyFingerprint(Kopete::ChatSession *session);
    void setPlugin(Kopete::Plugin *plugin);
    void emitGoneSecure(Kopete::ChatSession *sesseion, int state);
    void abortSMP(ConnContext *context, Kopete::ChatSession *session);
    void initSMP(ConnContext *context, Kopete::ChatSession *session, const QString &secret);
    void initSMPQ(ConnContext *context, Kopete::ChatSession *session, const QString &question, const QString &secret);
    void respondSMP(ConnContext *context, Kopete::ChatSession *session, const QString &secret);
    void setTrust(Kopete::ChatSession *session, bool trust);
    void generatePrivateKey(const QString &account, const QString &protocol);

    static QString formatContact(const QString &contactId);
private:
    OtrlChatInterface();
    static OtrlChatInterface *mSelf;
    Fingerprint *findFingerprint(Kopete::ChatSession *session);
    QList<uint> m_blackistIds;
    KeyGenThread *m_keyGenThread;
    QTimer m_forwardSecrecyTimer;
    QList<Kopete::Message> m_storedMessages;

    static OtrlMessageAppOps ui_ops;
    static OtrlPolicy policy(void *opdata, ConnContext *context);
    static void create_privkey(void *opdata, const char *accountname, const char *protocol);
    static int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient);
    static void inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message);
    static void update_context_list(void *opdata);
    static void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]);
    static void write_fingerprints(void *opdata);
    static void gone_secure(void *opdata, ConnContext *context);
    static void gone_insecure(void *opdata, ConnContext *context);
    static void still_secure(void *opdata, ConnContext *context, int is_reply);
    static int max_message_size(void *opdata, ConnContext *context);
    static const char *otr_error_message(void *opdata, ConnContext *context, OtrlErrorCode err_code);
    static void otr_error_message_free(void *opdata, const char *err_msg);
    static const char *resent_msg_prefix(void *opdata, ConnContext *context);
    static void resent_msg_prefix_free(void *opdata, const char *prefix);
    static void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char *message, gcry_error_t err);
    static void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question);
    static void create_instag(void *opdata, const char *accountname, const char *protocol);
    static void timer_control(void *opdata, unsigned int interval);

private Q_SLOTS:
    void otrlMessagePoll();
    void replayStoredMessages();
    void chatSessionDestroyed(Kopete::ChatSession *chatSession);

Q_SIGNALS:
    void goneSecure(Kopete::ChatSession *session, int state);
};

class KeyGenThread : public QThread
{
private:
    QString accountname;
    QString protocol;

public:
    KeyGenThread(const QString &accountname, const QString &protocol);
    void run() Q_DECL_OVERRIDE;
};

#endif
