/*
 * Copyright (C) 2019-2020 by Savoir-faire Linux
 * 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/>.
 */

#pragma once

#ifdef _MSC_VER
#undef ERROR
#endif

#include "accountlistmodel.h"
#include "rendermanager.h"
#include "settingskey.h"
#include "utils.h"

#include "api/account.h"
#include "api/avmodel.h"
#include "api/pluginmodel.h"
#include "api/behaviorcontroller.h"
#include "api/contact.h"
#include "api/contactmodel.h"
#include "api/conversation.h"
#include "api/conversationmodel.h"
#include "api/datatransfermodel.h"
#include "api/lrc.h"
#include "api/newaccountmodel.h"
#include "api/newcallmodel.h"
#include "api/newcodecmodel.h"
#include "api/newdevicemodel.h"
#include "api/peerdiscoverymodel.h"

#include <QBuffer>
#include <QMutex>
#include <QObject>
#include <QPixmap>
#include <QRegularExpression>
#include <QSettings>
#include <QtConcurrent/QtConcurrent>

#include <memory>

using namespace lrc::api;

using migrateCallback = std::function<void()>;
using getConvPredicate = std::function<bool(const conversation::Info &conv)>;

class LRCInstance : public QObject
{
    Q_OBJECT

public:
    static LRCInstance &
    instance(migrateCallback willMigrate = {}, migrateCallback didMigrate = {})
    {
        static LRCInstance instance_(willMigrate, didMigrate);
        return instance_;
    };
    static void
    init(migrateCallback willMigrate = {}, migrateCallback didMigrate = {})
    {
        instance(willMigrate, didMigrate);
    };
    static Lrc &
    getAPI()
    {
        return *(instance().lrc_);
    };
    static RenderManager *
    renderer()
    {
        return instance().renderer_.get();
    }
    static void
    connectivityChanged()
    {
        instance().lrc_->connectivityChanged();
    };
    static NewAccountModel &
    accountModel()
    {
        return instance().lrc_->getAccountModel();
    };
    static BehaviorController &
    behaviorController()
    {
        return instance().lrc_->getBehaviorController();
    };
    static DataTransferModel &
    dataTransferModel()
    {
        return instance().lrc_->getDataTransferModel();
    };
    static AVModel &
    avModel()
    {
        return instance().lrc_->getAVModel();
    };
    static PluginModel &
    pluginModel()
    {
        return instance().lrc_->getPluginModel();
    };
    static bool
    isConnected()
    {
        return instance().lrc_->isConnected();
    };
    static VectorString
    getActiveCalls()
    {
        return instance().lrc_->activeCalls();
    };
    static const account::Info &
    getAccountInfo(const QString &accountId)
    {
        return accountModel().getAccountInfo(accountId);
    };
    static const account::Info &
    getCurrentAccountInfo()
    {
        return getAccountInfo(getCurrAccId());
    };
    static bool
    hasVideoCall()
    {
        auto activeCalls = instance().lrc_->activeCalls();
        auto accountList = accountModel().getAccountList();
        bool result = false;
        for (const auto &callId : activeCalls) {
            for (const auto &accountId : accountList) {
                auto &accountInfo = accountModel().getAccountInfo(accountId);
                if (accountInfo.callModel->hasCall(callId)) {
                    auto call = accountInfo.callModel->getCall(callId);
                    result |= !(call.isAudioOnly || call.videoMuted);
                }
            }
        }
        return result;
    };
    static QString
    getCallIdForConversationUid(const QString &convUid, const QString &accountId)
    {
        auto &accInfo = LRCInstance::getAccountInfo(accountId);
        auto convInfo = accInfo.conversationModel->getConversationForUID(convUid);
        if (convInfo.uid.isEmpty()) {
            return {};
        }
        return convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId;
    }
    static const call::Info *
    getCallInfo(const QString &callId, const QString &accountId)
    {
        try {
            auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
            if (!accInfo.callModel->hasCall(callId)) {
                return nullptr;
            }
            return &accInfo.callModel->getCall(callId);
        } catch (...) {
            return nullptr;
        }
    }
    static const call::Info *
    getCallInfoForConversation(const conversation::Info &convInfo, bool forceCallOnly = {})
    {
        try {
            auto accountId = convInfo.accountId;
            auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
            auto callId = forceCallOnly
                              ? convInfo.callId
                              : (convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId);
            if (!accInfo.callModel->hasCall(callId)) {
                return nullptr;
            }
            return &accInfo.callModel->getCall(callId);
        } catch (...) {
            return nullptr;
        }
    }
    static const conversation::Info &
    getConversation(const QString &accountId, getConvPredicate pred = {}, bool filtered = false)
    {
        using namespace lrc::api;
        static conversation::Info invalid = {};
        try {
            auto &accInfo = LRCInstance::getAccountInfo(accountId);
            auto &convModel = accInfo.conversationModel;
            if (filtered) {
                auto &convs = convModel->allFilteredConversations();
                auto conv = std::find_if(convs.begin(), convs.end(), pred);
                if (conv != convs.end()) {
                    return *conv;
                }
            } else {
                for (int i = Utils::toUnderlyingValue(profile::Type::RING);
                     i <= Utils::toUnderlyingValue(profile::Type::TEMPORARY);
                     ++i) {
                    auto filter = Utils::toEnum<profile::Type>(i);
                    auto &convs = convModel->getFilteredConversations(filter);
                    auto conv = std::find_if(convs.begin(), convs.end(), pred);
                    if (conv != convs.end()) {
                        return *conv;
                    }
                }
            }
        } catch (...) {
        }
        return invalid;
    }
    static const conversation::Info &
    getConversationFromCallId(const QString &callId,
                              const QString &accountId = {},
                              bool filtered = false)
    {
        return getConversation(
            !accountId.isEmpty() ? accountId : getCurrAccId(),
            [&](const conversation::Info &conv) -> bool { return callId == conv.callId or callId == conv.confId; },
            filtered);
    }
    static const conversation::Info &
    getConversationFromPeerUri(const QString &peerUri,
                               const QString &accountId = {},
                               bool filtered = false)
    {
        return getConversation(
            !accountId.isEmpty() ? accountId : getCurrAccId(),
            [&](const conversation::Info &conv) -> bool { return peerUri == conv.participants[0]; },
            filtered);
    }

