#pragma once

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

#include <string>

namespace maps {
namespace wiki {
namespace diffalert {

class RevSnapshotHolder
{
public:
    RevSnapshotHolder(
            pgpool3::TransactionHandle&& txnHandle,
            revision::Snapshot&& snapshot)
        : txnHandle_(std::move(txnHandle))
        , snapshot_(std::move(snapshot))
    { }

    RevSnapshotHolder(const RevSnapshotHolder&) = delete;
    RevSnapshotHolder& operator=(const RevSnapshotHolder&) = delete;

    RevSnapshotHolder(RevSnapshotHolder&&) = default;
    RevSnapshotHolder& operator=(RevSnapshotHolder&&) = default;

    revision::Snapshot& operator*()
    { return snapshot_; }

    revision::Snapshot* operator->()
    { return std::addressof(snapshot_); }

private:
    pgpool3::TransactionHandle txnHandle_;
    revision::Snapshot snapshot_;
};

class RevSnapshotFactory
{
public:
    RevSnapshotFactory(
        revision::Branch branch,
        revision::SnapshotId snapshotId,
        pgpool3::Pool& pool);

    RevSnapshotHolder get();

private:
    revision::Branch branch_;
    revision::SnapshotId snapshotId_;
    pgpool3::Pool& pool_;
};

class ViewTxnFactory
{
public:
    ViewTxnFactory(
        revision::Branch branch,
        pgpool3::Pool& pool);

    bool isAvailable() const;

    pgpool3::TransactionHandle get();

private:
    revision::Branch branch_;
    std::string schemaName_;
    std::string token_;
    pgpool3::Pool& pool_;
    bool isAvailable_;
};

} // namespace diffalert
} // namespace wiki
} // namespace maps
