/*
 * Copyright (C) 2020 by Savoir-faire Linux
 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
 * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com>
 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
 * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
 * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
 * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.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 3 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 <http://www.gnu.org/licenses/>.
 */

#include "messagesadapter.h"
#include "webchathelpers.h"

#include "utils.h"

#include <QDesktopServices>
#include <QFileInfo>
#include <QImageReader>
#include <QList>
#include <QUrl>

MessagesAdapter::MessagesAdapter(QObject *parent)
    : QmlAdapterBase(parent)
{}

MessagesAdapter::~MessagesAdapter() {}

void
MessagesAdapter::initQmlObject() {}

void
MessagesAdapter::setupChatView(const QString &uid)
{

    auto* convModel = LRCInstance::getCurrentConversationModel();
    if (convModel == nullptr) {
        return;
    }
    const auto &convInfo = convModel->getConversationForUID(uid);
    if (convInfo.uid.isEmpty() || convInfo.participants.isEmpty()) {
        return;
    }

    QString contactURI = convInfo.participants.at(0);

    bool isContact = false;
    auto selectedAccountId = LRCInstance::getCurrAccId();
    auto &accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);

    lrc::api::profile::Type contactType;
    try {
        auto contactInfo = accountInfo.contactModel->getContact(contactURI);
        if (contactInfo.isTrusted) {
            isContact = true;
        }
        contactType = contactInfo.profileInfo.type;
    } catch (...) {
    }

    bool shouldShowSendContactRequestBtn = !isContact
                                           && contactType != lrc::api::profile::Type::SIP;

    QMetaObject::invokeMethod(qmlObj_,
                              "setSendContactRequestButtonVisible",
                              Q_ARG(QVariant, shouldShowSendContactRequestBtn));

    setMessagesVisibility(false);

    /*
     * Type Indicator (contact).
     */
    contactIsComposing(convInfo.uid, "", false);
    connect(LRCInstance::getCurrentConversationModel(),
            &ConversationModel::composingStatusChanged,
            [this](const QString &uid, const QString &contactUri, bool isComposing) {
                contactIsComposing(uid, contactUri, isComposing);
            });

    /*
     * Draft and message content set up.
     */
    Utils::oneShotConnect(qmlObj_,
                          SIGNAL(sendMessageContentSaved(const QString &)),
                          this,
                          SLOT(slotSendMessageContentSaved(const QString &)));

    requestSendMessageContent();
}

void
MessagesAdapter::connectConversationModel()
{
    auto currentConversationModel = LRCInstance::getCurrentConversationModel();

    QObject::disconnect(newInteractionConnection_);
    QObject::disconnect(interactionRemovedConnection_);
    QObject::disconnect(interactionStatusUpdatedConnection_);

    newInteractionConnection_ = QObject::connect(currentConversationModel,
                                                 &lrc::api::ConversationModel::newInteraction,
                                                 [this](const QString &convUid, uint64_t interactionId,
                                                        const lrc::api::interaction::Info &interaction) {
        auto accountId = LRCInstance::getCurrAccId();
        newInteraction(accountId, convUid, interactionId, interaction);
    });

    interactionStatusUpdatedConnection_ = QObject::connect(currentConversationModel,
                                                           &lrc::api::ConversationModel::interactionStatusUpdated,
                                                           [this](const QString &convUid, uint64_t interactionId,
                                                                  const lrc::api::interaction::Info &interaction) {
        auto currentConversationModel = LRCInstance::getCurrentConversationModel();
        currentConversationModel->clearUnreadInteractions(convUid);
        updateInteraction(*currentConversationModel, interactionId, interaction);
    });

    interactionRemovedConnection_
        = QObject::connect(currentConversationModel,
                           &lrc::api::ConversationModel::interactionRemoved,
                           [this](const QString &convUid, uint64_t interactionId) {
                               Q_UNUSED(convUid);
                               removeInteraction(interactionId);
                           });

    currentConversationModel->setFilter("");
}

void
MessagesAdapter::sendContactRequest()
{
    const auto convUid = LRCInstance::getCurrentConvUid();
    if (!convUid.isEmpty()) {
        LRCInstance::getCurrentConversationModel()->makePermanent(convUid);
    }
}

void
MessagesAdapter::updateConversationForAddedContact()
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());

    clear();
    setConversationProfileData(conversation);
    printHistory(*convModel, conversation.interactions);
}