    static ConversationModel *
    getCurrentConversationModel()
    {
        return getCurrentAccountInfo().conversationModel.get();
    };

    static NewCallModel *
    getCurrentCallModel()
    {
        return getCurrentAccountInfo().callModel.get();
    };

    static const QString &
    getCurrAccId()
    {
        auto accountList = accountModel().getAccountList();
        if (instance().selectedAccountId_.isEmpty() && accountList.size()) {
            instance().selectedAccountId_ = accountList.at(0);
        }
        return instance().selectedAccountId_;
    };

    static void
    setSelectedAccountId(const QString &accountId = {})
    {
        instance().selectedAccountId_ = accountId;
        emit instance().currentAccountChanged();
        QSettings settings("jami.net", "Jami");
        settings.setValue(SettingsKey::selectedAccount, accountId);

        // Last selected account should be set as preferred.
        accountModel().setTopAccount(accountId);
    };

    static const QString &
    getCurrentConvUid()
    {
        return instance().selectedConvUid_;
    };

    static void
    setSelectedConvId(const QString &convUid = {})
    {
        instance().selectedConvUid_ = convUid;
    };

    static void
    reset(bool newInstance = false)
    {
        if (newInstance) {
            instance().renderer_.reset(new RenderManager(avModel()));
            instance().lrc_.reset(new Lrc());
        } else {
            instance().renderer_.reset();
            instance().lrc_.reset();
        }
    };

    static const int
    getCurrentAccountIndex()
    {
        for (int i = 0; i < accountModel().getAccountList().size(); i++) {
            if (accountModel().getAccountList()[i] == getCurrAccId()) {
                return i;
            }
        }
        return -1;
    };

