#include "db_pools.h"
#include <yandex/maps/wiki/common/compound_token.h>

#include <pqxx/pqxx>
#include <memory>
#include <string>

namespace maps::wiki::socialsrv {

namespace pgp = pgpool3;

///
/// DbPools
///

DbPools::DbPools(pgpool3::Pool& core, pgpool3::Pool& social)
    : core_(core)
    , social_(social)
{ }

pgp::Pool& DbPools::core()
{
    return core_;
}

WriteContext DbPools::writeContext()
{
    return { core().masterWriteableTransaction(), socialTxn() };
}

pgp::TransactionHandle DbPools::coreReadTxn(const std::string& token)
{
    auto subtoken = common::CompoundToken::subToken(
        token, common::TOKEN_DB_ALIAS_CORE);
    return core().slaveTransaction(subtoken);
}

pgp::Pool& DbPools::social()
{
    return social_;
}

pgp::TransactionHandle DbPools::socialTxn()
{
    return social().masterWriteableTransaction();
}

pgp::TransactionHandle DbPools::socialReadTxn(const std::string& token)
{
    auto subtoken = common::CompoundToken::subToken(
        token, common::TOKEN_DB_ALIAS_SOCIAL);
    return social().slaveTransaction(subtoken);
}

pgp::TransactionHandle DbPools::socialRepeatableReadTxn()
{
    auto conn = social().getSlaveConnection();
    return pgpool3::makeRepeatableReadTransaction(std::move(conn));
}

WriteContext::WriteContext(
        pgpool3::TransactionHandle&& coreTxn,
        pgpool3::TransactionHandle&& socialTxn)
    : coreTxn_(std::move(coreTxn))
    , socialTxn_(std::move(socialTxn))
{}

DbToken WriteContext::commit()
{
    auto tokenCore = pgpool3::generateToken(*coreTxn_);
    auto tokenSocial = pgpool3::generateToken(*socialTxn_);

    coreTxn_->commit();
    socialTxn_->commit();

    coreTxn_.releaseConnection();
    socialTxn_.releaseConnection();


    // <tsCore>:<idCore>:core.<tsSocial>:<idSocial>:social

    common::CompoundToken compoundToken;
    compoundToken.append(common::TOKEN_DB_ALIAS_CORE, tokenCore);
    compoundToken.append(common::TOKEN_DB_ALIAS_SOCIAL, tokenSocial);

    return compoundToken.str();
}


///
/// DbPoolsWithViewTrunk
///

DbPoolsWithViewTrunk::DbPoolsWithViewTrunk(
    pgpool3::Pool& core,
    pgpool3::Pool& social,
    pgpool3::Pool& viewTrunk)
    : DbPools(core, social)
    , viewTrunk_(viewTrunk)
{}

pgp::Pool& DbPoolsWithViewTrunk::viewTrunk()
{
    return viewTrunk_;
}

pgp::TransactionHandle DbPoolsWithViewTrunk::viewTrunkTxn()
{
    return viewTrunk().slaveTransaction();
}

} // namespace maps::wiki::socialsrv
