/*
 * 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>
 * Author: Sébastien Blin <sebastien.blin@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 "calladapter.h"

#include "globalsystemtray.h"
#include "utils.h"

CallAdapter::CallAdapter(QObject* parent)
    : QmlAdapterBase(parent)
    , oneSecondTimer_(new QTimer(this))
{}

CallAdapter::~CallAdapter() {}

void
CallAdapter::initQmlObject()
{
    connectCallModel(LRCInstance::getCurrAccId());

    connect(&LRCInstance::behaviorController(),
            &BehaviorController::showIncomingCallView,
            this,
            &CallAdapter::slotShowIncomingCallView);
    connect(&LRCInstance::instance(),
            &LRCInstance::currentAccountChanged,
            this,
            &CallAdapter::slotAccountChanged);
    connect(&LRCInstance::behaviorController(),
            &BehaviorController::showCallView,
            this,
            &CallAdapter::slotShowCallView);
}

void
CallAdapter::slotAccountChanged()
{
    connectCallModel(LRCInstance::getCurrAccId());
}

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

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

void
CallAdapter::hangUpACall(const QString& accountId, const QString& convUid)
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid);
    if (!convInfo.uid.isEmpty()) {
        LRCInstance::getAccountInfo(accountId).callModel->hangUp(convInfo.callId);
    }
}

void
CallAdapter::refuseACall(const QString& accountId, const QString& convUid)
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid);
    if (!convInfo.uid.isEmpty()) {
        LRCInstance::getAccountInfo(accountId).callModel->refuse(convInfo.callId);
    }
}

void
CallAdapter::acceptACall(const QString& accountId, const QString& convUid)
{
    emit incomingCallNeedToSetupMainView(accountId, convUid);
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid);
    if (!convInfo.uid.isEmpty()) {
        LRCInstance::getAccountInfo(accountId).callModel->accept(convInfo.callId);
        auto& accInfo = LRCInstance::getAccountInfo(convInfo.accountId);
        accInfo.callModel->setCurrentCall(convInfo.callId);
    }
}

void
CallAdapter::slotShowIncomingCallView(const QString& accountId, const conversation::Info& convInfo)
{
    auto* callModel = LRCInstance::getCurrentCallModel();

    if (!callModel->hasCall(convInfo.callId)) {
        /*
         * Connection to close potential incoming call page when it is not current account.
         */
        auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);

        QObject::disconnect(closeIncomingCallPageConnection_);

        closeIncomingCallPageConnection_
            = QObject::connect(accInfo.callModel.get(),
                               &lrc::api::NewCallModel::callStatusChanged,
                               [this, accountId, uid = convInfo.uid](const QString& callId) {
                                   auto& accInfo = LRCInstance::accountModel().getAccountInfo(
                                       accountId);
                                   auto& callModel = accInfo.callModel;
                                   auto call = callModel->getCall(callId);

                                   switch (call.status) {
                                   case lrc::api::call::Status::INVALID:
                                   case lrc::api::call::Status::INACTIVE:
                                   case lrc::api::call::Status::ENDED:
                                   case lrc::api::call::Status::PEER_BUSY:
                                   case lrc::api::call::Status::TIMEOUT:
                                   case lrc::api::call::Status::TERMINATING: {
                                       if (!uid.isEmpty())
                                           emit closePotentialIncomingCallPageWindow(accountId, uid);
                                       break;
                                   }
                                   default:
                                       break;
                                   }

                                   emit updateConversationSmartList();
                                   QObject::disconnect(closeIncomingCallPageConnection_);
                               });
        /*
         * Show incoming call page only.
         */
        auto accountProperties = LRCInstance::accountModel().getAccountConfig(accountId);
        if (!accountProperties.autoAnswer && !accountProperties.isRendezVous) {
            emit showIncomingCallPage(accountId, convInfo.uid);
        }
        return;
    }

    auto call = callModel->getCall(convInfo.callId);
    auto isCallSelected = LRCInstance::getCurrentConvUid() == convInfo.uid;

    if (call.isOutgoing) {
        if (isCallSelected) {
            emit showOutgoingCallPage(accountId, convInfo.uid);
            emit showCallStack(accountId, convInfo.uid);
        }
    } else {
        auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
        auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
        if (!accountProperties.autoAnswer && !accountProperties.isRendezVous) {
            emit showIncomingCallPage(accountId, convInfo.uid);
        }
    }

    emit callStatusChanged(static_cast<int>(call.status), accountId, convInfo.uid);

    emit updateConversationSmartList();
}

