#include "BackupCandidatesComponent.h"

#include "AddExclusionRule.h"
#include "BackupCandidatesController.h"
#include "BackupCandidatesModel.h"
#include "DialogOpener.h"
#include "MegaApplication.h"
#include "Preferences.h"
#include "SyncsQmlDialog.h"

static bool qmlRegistrationDone = false;

BackupCandidatesComponent::BackupCandidatesComponent(QObject* parent):
    QMLComponent(parent),
    mOrigin(SyncInfo::SyncOrigin::NONE),
    mBackupCandidatesController(std::make_shared<BackupCandidatesController>()),
    mBackupsProxyModel(new BackupCandidatesProxyModel(mBackupCandidatesController))
{
    registerQmlModules();

    mBackupCandidatesController->initWithDefaultDirectories();
    // Just in case it is used from the Onboarding Dialog
    QmlManager::instance()->setRootContextProperty(this);

    connect(mBackupCandidatesController.get(),
            &BackupCandidatesController::backupsCreationFinished,
            this,
            &BackupCandidatesComponent::onBackupsCreationFinished);
}

BackupCandidatesComponent::~BackupCandidatesComponent()
{
    if (mBackupsProxyModel)
    {
        mBackupsProxyModel->deleteLater();
    }
}

QUrl BackupCandidatesComponent::getQmlUrl()
{
    return QUrl(QString::fromUtf8("qrc:/backups/BackupsDialog.qml"));
}

void BackupCandidatesComponent::registerQmlModules()
{
    if (!qmlRegistrationDone)
    {
        qmlRegisterType<BackupCandidatesComponent>("BackupsComponent", 1, 0, "BackupsComponent");
        qmlRegisterType<SyncsQmlDialog>("BackupsComponent", 1, 0, "SyncsQmlDialog");
        qmlRegisterType<BackupCandidatesProxyModel>("BackupCandidatesProxyModel",
                                                    1,
                                                    0,
                                                    "BackupCandidatesProxyModel");
        qmlRegisterType<BackupCandidates>("BackupCandidates", 1, 0, "BackupCandidates");
        qmlRegistrationDone = true;
    }
}

void BackupCandidatesComponent::openBackupsTabInPreferences() const
{
    MegaSyncApp->openSettings(SettingsDialog::BACKUP_TAB);
}

BackupCandidates* BackupCandidatesComponent::getData()
{
    return mBackupCandidatesController->getBackupCandidates().get();
}

void BackupCandidatesComponent::onBackupsCreationFinished(bool success)
{
    emit backupsCreationFinished(success);
    if (success)
    {
        mBackupsProxyModel->setSelectedFilterEnabled(false);
        MegaSyncApp->getStatsEventHandler()->sendTrackedEvent(getEventType());
        // Send event for the first backup
        if (!Preferences::instance()->isFirstBackupDone())
        {
            if (mOrigin == SyncInfo::SyncOrigin::ONBOARDING_ORIGIN)
            {
                MegaSyncApp->getStatsEventHandler()->sendEvent(
                    AppStatsEvents::EventType::
                        FIRST_BACKUP_FROM_ONBOARDING); // When the event sending is done,
                                                       // MegaApplication updates
                                                       // Preferences::setFirstBackupDone
            }
            else
            {
                MegaSyncApp->getStatsEventHandler()->sendEvent(
                    AppStatsEvents::EventType::FIRST_BACKUP);
            }
        }
    }
}

void BackupCandidatesComponent::setOrigin(SyncInfo::SyncOrigin origin)
{
    mOrigin = origin;
}

void BackupCandidatesComponent::openExclusionsDialog() const
{
    auto folderPaths = mBackupCandidatesController->getSelectedCandidates();

    QmlDialog* parent(QmlDialogWrapperUtilities::getQmlDialog<BackupCandidatesComponent>());
    QPointer<QmlDialogWrapper<AddExclusionRule>> exclusions =
        new QmlDialogWrapper<AddExclusionRule>(parent, folderPaths);
    DialogOpener::showDialog(exclusions);
}

void BackupCandidatesComponent::confirmFoldersMoveToSelect()
{
    mBackupsProxyModel->setSelectedFilterEnabled(false);
}

void BackupCandidatesComponent::selectFolderMoveToConfirm()
{
    mBackupCandidatesController->calculateFolderSizes();
    mBackupsProxyModel->setSelectedFilterEnabled(true);
    mBackupCandidatesController->refreshBackupCandidatesErrors();
}

void BackupCandidatesComponent::insertFolder(const QString& path)
{
    auto row = mBackupCandidatesController->insert(path);
    emit insertFolderAdded(row);
}

void BackupCandidatesComponent::insertFolders(const QStringList& folders)
{
    int row(-1);

    for (auto& folder: folders)
    {
        row = mBackupCandidatesController->insert(folder);
    }

    if (row >= 0)
    {
        emit insertFolderAdded(row);
    }
}

int BackupCandidatesComponent::rename(const QString& folder, const QString& newName)
{
    return mBackupCandidatesController->rename(folder, newName);
}

void BackupCandidatesComponent::remove(const QString& folder)
{
    mBackupCandidatesController->remove(folder);
}

void BackupCandidatesComponent::change(const QString& folder, const QString& newFolder)
{
    mBackupCandidatesController->change(folder, newFolder);
}

void BackupCandidatesComponent::selectAllFolders(Qt::CheckState state, bool fromModel)
{
    mBackupCandidatesController->setCheckAllState(state, fromModel);
}

void BackupCandidatesComponent::createBackups()
{
    mBackupCandidatesController->createBackups();
}

AppStatsEvents::EventType BackupCandidatesComponent::getEventType() const
{
    switch (mOrigin)
    {
        case SyncInfo::SyncOrigin::CONTEXT_MENU_ORIGIN:
            return AppStatsEvents::EventType::BACKUP_ADDED_CONTEXT_MENU;
        case SyncInfo::SyncOrigin::EXTERNAL_ORIGIN:
            return AppStatsEvents::EventType::BACKUP_ADDED_WEBCLIENT;
        case SyncInfo::SyncOrigin::ONBOARDING_ORIGIN:
            return AppStatsEvents::EventType::BACKUP_ADDED_ONBOARDING;
        case SyncInfo::SyncOrigin::SETTINGS_ORIGIN:
            return AppStatsEvents::EventType::BACKUP_ADDED_SETTINGS;
        case SyncInfo::SyncOrigin::SHELL_EXT_ORIGIN:
            return AppStatsEvents::EventType::BACKUP_ADDED_SHELL_EXTENSION;
        case SyncInfo::SyncOrigin::MAIN_APP_ORIGIN:
        default:
            return AppStatsEvents::EventType::BACKUP_ADDED_MAIN_APP;
    }
}
