#include "ChooseFolder.h"

#include "DialogOpener.h"
#include "FilePickerNodeSelectorSpecializations.h"
#include "megaapi.h"
#include "MegaApplication.h"
#include "Platform.h"
#include "Syncs.h"

#include <QDir>

ChooseLocalFolder::ChooseLocalFolder(QObject *parent)
    : QObject(parent)
    , mTitle(tr("Select local folder"))
{
}

void ChooseLocalFolder::openFolderSelector(const QString& folderPath, bool folderUp)
{
    auto openFromFolder = QDir::toNativeSeparators(Utilities::getDefaultBasePath());

    if (!folderPath.isEmpty())
    {
        openFromFolder = QDir::toNativeSeparators(folderPath);
        QDir openFromFolderDir(openFromFolder);

        if (folderUp)
        {
            if (openFromFolderDir.cdUp())
            {
                openFromFolder = openFromFolderDir.path();
            }
            else
            {
                openFromFolder = QDir::toNativeSeparators(Utilities::getDefaultBasePath());
            }
        }
    }

    SelectorInfo info;
    info.title = mTitle;
    info.defaultDir = openFromFolder;
    info.canCreateDirectories = true;

    QPointer<const QObject> context = this;
    info.func = [this, context, openFromFolder](QStringList selection)
    {
        if(context && !selection.isEmpty())
        {
            sendFolderChosenSignal(Platform::getInstance()->preparePathForSync(selection.first()),
                                   QString());
        }
    };

    Platform::getInstance()->folderSelector(info);
}

void ChooseLocalFolder::openRelativeFolderSelector(const QString& folderPath)
{
    auto openFromFolder = QDir::toNativeSeparators(Utilities::getDefaultBasePath());
    if (!folderPath.isEmpty())
    {
        openFromFolder = QDir::toNativeSeparators(folderPath);
    }

    SelectorInfo info;
    info.title = mTitle;
    info.multiSelection = false;
    info.defaultDir = openFromFolder;

    QPointer<const QObject> context = this;
    info.func = [this, context, openFromFolder](QStringList selection)
    {
        if(context && !selection.isEmpty())
        {
            sendFolderChosenSignal(Platform::getInstance()->preparePathForSync(selection.first()),
                                   openFromFolder);
        }
    };

    Platform::getInstance()->folderSelector(info);
}

void ChooseLocalFolder::sendFolderChosenSignal(const QString& folder, const QString& openFromFolder)
{
    if (!folder.isNull() && !folder.isEmpty())
    {
        if (openFromFolder.isEmpty())
        {
            emit folderChosen(folder);
        }
        else
        {
            emit folderChosen(QDir(openFromFolder).relativeFilePath(folder));
        }
    }
}

bool ChooseLocalFolder::createFolder(const QString& folderPath)
{
    if (folderPath.isEmpty())
    {
        return false;
    }

    auto folder = QDir::toNativeSeparators(folderPath);

    QDir defaultFolder(folder);
    if (!defaultFolder.exists() && (folder != getDefaultFolder(Syncs::getDefaultMegaFolder()) ||
                                    !defaultFolder.mkpath(QString::fromUtf8("."))))
    {
        mega::MegaApi::log(mega::MegaApi::LOG_LEVEL_WARNING,
                           QString::fromUtf8("ChooseFolder: %1 cannot be created.").arg(folderPath).toUtf8().constData());

        return false;
    }

    return true;
}

QString ChooseLocalFolder::getDefaultFolder(const QString& folderName)
{
    auto folder = Utilities::getDefaultBasePath();

    if(!folderName.isEmpty())
    {
        //in case there is a folder with the same name MEGA but with different case: Mega
        QStringList realName = QDir(folder).entryList(QStringList() << folderName);
        folder.append(QString::fromLatin1("/"));
        if(!realName.isEmpty())
        {
            folder.append(realName.first());
        }
        else
        {
            folder.append(folderName);
        }
    }
    return QDir::toNativeSeparators(folder);
}

QString ChooseRemoteFolder::DEFAULT_FOLDER_PATH = QString::fromLatin1("/");

ChooseRemoteFolder::ChooseRemoteFolder(QObject *parent)
    : QObject(parent)
    , mFolderHandle(mega::INVALID_HANDLE)
    , mFolderName(ChooseRemoteFolder::DEFAULT_FOLDER_PATH)
{
}

void ChooseRemoteFolder::openFolderSelector()
{
    QPointer<SyncNodeSelector> nodeSelector = new SyncNodeSelector();
    nodeSelector->init();

    if (mFolderHandle != mega::INVALID_HANDLE)
    {
        const std::shared_ptr<mega::MegaNode> node(
            MegaSyncApp->getMegaApi()->getNodeByHandle(mFolderHandle));

        // Make sure the node still exists and is not in the Rubbish before navigating
        if (node && !MegaSyncApp->getMegaApi()->isInRubbish(node.get()))
        {
            nodeSelector->setSelectedNodeHandle(node);
        }
        else
        {
            reset();
        }
    }

    QPointer<const QObject> context = this;
    DialogOpener::showDialog<SyncNodeSelector>(nodeSelector, [nodeSelector, this, context]()
    {
        if (context && nodeSelector->result() == QDialog::Accepted)
        {
            mFolderHandle = nodeSelector->getSelectedNodeHandle();
            auto node = MegaSyncApp->getMegaApi()->getNodeByHandle(mFolderHandle);
            if(node)
            {
                mFolderName = QString::fromUtf8(MegaSyncApp->getMegaApi()->getNodePath(node));
                if(!mFolderName.isNull() && !mFolderName.isEmpty())
                {
                    emit folderChosen(mFolderName);
                    emit folderNameChanged();
                }
            }
        }
    });
}

mega::MegaHandle ChooseRemoteFolder::getHandle()
{
    return mFolderHandle;
}

void ChooseRemoteFolder::reset()
{
    mFolderHandle = mega::INVALID_HANDLE;
    mFolderName = ChooseRemoteFolder::DEFAULT_FOLDER_PATH;
    emit folderNameChanged();
}

QString ChooseRemoteFolder::getFolderName()
{
    return mFolderName;
}
