#include "filter_manager.h"

#include <QMap>
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>

#include "util/libcurl.h"
#include "util/config.h"

class FilterManagerPrivate
{
public:
    FilterManagerPrivate(FilterManager *parent) : q_ptr(parent) {}

    QString platform;

    FilterManager *q_ptr;
    Q_DECLARE_PUBLIC(FilterManager)
};

FilterManager::FilterManager(QObject *parent) :
    QObject(parent), dd_ptr(new FilterManagerPrivate(this))
{

}

FilterManager::~FilterManager()
{

}

void FilterManager::setPlatform(const QString &platform)
{
    Q_D(FilterManager);
    d->platform = platform;
}

QMap<QString, QList<SoftwareFilter>> parseFilters(const QByteArray &data)
{
    QMap<QString, QList<SoftwareFilter>> softwareFilterMap;
    QJsonObject obj = QJsonDocument::fromJson(data).object();
    qDebug() << "load software filter" << obj;
    for (const QString &platform : obj.keys()) {
        auto softwares = obj.value(platform).toObject();
        for (const QString &key : softwares.keys()) {
            auto filter = SoftwareFilter(softwares.value(key).toObject());
            filter.id = key;
            auto filters = softwareFilterMap.take(platform);
            filters.push_back(filter);
            softwareFilterMap[platform] = filters;
        }
    }
    return softwareFilterMap;
}

QList<SoftwareFilter> loadFilters(const QString &filepath, const QString &platform)
{
    QFile softwareFilterFile(filepath);
    if (!softwareFilterFile.open(QIODevice::ReadOnly)) {
        qCritical() << "load software filters failed" << platform << filepath;
        return QList<SoftwareFilter>();
    }
    auto data = softwareFilterFile.readAll();
    qDebug() << "load software filter" << data;
    return parseFilters(data).value(platform);
}

QList<SoftwareFilter> FilterManager::filterList()
{
    Q_D(const FilterManager);
    auto filters = loadFilters(Config::SoftwareFilterPath(), d->platform);
    if (filters.length() <= 0) {
        qInfo() << "load inter software filter";
        filters = loadFilters(Config::InterSoftwareFilterPath(), d->platform);
    }

    return filters;
}

void FilterManager::update()
{
    std::string respone;
    std::string err;
    libcurl_get(Config::softwareFilterURL().toStdString().data(), respone, err);

    auto jsonDoc = QJsonDocument::fromJson(QByteArray::fromStdString(respone));
    auto softwareObj = jsonDoc.object();
    if (!softwareObj.contains("linux")) {
        qCritical() << "fetch software filter failed";
        return;
    }

    // save to config path
    QFile file(Config::SoftwareFilterPath());
    if (!file.open(QIODevice::WriteOnly)) {
        qCritical() << "Open file for write failed" << file.fileName();
        return;
    }

    file.write(QByteArray::fromStdString(respone));
    file.close();

    Q_EMIT filterListUpdated(filterList());
}