void
MessagesAdapter::slotSendMessageContentSaved(const QString &content)
{
    if (!LastConvUid_.isEmpty()) {
        LRCInstance::setContentDraft(LastConvUid_, LRCInstance::getCurrAccId(), content);
    }
    LastConvUid_ = LRCInstance::getCurrentConvUid();

    Utils::oneShotConnect(qmlObj_, SIGNAL(messagesCleared()), this, SLOT(slotMessagesCleared()));

    setInvitation(false);
    clear();
    auto restoredContent = LRCInstance::getContentDraft(LRCInstance::getCurrentConvUid(),
                                                        LRCInstance::getCurrAccId());
    setSendMessageContent(restoredContent);
    emit needToUpdateSmartList();
}

void
MessagesAdapter::slotUpdateDraft(const QString &content)
{
    if (!LastConvUid_.isEmpty()) {
        LRCInstance::setContentDraft(LastConvUid_, LRCInstance::getCurrAccId(), content);
    }
    emit needToUpdateSmartList();
}

void
MessagesAdapter::slotMessagesCleared()
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());

    printHistory(*convModel, convInfo.interactions);

    Utils::oneShotConnect(qmlObj_, SIGNAL(messagesLoaded()), this, SLOT(slotMessagesLoaded()));

    setConversationProfileData(convInfo);
}

void
MessagesAdapter::slotMessagesLoaded()
{
    setMessagesVisibility(true);
}

void
MessagesAdapter::sendMessage(const QString &message)
{
    try {
        const auto convUid = LRCInstance::getCurrentConvUid();
        LRCInstance::getCurrentConversationModel()->sendMessage(convUid, message);
    } catch (...) {
        qDebug() << "Exception during sendMessage:" << message;
    }
}

void
MessagesAdapter::sendImage(const QString &message)
{
    if (message.startsWith("data:image/png;base64,")) {
        /*
         * Img tag contains base64 data, trim "data:image/png;base64," from data.
         */
        QByteArray data = QByteArray::fromStdString(message.toStdString().substr(22));
        auto img_name_hash = QString::fromStdString(
            QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex().toStdString());
        QString fileName = "\\img_" + img_name_hash + ".png";

        QPixmap image_to_save;
        if (!image_to_save.loadFromData(QByteArray::fromBase64(data))) {
            qDebug().noquote() << "Errors during loadFromData"
                               << "\n";
        }

        QString path = QString(Utils::WinGetEnv("TEMP")) + fileName;
        if (!image_to_save.save(path, "PNG")) {
            qDebug().noquote() << "Errors during QPixmap save"
                               << "\n";
        }

        try {
            auto convUid = LRCInstance::getCurrentConvUid();
            LRCInstance::getCurrentConversationModel()->sendFile(convUid, path, fileName);
        } catch (...) {
            qDebug().noquote() << "Exception during sendFile - base64 img"
                               << "\n";
        }

    } else {
        /*
         * Img tag contains file paths.
         */

        QString msg(message);
#ifdef Q_OS_WIN
        msg = msg.replace("file:///", "");
#else
        msg = msg.replace("file:///", "/");
#endif
        QFileInfo fi(msg);
        QString fileName = fi.fileName();

        try {
            auto convUid = LRCInstance::getCurrentConvUid();
            LRCInstance::getCurrentConversationModel()->sendFile(convUid, msg, fileName);
        } catch (...) {
            qDebug().noquote() << "Exception during sendFile - image from path"
                               << "\n";
        }
    }
}

void
MessagesAdapter::sendFile(const QString &message)
{
    QFileInfo fi(message);
    QString fileName = fi.fileName();
    try {
        auto convUid = LRCInstance::getCurrentConvUid();
        LRCInstance::getCurrentConversationModel()->sendFile(convUid, message, fileName);
    } catch (...) {
        qDebug() << "Exception during sendFile";
    }
}

void
MessagesAdapter::retryInteraction(const QString &arg)
{
    bool ok;
    uint64_t interactionUid = arg.toULongLong(&ok);
    if (ok) {
        LRCInstance::getCurrentConversationModel()
            ->retryInteraction(LRCInstance::getCurrentConvUid(), interactionUid);
    } else {
        qDebug() << "retryInteraction - invalid arg" << arg;
    }
}

void
MessagesAdapter::setNewMessagesContent(const QString &path)
{
    if (path.length() == 0)
        return;
    QByteArray imageFormat = QImageReader::imageFormat(path);

    if (!imageFormat.isEmpty()) {
        setMessagesImageContent(path);
    } else {
        setMessagesFileContent(path);
    }
}

void
MessagesAdapter::deleteInteraction(const QString &arg)
{
    bool ok;
    uint64_t interactionUid = arg.toULongLong(&ok);
    if (ok) {
        LRCInstance::getCurrentConversationModel()
            ->clearInteractionFromConversation(LRCInstance::getCurrentConvUid(), interactionUid);
    } else {
        qDebug() << "DeleteInteraction - invalid arg" << arg;
    }
}

