#include "QmlDialogManager.h"

#include "AccountStatusController.h"
#include "AppState.h"
#include "DialogOpener.h"
#include "GuestContent.h"
#include "GuestQmlDialog.h"
#include "LoginController.h"
#include "megaapi.h"
#include "Onboarding.h"
#include "OnboardingQmlDialog.h"
#include "QmlDialogWrapper.h"

std::shared_ptr<QmlDialogManager> QmlDialogManager::instance()
{
    static std::shared_ptr<QmlDialogManager> manager(new QmlDialogManager());
    return manager;
}

QmlDialogManager* QmlDialogManager::getQmlInstance(QQmlEngine* qmlEngine, QJSEngine* jsEngine)
{
    Q_UNUSED(qmlEngine)
    Q_UNUSED(jsEngine)
    return instance().get();
}

void QmlDialogManager::openGuestDialog()
{
    if(MegaSyncApp->finished())
    {
        return;
    }

    auto dialogWrapper = DialogOpener::findDialog<QmlDialogWrapper<GuestContent>>();
    if(dialogWrapper == nullptr)
    {
        QPointer<QmlDialogWrapper<GuestContent>> guest = new QmlDialogWrapper<GuestContent>();
        DialogOpener::addDialog(guest)->setIgnoreRaiseAllAction(true);
        dialogWrapper = DialogOpener::findDialog<QmlDialogWrapper<GuestContent>>();
    }

    DialogOpener::showDialog(dialogWrapper->getDialog());
}

bool QmlDialogManager::openOnboardingDialog(bool force)
{
    const bool appFinished = MegaSyncApp->finished();
    const bool logged = Preferences::instance()->logged();
    const auto session = Preferences::instance()->getSession();
    const bool hasSession = !session.isEmpty();

    if (appFinished || (!force && hasSession))
    {
        mega::MegaApi::log(mega::MegaApi::LOG_LEVEL_INFO,
                           QString::fromUtf8("Logout diagnostics: openOnboardingDialog() blocked. "
                                             "force=%1 appFinished=%2 logged=%3 sessionEmpty=%4")
                               .arg(force)
                               .arg(appFinished)
                               .arg(logged)
                               .arg(session.isEmpty())
                               .toUtf8()
                               .constData());
        return false;
    }

    if(auto dialog = DialogOpener::findDialog<QmlDialogWrapper<Onboarding>>())
    {
        mega::MegaApi::log(
            mega::MegaApi::LOG_LEVEL_INFO,
            "Logout diagnostics: openOnboardingDialog() reusing existing onboarding dialog.");
        DialogOpener::showDialog(dialog->getDialog());
    }
    else
    {
        mega::MegaApi::log(
            mega::MegaApi::LOG_LEVEL_INFO,
            QString::fromUtf8("Logout diagnostics: openOnboardingDialog() creating new onboarding "
                              "dialog. force=%1 logged=%2 sessionEmpty=%3")
                .arg(force)
                .arg(logged)
                .arg(session.isEmpty())
                .toUtf8()
                .constData());
        QPointer<QmlDialogWrapper<Onboarding>> onboarding = new QmlDialogWrapper<Onboarding>();
        auto onboardingInfo(DialogOpener::showDialog(onboarding));
        if (onboardingInfo)
        {
            onboardingInfo->setIgnoreCloseAllAction(true);
        }
    }
    emit openOnboardingDialogSignal();
    return true;
}

bool QmlDialogManager::raiseGuestDialog()
{
    bool raisedGuestDialog = false;
    if (MegaSyncApp->getAccountStatusController()->isAccountBlocked() ||
        (MegaSyncApp->getLoginController() &&
         MegaSyncApp->getLoginController()->getState() != LoginController::FETCH_NODES_FINISHED) ||
        AppState::instance()->getAppState() != AppState::NOMINAL)
    {
        openGuestDialog();
        raisedGuestDialog = true;
    }
    return raisedGuestDialog;
}

void QmlDialogManager::raiseOnboardingDialog()
{
    if(MegaSyncApp->getAccountStatusController()->isAccountBlocked()
        || (MegaSyncApp->getLoginController()
                && MegaSyncApp->getLoginController()->getState() != LoginController::FETCH_NODES_FINISHED))
    {
        if (Preferences::instance()->getSession().isEmpty())
        {
            openOnboardingDialog();
        }
        else if(auto dialog = DialogOpener::findDialog<QmlDialogWrapper<Onboarding>>())
        {
            DialogOpener::showDialog(dialog->getDialog());
            dialog->getDialog()->raise();
        }
    }
}

void QmlDialogManager::raiseOrHideInfoGuestDialog(QTimer* dialogTimer, int msec)
{
    if(!dialogTimer || msec < 0)
    {
        return;
    }

    auto guestDialogWrapper = DialogOpener::findDialog<QmlDialogWrapper<GuestContent>>();
    if(guestDialogWrapper == nullptr) //dialog still not built
    {
        dialogTimer->start(msec);
        return;
    }

    auto dialog = dynamic_cast<GuestQmlDialog*>(guestDialogWrapper->getDialog()->windowHandle());
    if(dialog && dialog->isHiddenForLongTime())
    {
        dialogTimer->start(msec);
    }
}

void QmlDialogManager::forceCloseOnboardingDialog()
{
    if(auto dialog = DialogOpener::findDialog<QmlDialogWrapper<Onboarding>>())
    {
        static_cast<OnboardingQmlDialog*>(dialog->getDialog()->windowHandle())->forceClose();
    }
}
