#include "json.h"

#include <maps/libs/json/include/builder.h>
#include <maps/libs/json/include/value.h>
#include <map>

namespace md = maps::wiki::mds_dataset;
namespace mj = maps::json;

namespace maps {

namespace json {

void json(md::Timestamp ts, mj::VariantBuilder builder)
{
    builder << md::Timestamp::clock::to_time_t(ts);
}

} // namespace json

namespace wiki {
namespace dataset_explorer {

namespace {

const std::string EXPORT_REGION_PREFIX = "/export_";

const std::map<std::string, std::string> TRANSLATED_REGIONS = {
    { "and_turkey_mpro", "and_tr" },
};

} // namespace

std::string findRegion(const std::string& url)
{
    auto pos1 = url.find(EXPORT_REGION_PREFIX);
    if (pos1 == std::string::npos) {
        return {};
    }

    pos1 += EXPORT_REGION_PREFIX.size();
    auto pos2 = url.find('/', pos1);
    if (pos2 == std::string::npos) {
        return {};
    }

    // /export_and_mpro/ -> and_mpro
    auto region = url.substr(pos1, pos2 - pos1);

    auto it = TRANSLATED_REGIONS.find(region);
    return it != TRANSLATED_REGIONS.end()
        ? it->second
        : region;
}

namespace json {

void json(const ExportDataset& dataset, mj::ObjectBuilder builder)
{
    builder["name"] = dataset.id();
    builder["status"] = toString(dataset.metadata().basic().status());
    builder["tested"] = dataset.metadata().tested() == md::IsTested::Yes;
    builder["timestamp"] = dataset.metadata().basic().created();

    std::string region;
    builder["files"] = [&](mj::ArrayBuilder builder) {
        for (const auto& fileLink: dataset.fileLinks()) {
            builder << [&](mj::ObjectBuilder builder) {
                const auto& url = fileLink.readingUrl();
                builder["name"] = fileLink.name();
                builder["uri"] = url;
                if (region.empty()) {
                    region = findRegion(url);
                }
            };
        }
    };
    if (!region.empty()) {
        builder["region"] = region;
    }
}

} // namespace json

std::string makeJsonDatasetsList(
    const ExportDatasets& datasets,
    uint64_t offset,
    uint32_t limit)
{
    maps::json::Builder builder;

    builder << [&](mj::ObjectBuilder builder) {
        builder["offset"] = offset;
        builder["limit"] = limit;
        builder["datasets"] = [&](mj::ArrayBuilder builder) {
            for (const auto& dataset: datasets) {
                builder << [&](mj::ObjectBuilder builder) {
                    json::json(dataset, builder);
                };
            }
        };
    };
    return builder.str();
}

} // namespace dataset_explorer
} // namespace wiki
} // namespace maps
