#pragma once

#include "commit_data.h"
#include "helpers.h"
#include "revision_data.h"
#include "query_generator.h"

#include <yandex/maps/wiki/revision/revisionsgateway.h>

namespace maps::wiki::revision {

class CommitWorker : public boost::noncopyable {
public:
    using NewRevisionData = RevisionsGateway::NewRevisionData;

    CommitWorker(
        Transaction& work,
        const ConstRange<NewRevisionData>& newData,
        BranchType branchType,
        DBID branchId
    );

    CommitData createCommit(UserID createdBy,
        const PreparedCommitAttributes& attributes);

    void updateCommit(DBID commitId);

private:
    bool isBranchTrunk() const
    {
        return branchType_ == BranchType::Trunk;
    }

    void prepare();

    void checkUpdates();
    void insertNewData(DBID commitId);
    void writePreviousUpdates(DBID commitId) const;

    DBID insertAttributes(const std::string& tableName, const Attributes& data);
    DBID insertDescription(const Description& data) const;
    DBID insertGeometry(const Wkb& data) const;

    void setNewRevisionData(const ObjectRevision::Data& data,
        RevisionData& rdata);

    void processCurrentRevision(const ObjectRevision::ID& id,
        const RevisionData& currentData, const ObjectRevision::Data& newData);

private:
    struct RevisionDataWithCommitId {
        const RevisionData data;
        const DBID commitId;
    };

    Transaction& work_;
    const BranchType branchType_;
    const DBID branchId_;
    const ConstRange<NewRevisionData>& newData_;

    std::map<Hstore, DBID> attrsCache_;

    // including objects from current commit
    DBIDSet deletedUpdateObjectIds_;

    std::map<DBID, DBID> updates_; // object_id -> commit_id
    CommitIdToObjectIds updatePreviousRevisionsMap_;
    CommitIdToObjectIds previousRevisionsMap_;

    std::map<DBID, RevisionDataWithCommitId> updatePreviousData_; // object_id -> previous revision data
};

} // namespace maps::wiki::revision