void
CallAdapter::slotShowCallView(const QString& accountId, const lrc::api::conversation::Info& convInfo)
{
    updateCall(convInfo.uid, accountId);
}

void
CallAdapter::updateCall(const QString& convUid, const QString& accountId, bool forceCallOnly)
{
    accountId_ = accountId.isEmpty() ? accountId_ : accountId;
    convUid_ = convUid.isEmpty() ? convUid_ : convUid;

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

    auto call = LRCInstance::getCallInfoForConversation(convInfo, forceCallOnly);
    if (!call) {
        return;
    }

    if (call->isAudioOnly) {
        emit showAudioCallPage(accountId_, convUid_);
    } else {
        emit showVideoCallPage(accountId_, convUid_, call->id);
    }

    updateCallOverlay(convInfo);

    /*
     * Preview.
     */
    emit previewVisibilityNeedToChange(shouldShowPreview(forceCallOnly));

    emit showCallStack(accountId_, convUid_);
}

bool
CallAdapter::shouldShowPreview(bool force)
{
    bool shouldShowPreview {false};
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid_);
    if (convInfo.uid.isEmpty()) {
        return shouldShowPreview;
    }
    auto call = LRCInstance::getCallInfoForConversation(convInfo, force);
    if (call) {
        shouldShowPreview = !call->isAudioOnly && !(call->status == lrc::api::call::Status::PAUSED)
                            && !call->videoMuted && call->type != lrc::api::call::Type::CONFERENCE;
    }
    return shouldShowPreview;
}

QVariantList
CallAdapter::getConferencesInfos()
{
    QVariantList map;
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid_);
    if (convInfo.uid.isEmpty())
        return map;
    auto callId = convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId;
    if (!callId.isEmpty()) {
        try {
            auto call = LRCInstance::getCurrentCallModel()->getCall(callId);
            for (const auto& participant : call.participantsInfos) {
                QJsonObject data;
                data["x"] = participant["x"].toInt();
                data["y"] = participant["y"].toInt();
                data["w"] = participant["w"].toInt();
                data["h"] = participant["h"].toInt();
                data["active"] = participant["active"] == "true";
                auto bestName = participant["uri"];
                auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
                data["isLocal"] = false;
                if (bestName == accInfo.profileInfo.uri) {
                    bestName = tr("me");
                    data["isLocal"] = true;
                } else {
                    try {
                        auto& contact = LRCInstance::getCurrentAccountInfo()
                                            .contactModel->getContact(participant["uri"]);
                        bestName = Utils::bestNameForContact(contact);
                    } catch (...) {
                    }
                }
                data["bestName"] = bestName;

                map.push_back(QVariant(data));
            }
            return map;
        } catch (...) {
        }
    }
    return map;
}