void
MessagesAdapter::openFile(const QString &arg)
{
    QUrl fileUrl("file:///" + arg);
    if (!QDesktopServices::openUrl(fileUrl)) {
        qDebug() << "Couldn't open file: " << fileUrl;
    }
}

void
MessagesAdapter::acceptFile(const QString &arg)
{
    try {
        auto interactionUid = arg.toLongLong();
        auto convUid = LRCInstance::getCurrentConvUid();
        LRCInstance::getCurrentConversationModel()->acceptTransfer(convUid, interactionUid);
    } catch (...) {
        qDebug() << "JS bridging - exception during acceptFile: " << arg;
    }
}

void
MessagesAdapter::refuseFile(const QString &arg)
{
    try {
        auto interactionUid = arg.toLongLong();
        const auto convUid = LRCInstance::getCurrentConvUid();
        LRCInstance::getCurrentConversationModel()->cancelTransfer(convUid, interactionUid);
    } catch (...) {
        qDebug() << "JS bridging - exception during refuseFile:" << arg;
    }
}

void
MessagesAdapter::pasteKeyDetected()
{
    const QMimeData *mimeData = QApplication::clipboard()->mimeData();

    if (mimeData->hasImage()) {
        /*
         * Save temp data into base64 format.
         */
        QPixmap pixmap = qvariant_cast<QPixmap>(mimeData->imageData());
        QByteArray ba;
        QBuffer bu(&ba);
        bu.open(QIODevice::WriteOnly);
        pixmap.save(&bu, "PNG");
        auto str = QString::fromLocal8Bit(ba.toBase64());

        setMessagesImageContent(str, true);
    } else if (mimeData->hasUrls()) {
        QList<QUrl> urlList = mimeData->urls();
        /*
        * Extract the local paths of the files.
        */
        for (int i = 0; i < urlList.size(); ++i) {
            /*
             * Trim file:/// from url.
             */
            QString filePath = urlList.at(i).toString().remove(0, 8);
            QByteArray imageFormat = QImageReader::imageFormat(filePath);

            /*
             * Check if file is qt supported image file type.
             */
            if (!imageFormat.isEmpty()) {
                setMessagesImageContent(filePath);
            } else {
                setMessagesFileContent(filePath);
            }
        }
    } else {
        QMetaObject::invokeMethod(qmlObj_,
                                  "webViewRunJavaScript",
                                  Q_ARG(QVariant,
                                        QStringLiteral("replaceText(`%1`)").arg(mimeData->text())));
    }
}

void
MessagesAdapter::onComposing(bool isComposing)
{
    LRCInstance::getCurrentConversationModel()->setIsComposing(LRCInstance::getCurrentConvUid(),
                                                               isComposing);
}

void
MessagesAdapter::setConversationProfileData(const lrc::api::conversation::Info &convInfo)
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    auto accInfo = &LRCInstance::getCurrentAccountInfo();
    const auto conv = convModel->getConversationForUID(convInfo.uid);

    if (conv.participants.isEmpty()) {
        return;
    }

    auto contactUri = conv.participants.front();
    if (contactUri.isEmpty()) {
        return;
    }
    try {
        auto &contact = accInfo->contactModel->getContact(contactUri);
        auto bestName = Utils::bestNameForConversation(convInfo, *convModel);
        setInvitation(contact.profileInfo.type == lrc::api::profile::Type::PENDING,
                      bestName,
                      contactUri);

        if (!contact.profileInfo.avatar.isEmpty()) {
            setSenderImage(contactUri, contact.profileInfo.avatar);
        } else {
            auto avatar = Utils::conversationPhoto(convInfo.uid, *accInfo, true);
            QByteArray ba;
            QBuffer bu(&ba);
            avatar.save(&bu, "PNG");
            setSenderImage(contactUri, QString::fromLocal8Bit(ba.toBase64()));
        }
    } catch (...) {
    }
}

void
MessagesAdapter::newInteraction(const QString &accountId,
                                const QString &convUid,
                                uint64_t interactionId,
                                const interaction::Info &interaction)
{
    Q_UNUSED(interactionId);
    try {
        auto &accountInfo = LRCInstance::getAccountInfo(accountId);
        auto &convModel = accountInfo.conversationModel;
        const auto conversation = convModel->getConversationForUID(convUid);

        if (conversation.uid.isEmpty()) {
            return;
        }
        if (!interaction.authorUri.isEmpty()
            && (!QApplication::focusWindow() || LRCInstance::getCurrAccId() != accountId)) {
            /*
             * TODO: Notification from other accounts.
             */
        }
        if (convUid != LRCInstance::getCurrentConvUid()) {
            return;
        }
        convModel->clearUnreadInteractions(convUid);
        printNewInteraction(*convModel, interactionId, interaction);
    } catch (...) {
    }
}

