#include "DuplicatedNodeItem.h"

#include "MegaApplication.h"
#include "TextDecorator.h"
#include "ThemeManager.h"
#include "TokenParserWidgetManager.h"
#include "ui_DuplicatedNodeItem.h"
#include "Utilities.h"

/*
 * BASE CLASS
*/
DuplicatedNodeItem::DuplicatedNodeItem(QWidget* parent):
    QWidget(parent),
    mType(NodeItemType::DONT_UPLOAD),
    mInfo(nullptr),
    mNodeSize(-1),
    ui(new Ui::DuplicatedNodeItem)
{
    ui->setupUi(this);
    ui->lLearnMore->hide();

    // Centre the name (and size/date) block vertically within the card cell. The labels are
    // sized to their text and QTextBrowser can't vertically centre its own text, so equal
    // stretches above and below the content do the centring. This keeps a single-line item
    // such as the rename option aligned with the icon instead of stuck at the top.
    ui->verticalLayout_4->insertStretch(0);
    ui->verticalLayout_4->addStretch();

    TokenParserWidgetManager::instance()->applyCurrentTheme(this);
}

DuplicatedNodeItem::~DuplicatedNodeItem()
{
    delete ui;
}

void DuplicatedNodeItem::setInfo(std::shared_ptr<DuplicatedNodeInfo>info, NodeItemType type)
{
    mInfo = info;
    mType = type;

    fillUi();
}

void DuplicatedNodeItem::setDescription(const QString &description)
{
    ui->lDescription->setText(description);
}

void DuplicatedNodeItem::showLearnMore(const QString& url)
{
    mLearnMoreUrl = url;
    rebuildLearnMore();
    ui->lLearnMore->show();

    connect(ThemeManager::instance(),
            &ThemeManager::themeChanged,
            this,
            &DuplicatedNodeItem::rebuildLearnMore,
            Qt::UniqueConnection);
}

void DuplicatedNodeItem::rebuildLearnMore()
{
    if (mLearnMoreUrl.isEmpty())
    {
        return;
    }

    QString text = QStringLiteral("[A]%1[/A]").arg(tr("Learn more"));
    Text::Link(mLearnMoreUrl).process(text);
    ui->lLearnMore->setText(text);
}

void DuplicatedNodeItem::fillUi()
{
    switch(mType)
    {
        case NodeItemType::FOLDER_UPLOAD_AND_MERGE:
        {
            setActionAndTitle(tr("Merge"));
            break;
        }
        case NodeItemType::UPLOAD_AND_RENAME:
        {
            setActionAndTitle(tr("Rename"));
            ui->wNodeInfo->hide();
            break;
        }
        case NodeItemType::FILE_UPLOAD_AND_REPLACE:
        {
            setActionAndTitle(tr("Replace"));
            break;
        }
        case NodeItemType::FILE_UPLOAD_AND_UPDATE:
        {
            setActionAndTitle(tr("Update"));
            break;
        }
        case NodeItemType::DONT_UPLOAD:
        default:
        {
            ui->bAction->setText(tr("Skip"));
            ui->lTitle->setText(mInfo->sourceItemIsFile() ? tr("Skip this file") :
                                                            tr("Skip this folder"));
            break;
        }
    }

    auto nodeName(getNodeName());
    ui->lNodeName->setMaximumLines(4);
    ui->lNodeName->setText(nodeName);

    QIcon icon =
        isFile() ?
            QIcon(Utilities::getExtensionPixmapName(nodeName, Utilities::AttributeType::MEDIUM)) :
            QIcon(Utilities::getFolderPixmapName(Utilities::FolderType::TYPE_NORMAL,
                                                 Utilities::AttributeType::MEDIUM));

    ui->lIcon->setIcon(icon);
}

void DuplicatedNodeItem::setModifiedTime(const QDateTime& dateTime)
{
    auto timeString = dateTime.isValid() ? MegaSyncApp->getFormattedDateByCurrentLanguage(dateTime, QLocale::FormatType::ShortFormat) : tr("loading time…");

#ifdef Q_OS_LINUX
    if(QDateTime::fromSecsSinceEpoch(0) == dateTime)
    {
        timeString = QString::fromLatin1("");
        ui->point->hide();
    }
#endif

    ui->lDate->setText(timeString);
}

void DuplicatedNodeItem::setSize(qint64 size)
{
    QString nodeSizeText(size < 0 ? tr("loading size…") : Utilities::getSizeString(size));
    ui->lSize->setText(nodeSizeText);
}

