// This file Copyright © Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.

#include <QDir>
#include <QFile>
#include <QFileInfo>

#include <libtransmission/transmission.h>

#include <libtransmission/error.h>
#include <libtransmission/torrent-metainfo.h>
#include <libtransmission/utils.h>
#include <libtransmission/web-utils.h>

#include "AddData.h"
#include "Utils.h"

namespace
{

QString getNameFromMetainfo(QByteArray const& benc)
{
    if (auto metainfo = tr_torrent_metainfo{}; metainfo.parse_benc({ benc.constData(), static_cast<size_t>(benc.size()) }))
    {
        return QString::fromStdString(metainfo.name());
    }

    return {};
}

QString getNameFromMagnet(QString const& magnet)
{
    auto tmp = tr_magnet_metainfo{};

    if (!tmp.parseMagnet(magnet.toStdString()))
    {
        return magnet;
    }

    if (!std::empty(tmp.name()))
    {
        return QString::fromStdString(tmp.name());
    }

    auto const& hashstr = tmp.info_hash_string();
    return QString::fromUtf8(std::data(hashstr), std::size(hashstr));
}

} // namespace

int AddData::set(QString const& key)
{
    if (auto const key_std = key.toStdString(); tr_urlIsValid(key_std))
    {
        this->url = key;
        this->type = URL;
    }
    else if (tr_magnet_metainfo{}.parseMagnet(key_std))
    {
        this->magnet = key;
        this->type = MAGNET;
    }
    else if (auto const kurl = QUrl::fromUserInput(key, QDir::currentPath()); kurl.isValid() && kurl.isLocalFile())
    {
        if (auto file = QFile{ kurl.toLocalFile() }; file.exists())
        {
            this->filename = file.fileName();
            this->type = FILENAME;

            file.open(QIODevice::ReadOnly);
            this->metainfo = file.readAll();
            file.close();
        }
    }
    else if (auto const raw = QByteArray::fromBase64(key.toUtf8()); !raw.isEmpty())
    {
        this->metainfo.append(raw);
        this->type = METAINFO;
    }
    else
    {
        this->type = NONE;
    }

    return this->type;
}

QByteArray AddData::toBase64() const
{
    return metainfo.toBase64();
}

QString AddData::readableName() const
{
    switch (type)
    {
    case FILENAME:
        return filename;

    case MAGNET:
        return getNameFromMagnet(magnet);

    case URL:
        return url.toString();

    case METAINFO:
        return getNameFromMetainfo(metainfo);

    default: // NONE
        return {};
    }
}

QString AddData::readableShortName() const
{
    switch (type)
    {
    case FILENAME:
        return QFileInfo{ filename }.baseName();

    case URL:
        return url.path().split(QLatin1Char('/')).last();

    default:
        return readableName();
    }
}

void AddData::disposeSourceFile() const
{
    auto file = QFile{ filename };
    if (!disposal_ || !file.exists())
    {
        return;
    }

    switch (*disposal_)
    {
    case FilenameDisposal::Delete:
        file.setPermissions(QFile::ReadOwner | QFile::WriteOwner);
        file.remove();
        break;

    case FilenameDisposal::Rename:
        file.rename(QStringLiteral("%1.added").arg(filename));
        break;

    default:
        // no action
        break;
    }
}
