#pragma once

#include "jsonhelper.h"

#include <maps/libs/pgpool/include/pgpool3.h>
#include <yandex/maps/wiki/revision/objectrevision.h>
#include <yandex/maps/wiki/revision/revisionid.h>
#include <yandex/maps/wiki/revision/revisionsgateway.h>
#include <yandex/maps/wiki/revisionapi/revisionapi.h>

#include <list>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <vector>

namespace json = maps::json;
namespace revision = maps::wiki::revision;
namespace pgpool = maps::pgpool3;

namespace maps::wiki::revisionapi {

class IdMapper;

class Importer {
public:
    Importer(
        pgpool::Pool& pool,
        VerboseLevel verboseLevel,
        const json::Value& objects,
        IdMode idMode,
        size_t idOffset,
        std::map<std::string, std::string>& jsonIdToError);

    Importer(
        VerboseLevel verboseLevel,
        const json::Value& objects,
        const BaseIdMapper& idMapper,
        std::map<std::string, std::string>& jsonIdToError);

    std::list<revision::DBID> import(
        pgpool::Pool& pool,
        revision::UserID userId,
        const revision::Attributes& attributes,
        size_t batchLoadingSize);

    std::list<revision::DBID> import(
        pgpool3::TransactionHandle& writeTr,
        revision::UserID userId,
        const revision::Attributes& attributes,
        size_t batchLoadingSize);

private:
    using PreparedData = std::vector<revision::RevisionsGateway::NewRevisionData>;

    void addObjects(
        const BaseIdMapper& idMapper,
        VerboseLevel verboseLevel,
        const json::Value& objects,
        std::map<std::string, std::string>& jsonIdToError);

    void addObject(
        const BaseIdMapper& idMapper,
        const std::string& jsonId,
        const json::Value& object);

    void addRelations(
        const BaseIdMapper& idMapper,
        revision::DBID objectId,
        const json::Value& relations);

    static std::list<revision::DBID> import(
        pqxx::transaction_base& txn,
        revision::UserID userId,
        const revision::Attributes& attributes,
        size_t batchLoadingSize,
        PreparedData& preparedData);

    PreparedData objects_;
    PreparedData relations_;
};

} // namespace maps::wiki::revisionapi
