#include "importer.h"
#include "exporter.h"
#include "deleter.h"

#include <yandex/maps/wiki/revisionapi/revisionapi.h>

#include <utility>

namespace json = maps::json;
namespace revision = maps::wiki::revision;
namespace filters = revision::filters;

namespace maps::wiki::revisionapi {

class RevisionAPI::Impl
{
public:
    pgpool3::Pool& pool;
    VerboseLevel verboseLevel;
};

RevisionAPI::RevisionAPI(pgpool3::Pool& pool, VerboseLevel verboseLevel)
    : impl_(new Impl{pool, verboseLevel})
{}

RevisionAPI::~RevisionAPI() = default;

std::list<revision::DBID> RevisionAPI::importData(
    const revision::UserID userId,
    const IdMode idMode,
    std::istream& is,
    const size_t batchLoadingSize,
    const size_t idOffset)
{
    std::map<std::string, std::string> jsonIdToError;
    const json::Value jsonData = json::Value::fromStream(is);
    Importer importer(
        impl_->pool, impl_->verboseLevel,
        jsonData[JSON_FIELD_OBJECTS], idMode, idOffset, jsonIdToError);
    return importer.import(
        impl_->pool, userId, json2attributes(jsonData[JSON_FIELD_ATTRIBUTES]), batchLoadingSize);
}

std::list<revision::DBID> RevisionAPI::importData(
    const revision::UserID userId,
    const IdMode idMode,
    std::istream& is,
    std::map<std::string, std::string>& jsonIdToError,
    pgpool3::TransactionHandle& writeTr,
    const size_t batchLoadingSize,
    const size_t idOffset)
{
    const json::Value jsonData = json::Value::fromStream(is);
    Importer importer(
        impl_->pool, impl_->verboseLevel,
        jsonData[JSON_FIELD_OBJECTS], idMode, idOffset, jsonIdToError);
    return importer.import(
        writeTr, userId, json2attributes(jsonData[JSON_FIELD_ATTRIBUTES]), batchLoadingSize);
}

std::list<revision::DBID> RevisionAPI::importData(
    const revision::UserID userId,
    const BaseIdMapper& idMapper,
    std::istream& is,
    std::map<std::string, std::string>& jsonIdToError,
    pgpool3::TransactionHandle& writeTr,
    const size_t batchLoadingSize)
{
    const json::Value jsonData = json::Value::fromStream(is);
    Importer importer(
        impl_->verboseLevel,
        jsonData[JSON_FIELD_OBJECTS], idMapper, jsonIdToError);
    return importer.import(
        writeTr, userId, json2attributes(jsonData[JSON_FIELD_ATTRIBUTES]), batchLoadingSize);
}

void RevisionAPI::exportData(
    const ExportParams& params,
    GetStreamForChunkFunc getStreamForChunkFunc,
    const FilterPtr& filter)
{
    Exporter exporter(impl_->pool);
    exporter.exportToJsonByFilter(params, std::move(getStreamForChunkFunc), filter);
}

void RevisionAPI::exportData(
    const ExportParams& params,
    GetStreamForChunkFunc getStreamForChunkFunc,
    const std::vector<revision::DBID>& objectIds)
{
    Exporter exporter(impl_->pool);
    exporter.exportToJsonByObjectIds(params, std::move(getStreamForChunkFunc), objectIds);
}

std::list<revision::DBID>
RevisionAPI::deleteData(
    const revision::UserID userId,
    const std::vector<revision::DBID>& objectIds,
    const size_t commitBatchSize)
{
    return deleteObjects(impl_->pool, revision::TRUNK_BRANCH_ID, impl_->verboseLevel, objectIds, userId, commitBatchSize);
}

std::list<revision::DBID>
RevisionAPI::deleteDataFromBranch(
    const revision::DBID branchId,
    const revision::UserID userId,
    const std::vector<revision::DBID>& objectIds,
    const size_t commitBatchSize)
{
    return deleteObjects(impl_->pool, branchId, impl_->verboseLevel, objectIds, userId, commitBatchSize);
}

} // namespace maps::wiki::revisionapi
