#pragma once

#include <yandex/maps/wiki/filters/common.h>
#include <yandex/maps/wiki/groupedit/actions/move.h>
#include <yandex/maps/wiki/groupedit/session.h>
#include <yandex/maps/wiki/revision/common.h>

#include <maps/libs/common/include/profiletimer.h>
#include <maps/libs/json/include/value.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/libs/pgpool/include/pgpool3.h>

#include <string>
#include <iosfwd>

namespace maps::wiki::groupedit {

using StringSet = std::set<std::string>;

enum class Action
{
    Move,
    UpdateAttrs,
    SetState
};

template<typename Handler>
std::vector<TCommitId> perform(
        Action action,
        pgpool3::TransactionHandle& txn,
        Handler handler)
{
    INFO() << "performing " << action << " operation";
    ProfileTimer editTimer;

    std::vector<TCommitId> commitIds;

    try {
        commitIds = handler();
    } catch (...) {
        ERROR() << "operation " << action << " failed";
        txn->abort();
        throw;
    }

    INFO() << "wrote " << commitIds.size() << " commits"
           << ", operation " << action << " completed successfully in "
           << editTimer.getElapsedTime() << " s.";

    return commitIds;
}

revision::filters::ProxyFilterExpr loadFilter(
        pgpool3::TransactionHandle& txn,
        filters::TExpressionId filterExprId);

std::vector<TCommitId> move(
        pgpool3::TransactionHandle& txn,
        pgpool3::TransactionHandle& viewTxn,
        revision::DBID branchId,
        TUserId author,
        const std::optional<filters::TExpressionId>& filterExprId,
        const std::string& aoiWkb,
        double dx, double dy,
        const StringSet& categoryIds,
        groupedit::actions::PolygonMode polygonMode);

std::vector<TCommitId> updateAttrs(
        pgpool3::TransactionHandle& txn,
        pgpool3::TransactionHandle& viewTxn,
        revision::DBID branchId,
        groupedit::TUserId author,
        filters::TExpressionId filterExprId,
        const std::optional<std::string>& aoiWkb,
        const json::Value& attrs);

std::vector<TCommitId> deleteObjects(
        pgpool3::TransactionHandle& txn,
        pgpool3::TransactionHandle& viewTxn,
        revision::DBID branchId,
        groupedit::TUserId author,
        filters::TExpressionId filterExprId,
        const std::optional<std::string>& aoiWkb);

Action actionFromString(const std::string& value);
std::string actionToString(Action action);

std::ostream& operator<<(std::ostream& os, Action action);
std::istream& operator>>(std::istream& is, Action& action);

} // namespace maps::wiki::groupedit
