#pragma once

#include <yandex/maps/wiki/validator/common/relation.h>
#include <yandex/maps/wiki/validator/common.h>

#include <yandex/maps/wiki/revision/common.h>
#include <yandex/maps/wiki/revision/branch.h>
#include <yandex/maps/wiki/revision/objectrevision.h>
#include <yandex/maps/wiki/revision/filters.h>
#include <yandex/maps/wiki/revision/snapshot.h>
#include <maps/libs/pgpool/include/pgpool3.h>

#include <list>
#include <set>
#include <unordered_map>
#include <vector>

namespace maps::wiki::validator {

typedef std::unordered_map<TId, revision::DBID> ObjectIdToCommitId;
typedef std::list<revision::ObjectRevision> Revisions;
typedef std::unordered_map<TId, std::vector<Relation>> RelationsMap;
typedef std::unordered_map<TCategoryId, ObjectIdSet> CategoryIdToObjectIds;

enum class RelationType
{
    Master,
    Slave
};

class DBGateway
{
public:
    DBGateway(
            pgpool3::Pool& pgPool,
            revision::DBID branchId,
            revision::DBID commitId);

    const revision::Branch& branch() const
    { return branch_; }

    revision::DBID commitId() const
    { return commitId_; }

    size_t maxConnections() const;

    // returns txn with db state containing commit commitId_
    pgpool3::TransactionHandle getTransaction() const;

    RevisionIds revisionIdsByFilter(
            const revision::filters::FilterExpr& filter,
            pqxx::transaction_base& txn) const;

    RevisionIds revisionIdsByObjectIds(
            const revision::ConstRange<TId>& ids,
            pqxx::transaction_base& txn) const;

    RevisionIds revisionIdsByObjectIds(
            const revision::ConstRange<TId>& ids,
            const revision::filters::FilterExpr& filter,
            pqxx::transaction_base& txn) const;

    Revisions revisionsByRevisionIds(
            const RevisionIds& ids,
            bool hasGeom,
            pqxx::transaction_base& txn) const;

    RelationsMap mastersOf(
            const std::vector<TId>& slaves,
            pqxx::transaction_base& txn) const;

    RelationsMap slavesOf(
            const std::vector<TId>& masters,
            pqxx::transaction_base& txn) const;

    ObjectIdSet loadObjectIdsByRelatedIds(
        pqxx::transaction_base& txn,
        const TCategoryId& categoryId,
        const std::vector<TId>& relatedIds,
        RelationType relationType,
        const std::set<std::string>& roleIds) const;

    revision::Snapshot snapshot(pqxx::transaction_base& txn) const;

private:
    pgpool3::Pool& pgPool_;
    revision::Branch branch_;
    revision::DBID commitId_;
};

} // namespace maps::wiki::validator