void
CallAdapter::connectCallModel(const QString& accountId)
{
    auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);

    QObject::disconnect(callStatusChangedConnection_);
    QObject::disconnect(onParticipantsChangedConnection_);

    onParticipantsChangedConnection_ = QObject::connect(
        accInfo.callModel.get(),
        &lrc::api::NewCallModel::onParticipantsChanged,
        [this, accountId](const QString& confId) {
            auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
            auto& callModel = accInfo.callModel;
            auto call = callModel->getCall(confId);
            const auto convInfo = LRCInstance::getConversationFromCallId(confId);
            if (!convInfo.uid.isEmpty()) {
                // Convert to QML
                QVariantList map;
                for (const auto& participant : call.participantsInfos) {
                    QJsonObject data;
                    data["x"] = participant["x"].toInt();
                    data["y"] = participant["y"].toInt();
                    data["w"] = participant["w"].toInt();
                    data["h"] = participant["h"].toInt();
                    data["uri"] = participant["uri"];
                    data["active"] = participant["active"] == "true";
                    data["videoMuted"] = participant["videoMuted"] == "true";
                    data["audioMuted"] = participant["audioMuted"] == "true";
                    auto bestName = participant["uri"];
                    data["isLocal"] = false;
                    auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
                    if (bestName == accInfo.profileInfo.uri) {
                        bestName = tr("me");
                        data["isLocal"] = true;
                        if (participant["videoMuted"] == "true")
                            data["avatar"] = accInfo.profileInfo.avatar;
                    } else {
                        try {
                            auto& contact = LRCInstance::getCurrentAccountInfo()
                                                .contactModel->getContact(participant["uri"]);
                            bestName = Utils::bestNameForContact(contact);
                            if (participant["videoMuted"] == "true")
                                data["avatar"] = contact.profileInfo.avatar;
                        } catch (...) {}
                    }
                    data["bestName"] = bestName;
                    map.push_back(QVariant(data));
                }
                emit updateParticipantsInfos(map, accountId, confId);
            }
        });

    callStatusChangedConnection_ = QObject::connect(
        accInfo.callModel.get(),
        &lrc::api::NewCallModel::callStatusChanged,
        [this, accountId](const QString& callId) {
            auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
            auto& callModel = accInfo.callModel;
            const auto call = callModel->getCall(callId);

            /*
             * Change status label text.
             */
            const auto convInfo = LRCInstance::getConversationFromCallId(callId);
            if (!convInfo.uid.isEmpty()) {
                emit callStatusChanged(static_cast<int>(call.status), accountId, convInfo.uid);
            }

            switch (call.status) {
            case lrc::api::call::Status::INVALID:
            case lrc::api::call::Status::INACTIVE:
            case lrc::api::call::Status::ENDED:
            case lrc::api::call::Status::PEER_BUSY:
            case lrc::api::call::Status::TIMEOUT:
            case lrc::api::call::Status::TERMINATING: {
                LRCInstance::renderer()->removeDistantRenderer(callId);
                if (convInfo.uid.isEmpty()) {
                    break;
                }
                /*
                 * If it's a conference, change the smartlist index
                 * to the next remaining participant.
                 */
                bool forceCallOnly {false};
                if (!convInfo.confId.isEmpty()) {
                    auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId);
                    if (callList.empty()) {
                        auto lastConferencee = LRCInstance::instance().popLastConferencee(
                            convInfo.confId);
                        callList.append(lastConferencee);
                        forceCallOnly = true;
                    }
                    for (const auto& callId : callList) {
                        if (!callModel->hasCall(callId)) {
                            continue;
                        }
                        auto otherConv = LRCInstance::getConversationFromCallId(callId);
                        if (!otherConv.uid.isEmpty() && otherConv.uid != convInfo.uid) {
                            /*
                             * Reset the call view corresponding accountId, uid.
                             */
                            LRCInstance::setSelectedConvId(otherConv.uid);
                            showCallStack(otherConv.accountId, otherConv.uid, true);
                            updateCall(otherConv.uid, otherConv.accountId, forceCallOnly);
                        }
                    }
                } else {
                    emit closeCallStack(accountId, convInfo.uid);
                    emit closePotentialIncomingCallPageWindow(accountId, convInfo.uid);
                }

                break;
            }
            case lrc::api::call::Status::CONNECTED:
            case lrc::api::call::Status::IN_PROGRESS: {
                const auto convInfo = LRCInstance::getConversationFromCallId(callId, accountId);
                if (!convInfo.uid.isEmpty() && convInfo.uid == LRCInstance::getCurrentConvUid()) {
                    accInfo.conversationModel->selectConversation(convInfo.uid);
                }
                LRCInstance::renderer()->addDistantRenderer(callId);
                updateCall();
                LRCInstance::getAccountInfo(accountId).callModel->setCurrentCall(callId);
                break;
            }
            case lrc::api::call::Status::PAUSED:
                updateCall();
            default:
                break;
            }

            emit updateConversationSmartList();
        });
}