    static const QPixmap
    getCurrAccPixmap()
    {
        return instance()
            .accountListModel_
            .data(instance().accountListModel_.index(getCurrentAccountIndex()),
                  AccountListModel::Role::Picture)
            .value<QPixmap>();
    };

    static void
    setAvatarForAccount(const QPixmap &avatarPixmap, const QString &accountID)
    {
        QByteArray ba;
        QBuffer bu(&ba);
        bu.open(QIODevice::WriteOnly);
        avatarPixmap.save(&bu, "PNG");
        auto str = QString::fromLocal8Bit(ba.toBase64());
        accountModel().setAvatar(accountID, str);
    };

    static void
    setCurrAccAvatar(const QPixmap &avatarPixmap)
    {
        QByteArray ba;
        QBuffer bu(&ba);
        bu.open(QIODevice::WriteOnly);
        avatarPixmap.save(&bu, "PNG");
        auto str = QString::fromLocal8Bit(ba.toBase64());
        accountModel().setAvatar(getCurrAccId(), str);
    };

    static void
    setCurrAccAvatar(const QString &avatar)
    {
        accountModel().setAvatar(getCurrAccId(), avatar);
    };

    static void
    setCurrAccDisplayName(const QString &displayName)
    {
        auto accountId = LRCInstance::getCurrAccId();
        accountModel().setAlias(accountId, displayName);
        /*
         * Force save to .yml.
         */
        auto confProps = LRCInstance::accountModel().getAccountConfig(accountId);
        LRCInstance::accountModel().setAccountConfig(accountId, confProps);
    };

    static const account::ConfProperties_t &
    getCurrAccConfig()
    {
        return instance().getCurrentAccountInfo().confProperties;
    }

    static void
    subscribeToDebugReceived()
    {
        instance().lrc_->subscribeToDebugReceived();
    }

    static void
    startAudioMeter(bool async)
    {
        auto f = [] {
            if (!LRCInstance::getActiveCalls().size()) {
                LRCInstance::avModel().startAudioDevice();
            }
            LRCInstance::avModel().setAudioMeterState(true);
        };
        if (async) {
            QtConcurrent::run(f);
        } else {
            f();
        }
    }

    static void
    stopAudioMeter(bool async)
    {
        auto f = [] {
            if (!LRCInstance::getActiveCalls().size()) {
                LRCInstance::avModel().stopAudioDevice();
            }
            LRCInstance::avModel().setAudioMeterState(false);
        };
        if (async) {
            QtConcurrent::run(f);
        } else {
            f();
        }
    }

    static QString
    getContentDraft(const QString &convUid, const QString &accountId)
    {
        auto draftKey = accountId + "_" + convUid;
        return instance().contentDrafts_[draftKey];
    }

    static void
    setContentDraft(const QString &convUid, const QString &accountId, const QString &content)
    {
        auto draftKey = accountId + "_" + convUid;
        instance().contentDrafts_[draftKey] = content;
    }

    static void
    pushLastConferencee(const QString &confId, const QString &callId)
    {
        instance().lastConferencees_[confId] = callId;
    }

    static QString
    popLastConferencee(const QString &confId)
    {
        QString callId = {};
        auto iter = instance().lastConferencees_.find(confId);
        if (iter != instance().lastConferencees_.end()) {
            callId = iter.value();
            instance().lastConferencees_.erase(iter);
        }
        return callId;
    }

signals:
    void accountListChanged();
    void currentAccountChanged();

private:
    LRCInstance(migrateCallback willMigrateCb = {}, migrateCallback didMigrateCb = {})
    {
        lrc_ = std::make_unique<Lrc>(willMigrateCb, didMigrateCb);
        renderer_ = std::make_unique<RenderManager>(lrc_->getAVModel());
    };

    std::unique_ptr<Lrc> lrc_;
    std::unique_ptr<RenderManager> renderer_;
    AccountListModel accountListModel_;
    QString selectedAccountId_;
    QString selectedConvUid_;
    MapStringString contentDrafts_;
    MapStringString lastConferencees_;
};
Q_DECLARE_METATYPE(LRCInstance *)
