/*
 * 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 "conversationsadapter.h"

#include "utils.h"

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

ConversationsAdapter::~ConversationsAdapter() {}

void
ConversationsAdapter::initQmlObject()
{
    conversationSmartListModel_ = new SmartListModel(LRCInstance::getCurrAccId(), this);

    QMetaObject::invokeMethod(qmlObj_, "setModel",
                              Q_ARG(QVariant, QVariant::fromValue(conversationSmartListModel_)));

    connect(&LRCInstance::behaviorController(),
            &BehaviorController::showChatView,
            [this](const QString &accountId, lrc::api::conversation::Info convInfo) {
                emit showChatView(accountId, convInfo.uid);
            });
    connect(&LRCInstance::instance(),
            &LRCInstance::currentAccountChanged,
            this,
            &ConversationsAdapter::slotAccountChanged);

    connectConversationModel();
}

void
ConversationsAdapter::slotAccountChanged()
{
    connectConversationModel();
}

void
ConversationsAdapter::backToWelcomePage()
{
    deselectConversation();
    QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage");
}

void
ConversationsAdapter::selectConversation(const QString &accountId,
                                         const QString &convUid,
                                         bool preventSendingSignal)
{
    auto &accInfo = LRCInstance::getAccountInfo(accountId);
    const auto convInfo = accInfo.conversationModel->getConversationForUID(convUid);

    selectConversation(convInfo, preventSendingSignal);
}

void
ConversationsAdapter::selectConversation(const QString &convUid)
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    if (convModel == nullptr) {
        return;
    }

    const auto &conversation = convModel->getConversationForUID(convUid);

    if (selectConversation(conversation, false)) {

        // If it is calling, show callview (can use showChatView signal, since it will be determined on qml).
        if (!conversation.uid.isEmpty()
            && LRCInstance::getCurrentCallModel()->hasCall(conversation.callId)) {
            emit showChatView(LRCInstance::getCurrAccId(), conversation.uid);
        }
    }
}

bool
ConversationsAdapter::selectConversation(const lrc::api::conversation::Info &item,
                                         bool preventSendingSignal)
{
    // accInfo.conversationModel->selectConversation(item.uid) only emit ui
    // behavior control signals, but sometimes we do not want that,
    // preventSendingSignal boolean can help us to determine.
    if (LRCInstance::getCurrentConvUid() == item.uid) {
        return false;
    } else if (item.participants.size() > 0) {
        auto &accInfo = LRCInstance::getAccountInfo(item.accountId);
        LRCInstance::setSelectedConvId(item.uid);
        if (!preventSendingSignal)
            accInfo.conversationModel->selectConversation(item.uid);
        accInfo.conversationModel->clearUnreadInteractions(item.uid);
        return true;
    }
}

void
ConversationsAdapter::deselectConversation()
{
    if (LRCInstance::getCurrentConvUid().isEmpty()) {
        return;
    }

    auto currentConversationModel = LRCInstance::getCurrentConversationModel();

    if (currentConversationModel == nullptr) {
        return;
    }

    currentConversationModel->selectConversation("");
    LRCInstance::setSelectedConvId();
}

void
ConversationsAdapter::accountChangedSetUp(const QString &accountId)
{
    // Should be called when current account is changed.
    auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
    currentTypeFilter_ = accountInfo.profileInfo.type;
    LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
    updateConversationsFilterWidget();

    connectConversationModel();
}

void
ConversationsAdapter::updateConversationsFilterWidget()
{
    // Update status of "Conversations" and "Invitations".
    auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
    if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
        currentTypeFilter_ = lrc::api::profile::Type::RING;
        LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
    }
    showConversationTabs(invites);
}

void
ConversationsAdapter::setConversationFilter(const QString &type)
{
    // Set conversation filter according to type,
    // type needs to be recognizable by lrc::api::profile::to_type.
    if (type.isEmpty()) {
        if (LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::RING)
            setConversationFilter(lrc::api::profile::Type::RING);
        else
            setConversationFilter(lrc::api::profile::Type::SIP);
    } else {
        setConversationFilter(lrc::api::profile::to_type(type));
    }
}

void
ConversationsAdapter::setConversationFilter(lrc::api::profile::Type filter)
{
    if (currentTypeFilter_ == filter) {
        return;
    }
    currentTypeFilter_ = filter;
    LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
}

bool
ConversationsAdapter::connectConversationModel()
{
    // Signal connections
    auto currentConversationModel = LRCInstance::getCurrentConversationModel();

    QObject::disconnect(modelSortedConnection_);
    QObject::disconnect(modelUpdatedConnection_);
    QObject::disconnect(filterChangedConnection_);
    QObject::disconnect(newConversationConnection_);
    QObject::disconnect(conversationRemovedConnection_);
    QObject::disconnect(conversationClearedConnection);
    QObject::disconnect(newInteractionConnection_);
    QObject::disconnect(interactionRemovedConnection_);
    QObject::disconnect(searchStatusChangedConnection_);
    QObject::disconnect(searchResultUpdatedConnection_);

    modelSortedConnection_ = QObject::connect(currentConversationModel,
                                              &lrc::api::ConversationModel::modelSorted,
                                              [this]() {
        conversationSmartListModel_->fillConversationsList();
        updateConversationsFilterWidget();
        QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
        auto* convModel = LRCInstance::getCurrentConversationModel();
        const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());

        if (conversation.uid.isEmpty() || conversation.participants.isEmpty()) {
            return;
        }
        const auto contactURI = conversation.participants[0];
        if (contactURI.isEmpty()
            || convModel->owner.contactModel->getContact(contactURI).profileInfo.type
                   == lrc::api::profile::Type::TEMPORARY) {
            return;
        }
        QMetaObject::invokeMethod(qmlObj_, "modelSorted", Q_ARG(QVariant, contactURI));
    });

    modelUpdatedConnection_ = QObject::connect(currentConversationModel,
                                               &lrc::api::ConversationModel::conversationUpdated,
                                               [this](const QString &convUid) {
        conversationSmartListModel_->updateConversation(convUid);
        updateConversationsFilterWidget();
        QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
    });

    filterChangedConnection_ = QObject::connect(currentConversationModel,
                                                &lrc::api::ConversationModel::filterChanged,
                                                [this]() {
        conversationSmartListModel_->fillConversationsList();
        QMetaObject::invokeMethod(qmlObj_,
                                  "updateSmartList",
                                  Q_ARG(QVariant, LRCInstance::getCurrAccId()));
        updateConversationsFilterWidget();
        QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
    });

    newConversationConnection_ = QObject::connect(currentConversationModel,
                                                  &lrc::api::ConversationModel::newConversation,
                                                  [this](const QString &convUid) {
        conversationSmartListModel_->fillConversationsList();
        QMetaObject::invokeMethod(qmlObj_,
                                  "updateSmartList",
                                    Q_ARG(QVariant, LRCInstance::getCurrAccId()));
        updateConversationForNewContact(convUid);
    });

    conversationRemovedConnection_ = QObject::connect(currentConversationModel,
                                                      &lrc::api::ConversationModel::conversationRemoved,
                                                      [this]() {
        conversationSmartListModel_->fillConversationsList();
        backToWelcomePage();
    });

    conversationClearedConnection = QObject::connect(currentConversationModel,
                                                     &lrc::api::ConversationModel::conversationCleared,
                                                     [this](const QString &convUid) {
        // If currently selected, switch to welcome screen (deselecting current smartlist item ).
        if (convUid != LRCInstance::getCurrentConvUid()) {
            return;
        }
        backToWelcomePage();
    });

    newInteractionConnection_ = QObject::connect(currentConversationModel,
                                                 &lrc::api::ConversationModel::newInteraction,
                                                 [this] {
        conversationSmartListModel_->fillConversationsList();
        updateConversationsFilterWidget();
        QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
    });

    searchStatusChangedConnection_ = QObject::connect(currentConversationModel,
                                                      &lrc::api::ConversationModel::searchStatusChanged,
                                                      [this](const QString &status) {
        emit showSearchStatus(status);
    });

    searchResultUpdatedConnection_ = QObject::connect(currentConversationModel,
                                                      &lrc::api::ConversationModel::searchResultUpdated,
                                                      [this]() {
        conversationSmartListModel_->fillConversationsList();
        QMetaObject::invokeMethod(qmlObj_, "updateSmartList",
                                  Q_ARG(QVariant, LRCInstance::getCurrAccId()));
        QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
    });

    currentConversationModel->setFilter("");
    return true;
}

void
ConversationsAdapter::updateConversationForNewContact(const QString &convUid)
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    if (convModel == nullptr) {
        return;
    }
    const auto selectedUid = LRCInstance::getCurrentConvUid();
    const auto conversation = convModel->getConversationForUID(convUid);
    if (!conversation.uid.isEmpty() && !conversation.participants.isEmpty()) {
        try {
            const auto contact = convModel->owner.contactModel->getContact(conversation.participants[0]);
            if (!contact.profileInfo.uri.isEmpty() && contact.profileInfo.uri == selectedUid) {
                LRCInstance::setSelectedConvId(convUid);
                convModel->selectConversation(convUid);
            }
        } catch (...) {
            return;
        }
    }
}