void
MessagesAdapter::updateDraft()
{
    Utils::oneShotConnect(qmlObj_,
                          SIGNAL(sendMessageContentSaved(const QString &)),
                          this,
                          SLOT(slotUpdateDraft(const QString &)));

    requestSendMessageContent();
}

/*
 * JS invoke.
 */
void
MessagesAdapter::setMessagesVisibility(bool visible)
{
    QString s = QString::fromLatin1(visible ? "showMessagesDiv();" : "hideMessagesDiv();");
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::requestSendMessageContent()
{
    QString s = QString::fromLatin1("requestSendMessageContent();");
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::setInvitation(bool show, const QString &contactUri, const QString &contactId)
{
    QString s
        = show
              ? QString::fromLatin1("showInvitation(\"%1\", \"%2\")").arg(contactUri).arg(contactId)
              : QString::fromLatin1("showInvitation()");

    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::clear()
{
    QString s = QString::fromLatin1("clearMessages();");
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::printHistory(lrc::api::ConversationModel &conversationModel,
                              const std::map<uint64_t, lrc::api::interaction::Info> interactions)
{
    auto interactionsStr = interactionsToJsonArrayObject(conversationModel, interactions).toUtf8();
    QString s = QString::fromLatin1("printHistory(%1);").arg(interactionsStr.constData());
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::setSenderImage(const QString &sender, const QString &senderImage)
{
    QJsonObject setSenderImageObject = QJsonObject();
    setSenderImageObject.insert("sender_contact_method", QJsonValue(sender));
    setSenderImageObject.insert("sender_image", QJsonValue(senderImage));

    auto setSenderImageObjectString = QString(
        QJsonDocument(setSenderImageObject).toJson(QJsonDocument::Compact));
    QString s = QString::fromLatin1("setSenderImage(%1);")
                    .arg(setSenderImageObjectString.toUtf8().constData());
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::printNewInteraction(lrc::api::ConversationModel &conversationModel,
                                     uint64_t msgId,
                                     const lrc::api::interaction::Info &interaction)
{
    auto interactionObject
        = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8();
    if (interactionObject.isEmpty()) {
        return;
    }
    QString s = QString::fromLatin1("addMessage(%1);").arg(interactionObject.constData());
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::updateInteraction(lrc::api::ConversationModel &conversationModel,
                                   uint64_t msgId,
                                   const lrc::api::interaction::Info &interaction)
{
    auto interactionObject
        = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8();
    if (interactionObject.isEmpty()) {
        return;
    }
    QString s = QString::fromLatin1("updateMessage(%1);").arg(interactionObject.constData());
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::setMessagesImageContent(const QString &path, bool isBased64)
{
    if (isBased64) {
        QString param = QString("addImage_base64('file://%1')").arg(path);
        QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param));
    } else {
        QString param = QString("addImage_path('file://%1')").arg(path);
        QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param));
    }
}

void
MessagesAdapter::setMessagesFileContent(const QString &path)
{
    qint64 fileSize = QFileInfo(path).size();
    QString fileName = QFileInfo(path).fileName();
    /*
     * If file name is too large, trim it.
     */
    if (fileName.length() > 15) {
        fileName = fileName.remove(12, fileName.length() - 12) + "...";
    }
    QString param = QString("addFile_path('%1','%2','%3')")
                        .arg(path, fileName, Utils::humanFileSize(fileSize));

    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param));
}

void
MessagesAdapter::removeInteraction(uint64_t interactionId)
{
    QString s = QString::fromLatin1("removeInteraction(%1);").arg(QString::number(interactionId));
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::setSendMessageContent(const QString &content)
{
    QString s = QString::fromLatin1("setSendMessageContent(`%1`);").arg(content);
    QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
}

void
MessagesAdapter::contactIsComposing(const QString &uid, const QString &contactUri, bool isComposing)
{
    if (LRCInstance::getCurrentConvUid() == uid) {
        QString s
            = QString::fromLatin1("showTypingIndicator(`%1`, %2);").arg(contactUri).arg(isComposing);
        QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
    }
}

void
MessagesAdapter::acceptInvitation(const QString &convUid)
{
    const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
    LRCInstance::getCurrentConversationModel()->makePermanent(currentConvUid);
}

void
MessagesAdapter::refuseInvitation(const QString &convUid)
{
    const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
    LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, false);
    setInvitation(false);
}

void
MessagesAdapter::blockConversation(const QString &convUid)
{
    const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
    LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, true);
    setInvitation(false);
}