void
CallAdapter::sipInputPanelPlayDTMF(const QString& key)
{
    auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
    if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
        return;
    }

    LRCInstance::getCurrentCallModel()->playDTMF(callId, key);
}

/*
 * For Call Overlay
 */
void
CallAdapter::updateCallOverlay(const lrc::api::conversation::Info& convInfo)
{
    setTime(accountId_, convUid_);
    QObject::disconnect(oneSecondTimer_);
    QObject::connect(oneSecondTimer_, &QTimer::timeout, [this] { setTime(accountId_, convUid_); });
    oneSecondTimer_->start(20);
    auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);

    auto call = LRCInstance::getCallInfoForConversation(convInfo);
    if (!call) {
        return;
    }

    bool isPaused = call->status == lrc::api::call::Status::PAUSED;
    bool isAudioOnly = call->isAudioOnly && !isPaused;
    bool isAudioMuted = call->audioMuted && (call->status != lrc::api::call::Status::PAUSED);
    bool isVideoMuted = call->videoMuted && !isPaused && !call->isAudioOnly;
    bool isRecording = isRecordingThisCall();

    emit updateOverlay(isPaused,
                       isAudioOnly,
                       isAudioMuted,
                       isVideoMuted,
                       isRecording,
                       accInfo.profileInfo.type == lrc::api::profile::Type::SIP,
                       !convInfo.confId.isEmpty(),
                       Utils::bestNameForConversation(convInfo,
                                                      *LRCInstance::getCurrentConversationModel()));
}

void
CallAdapter::hangupCall(const QString& uri)
{
    const auto convInfo = LRCInstance::getConversationFromPeerUri(uri, accountId_);
    if (!convInfo.uid.isEmpty()) {
        auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
        if (callModel->hasCall(convInfo.callId)) {
            /*
             * Store the last remaining participant of the conference,
             * so we can switch the smartlist index after termination.
             */
            if (!convInfo.confId.isEmpty()) {
                auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId);
                if (callList.size() == 2) {
                    for (const auto& cId : callList) {
                        if (cId != convInfo.callId) {
                            LRCInstance::instance().pushLastConferencee(convInfo.confId, cId);
                        }
                    }
                }
            }

            callModel->hangUp(convInfo.callId);
        }
    }
}

void
CallAdapter::maximizeParticipant(const QString& uri, bool isActive)
{
    auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
    const auto confId = conversation.confId;

    QString callId;
    if (LRCInstance::getCurrentAccountInfo().profileInfo.uri != uri) {
        const auto convInfo = LRCInstance::getConversationFromPeerUri(uri, accountId_);
        if (!convInfo.uid.isEmpty()) {
            callId = convInfo.callId;
        }
    }
    try {
        const auto call = callModel->getCall(confId);
        switch (call.layout) {
        case lrc::api::call::Layout::GRID:
            callModel->setActiveParticipant(confId, callId);
            callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
            break;
        case lrc::api::call::Layout::ONE_WITH_SMALL:
            callModel->setActiveParticipant(confId, callId);
            callModel->setConferenceLayout(confId,
                                           isActive ? lrc::api::call::Layout::ONE
                                                    : lrc::api::call::Layout::ONE_WITH_SMALL);
            break;
        case lrc::api::call::Layout::ONE:
            callModel->setActiveParticipant(confId, callId);
            callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
            break;
        };
    } catch (...) {
    }
}