bool DuplicatedNodeItem::isValid() const
{
    return mInfo != nullptr;
}

void DuplicatedNodeItem::setActionAndTitle(const QString &text)
{
    ui->bAction->setText(text);
    ui->lTitle->setText(text);
}

void DuplicatedNodeItem::on_bAction_clicked()
{
    emit actionClicked();
}

/*
 * REMOTE IMPLEMENTATION CLASS
 * USE TO SHOW THE REMOTE NODE INFO
*/
DuplicatedRemoteItem::DuplicatedRemoteItem(QWidget *parent)
    : DuplicatedNodeItem(parent)
{
}

DuplicatedRemoteItem::~DuplicatedRemoteItem()
{
    if (mFolderAttributes)
    {
        mFolderAttributes->cancel();
    }
}

void DuplicatedRemoteItem::setInfo(std::shared_ptr<DuplicatedNodeInfo> info, NodeItemType type)
{
    if(!mFolderAttributes)
    {
        mFolderAttributes = new RemoteFileFolderAttributes(info->getConflictNode()->getHandle(), this, false);
        mFolderAttributes->requestModifiedTime(this,[this](const QDateTime& time)
        {
            setModifiedTime(time);
        });
        mFolderAttributes->requestSize(this,[this](qint64 size)
        {
            setSize(size);
        });
    }

    DuplicatedNodeItem::setInfo(info, type);
}

void DuplicatedRemoteItem::setInfoSpecifyingHandle(
    std::shared_ptr<DuplicatedNodeInfo> info, mega::MegaHandle handle, NodeItemType type)
{
    if(!mFolderAttributes)
    {
        mFolderAttributes = new RemoteFileFolderAttributes(handle, this, false);
        mFolderAttributes->requestModifiedTime(this,[this](const QDateTime& time)
            {
                setModifiedTime(time);
            });
        mFolderAttributes->requestSize(this,[this](qint64 size)
            {
                setSize(size);
            });
    }

    DuplicatedNodeItem::setInfo(info, type);
}

std::shared_ptr<mega::MegaNode> DuplicatedRemoteItem::getNode()
{
    return mInfo->getConflictNode();
}

QString DuplicatedRemoteItem::getNodeName()
{
    return mInfo->getName();
}

bool DuplicatedRemoteItem::isFile() const
{
    return mInfo->conflictNodeIsFile();
}

/*
 * LOCAL IMPLEMENTATION CLASS
 * USE TO SHOW THE LOCAL NODE INFO
*/
DuplicatedLocalItem::DuplicatedLocalItem(QWidget *parent)
    : DuplicatedNodeItem(parent)
{
}

DuplicatedLocalItem::~DuplicatedLocalItem()
{
    if (mFolderAttributes)
    {
        mFolderAttributes->cancel();
    }
}

void DuplicatedLocalItem::setInfo(std::shared_ptr<DuplicatedNodeInfo> info, NodeItemType type)
{
    if(!mFolderAttributes)
    {
        mFolderAttributes = new LocalFileFolderAttributes(info->getSourceItemPath(), this);
        mFolderAttributes->requestModifiedTime(this,[this](const QDateTime& time)
        {
            setModifiedTime(time);
        });
        mFolderAttributes->requestSize(this,[this](qint64 size)
        {
            setSize(size);
        });
    }

    DuplicatedNodeItem::setInfo(info, type);
}

QString DuplicatedLocalItem::getNodeName()
{
    if(isFile())
    {
        QFileInfo localNode(mInfo->getSourceItemPath());
        return localNode.fileName();
    }
    else
    {
        QDir dir(mInfo->getSourceItemPath());
        return dir.dirName();
    }
}

bool DuplicatedLocalItem::isFile() const
{
    return mInfo->sourceItemIsFile();
}

QString DuplicatedLocalItem::getFullFileName(const QString &path, const QString &fileName)
{
    return QString(QString::fromUtf8("%1/%2")).arg(path, fileName);
}

/*
 * RENAME IMPLEMENTATION FOR LOCAL NODES
 * USE TO SHOW THE RENAME OPTION
*/
DuplicatedRenameItem::DuplicatedRenameItem(QWidget *parent)
    :DuplicatedLocalItem(parent)
{
}

void DuplicatedRenameItem::setRenameInfo(std::shared_ptr<DuplicatedNodeInfo> conflict)
{
    DuplicatedLocalItem::setInfo(conflict, NodeItemType::UPLOAD_AND_RENAME);
}

QString DuplicatedRenameItem::getNodeName()
{
    return mInfo->getDisplayNewName();
}
