#include "AccountStatusController.h"

#include "DialogOpener.h"
#include "GuestContent.h"
#include "LoginController.h"
#include "MegaApplication.h"
#include "MessageDialogOpener.h"
#include "VerifyLockMessage.h"

#include <QDebug>

AccountStatusController::AccountStatusController(QObject* parent):
    QObject(parent),
    mMegaApi(MegaSyncApp->getMegaApi()),
    mDelegateListener(new mega::QTMegaListener(MegaSyncApp->getMegaApi(), this)),
    mPreferences(Preferences::instance()),
    mQueringWhyAmIBlocked(false),
    mBlockedState(mega::MegaApi::ACCOUNT_NOT_BLOCKED),
    mBlockedStateSet(false)
{
    mMegaApi->addListener(mDelegateListener);
}

void AccountStatusController::onEvent(mega::MegaApi*, mega::MegaEvent* event)
{
    if (event->getType() == mega::MegaEvent::EVENT_ACCOUNT_BLOCKED)
    {
        switch (event->getNumber())
        {
            case mega::MegaApi::ACCOUNT_BLOCKED_VERIFICATION_EMAIL:
            {
                mBlockedStateSet = true;
                int blockState = static_cast<int>(event->getNumber());
                if(mBlockedState == blockState)
                {
                    return;
                }

                mBlockedState = blockState;
                DialogOpener::closeAllDialogs();
                showVerifyAccountInfo();

                if (Preferences::instance()->logged())
                {
                    Preferences::instance()->setBlockedState(blockState);
                }

                emit blockedStateChanged(static_cast<int>(event->getNumber()));
                break;
            }
            case mega::MegaApi::ACCOUNT_BLOCKED_SUBUSER_DISABLED:
            {
                DialogOpener::closeAllDialogs();
                MessageDialogInfo msgInfo;
                msgInfo.descriptionText =
                    tr("Your account has been disabled by your administrator. Please contact your "
                       "business account administrator for further details.");
                MessageDialogOpener::warning(msgInfo);
                break;
            }
            default:
            {
                DialogOpener::closeAllDialogs();
                MessageDialogInfo msgInfo;
                msgInfo.descriptionText =
                    QCoreApplication::translate("MegaError", event->getText());
                MessageDialogOpener::critical(msgInfo);
                break;
            }
        }
    }
}

void AccountStatusController::onRequestFinish(mega::MegaApi *api, mega::MegaRequest *request, mega::MegaError *e)
{
    Q_UNUSED(api)
    if(request->getType() == mega::MegaRequest::TYPE_WHY_AM_I_BLOCKED)
    {
        if (e->getErrorCode() == mega::MegaError::API_OK
            && request->getNumber() == mega::MegaApi::ACCOUNT_NOT_BLOCKED)
        {
            mBlockedStateSet = true;
            int blockState = mega::MegaApi::ACCOUNT_NOT_BLOCKED;
            if(mBlockedState == blockState)
            {
                return;
            }
            mBlockedState = blockState;
            if (Preferences::instance()->logged())
            {
                Preferences::instance()->setBlockedState(blockState);
            }
            MegaSyncApp->requestUserData(); // querying some user attributes might have been rejected: we query them again

            mega::MegaApi::log(mega::MegaApi::LOG_LEVEL_DEBUG, QString::fromUtf8("no longer blocked").toUtf8().constData());

            //in any case we reflect the change in the InfoDialog
            emit blockedStateChanged(blockState);

            if(auto lockDialog = DialogOpener::findDialog<VerifyLockMessage>())
            {
                lockDialog->close();
            }
            if(auto dialog = DialogOpener::findDialog<QmlDialogWrapper<GuestContent>>())
            {
                dialog->close();
            }
            if (auto loginController = MegaSyncApp->getLoginController())
            {
                loginController->processOnboardingClosed();
            }
            MegaSyncApp->showInfoDialog();
        }

        MegaSyncApp->updateTrayIconMenu();
        mQueringWhyAmIBlocked = false;
    }
}

void AccountStatusController::whyAmIBlocked(bool force)
{
    if((!mQueringWhyAmIBlocked && isAccountBlocked()) || force)
    {
        mQueringWhyAmIBlocked = true;
        mMegaApi->whyAmIBlocked();
    }
}

bool AccountStatusController::isAccountBlocked() const
{
    if(mMegaApi->isLoggedIn())
    {
        return (mBlockedState != mega::MegaApi::ACCOUNT_NOT_BLOCKED);
    }
    return false;
}

int AccountStatusController::getBlockedState() const
{
    return mBlockedState;
}

void AccountStatusController::loggedIn()
{
    auto cachedBlockedState = mPreferences->getBlockedState();
    if (mBlockedStateSet && cachedBlockedState != mBlockedState) // blockstate received and needs to be updated in cache
    {
        mega::MegaApi::log(mega::MegaApi::LOG_LEVEL_DEBUG, QString::fromUtf8("cached blocked states %1 differs from applied blockedStatus %2. Overriding cache")
                                                   .arg(cachedBlockedState).arg(mBlockedState).toUtf8().constData());
        mPreferences->setBlockedState(mBlockedState);
    }
    else if (!mBlockedStateSet && cachedBlockedState != -2 && cachedBlockedState) //block state not received in this execution, and cached says we were blocked last time
    {
        mega::MegaApi::log(mega::MegaApi::LOG_LEVEL_DEBUG, QString::fromUtf8("cached blocked states %1 reports blocked, and no block state has been received before, lets query the block status")
                                                   .arg(cachedBlockedState).toUtf8().constData());

        whyAmIBlocked(true);// lets query again, to trigger transition and restoreSyncs
    }
}

void AccountStatusController::reset()
{
    mBlockedState = mega::MegaApi::ACCOUNT_NOT_BLOCKED;
    mQueringWhyAmIBlocked = false;
    mBlockedStateSet = false;
}

void AccountStatusController::showVerifyAccountInfo()
{
    QPointer<VerifyLockMessage> verifyEmail = new VerifyLockMessage();
    connect(verifyEmail.data(), SIGNAL(logout()), MegaSyncApp, SLOT(unlink()));

    DialogOpener::showDialog(verifyEmail);
}