void
CallAdapter::minimizeParticipant()
{
    auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
    const auto confId = conversation.confId;
    try {
        auto call = callModel->getCall(confId);
        switch (call.layout) {
        case lrc::api::call::Layout::GRID:
            break;
        case lrc::api::call::Layout::ONE_WITH_SMALL:
            callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
            break;
        case lrc::api::call::Layout::ONE:
            callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
            break;
        };
    } catch (...) {
    }
}

void
CallAdapter::hangUpThisCall()
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid_);
    if (!convInfo.uid.isEmpty()) {
        auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
        if (!convInfo.confId.isEmpty() && callModel->hasCall(convInfo.confId)) {
            callModel->hangUp(convInfo.confId);
        } else if (callModel->hasCall(convInfo.callId)) {
            callModel->hangUp(convInfo.callId);
        }
    }
}

bool
CallAdapter::isRecordingThisCall()
{
    auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
    auto& convModel = accInfo.conversationModel;
    const auto convInfo = convModel->getConversationForUID(convUid_);
    return accInfo.callModel->isRecording(convInfo.confId)
           || accInfo.callModel->isRecording(convInfo.callId);
}

bool
CallAdapter::isCurrentMaster() const
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid_);
    if (!convInfo.uid.isEmpty()) {
        auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
        try {
            if (!convInfo.confId.isEmpty() && callModel->hasCall(convInfo.confId)) {
                return true;
            } else {
                auto call = callModel->getCall(convInfo.callId);
                return call.participantsInfos.size() == 0;
            }
        } catch (...) {
        }
    }
    return true;
}

int
CallAdapter::getCurrentLayoutType() const
{
    auto* convModel = LRCInstance::getCurrentConversationModel();
    const auto convInfo = convModel->getConversationForUID(convUid_);
    if (!convInfo.uid.isEmpty()) {
        auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
        try {
            auto call = callModel->getCall(convInfo.confId);
            return Utils::toUnderlyingValue(call.layout);
        } catch (...) {
        }
    }
    return -1;
}

void
CallAdapter::holdThisCallToggle()
{
    const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
    if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
        return;
    }
    auto* callModel = LRCInstance::getCurrentCallModel();
    if (callModel->hasCall(callId)) {
        callModel->togglePause(callId);
    }
    emit showOnHoldLabel(true);
}

void
CallAdapter::muteThisCallToggle()
{
    const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
    if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
        return;
    }
    auto* callModel = LRCInstance::getCurrentCallModel();
    if (callModel->hasCall(callId)) {
        callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::AUDIO);
    }
}

void
CallAdapter::recordThisCallToggle()
{
    const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
    if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
        return;
    }
    auto* callModel = LRCInstance::getCurrentCallModel();
    if (callModel->hasCall(callId)) {
        callModel->toggleAudioRecord(callId);
    }
}

void
CallAdapter::videoPauseThisCallToggle()
{
    const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
    if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
        return;
    }
    auto* callModel = LRCInstance::getCurrentCallModel();
    if (callModel->hasCall(callId)) {
        callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::VIDEO);
    }
    emit previewVisibilityNeedToChange(shouldShowPreview(false));
}

void
CallAdapter::setTime(const QString& accountId, const QString& convUid)
{
    const auto callId = LRCInstance::getCallIdForConversationUid(convUid, accountId);
    if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
        return;
    }
    const auto callInfo = LRCInstance::getCurrentCallModel()->getCall(callId);
    if (callInfo.status == lrc::api::call::Status::IN_PROGRESS
        || callInfo.status == lrc::api::call::Status::PAUSED) {
        auto timeString = LRCInstance::getCurrentCallModel()->getFormattedCallDuration(callId);
        emit updateTimeText(timeString);
    }
}