#pragma once

#include "bbox_context.h"
#include "bbox_writer.h"

#include <maps/wikimap/mapspro/services/editor/src/common.h>
#include <maps/wikimap/mapspro/services/editor/src/branch_helpers.h>
#include <maps/wikimap/mapspro/services/editor/src/objects_cache.h>
#include <maps/wikimap/mapspro/services/editor/src/objects/object.h>

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

namespace maps {
namespace wiki {

struct ComplexObjectInfo
{
    std::string categoryId;
    size_t cacheGeomPartsThreshold;
};

class ComplexObjectBBoxComputer
{
public:
    ComplexObjectBBoxComputer(
        TOIds topLevelComplexObjectIds,
        std::string topLevelCategoryId,
        BBoxContext context);

    void preload();
    void run();

    std::map<TOid, Geom> finalGeometries();

private:
    void addComplexObjectInfo(TOid objectId, const Category& category);

    TOIds loadComplexObjectsInitialState(const revision::Snapshot& snapshot, const TOIds& complexObjectIds);
    void loadGeomPartsInitialState(const revision::Snapshot& snapshot);
    void loadInitialState(const revision::Snapshot& snaphot);
    void computeComplexObjectsInitialGeometry();

    TOIds loadHistorySlaveComplexObjectIds(const revision::HistoricalSnapshot& historicalSnapshot);
    void loadHistoryGeomPartsIds(const revision::HistoricalSnapshot& historicalSnapshot);
    void loadHistoryGeometryData(const revision::HistoricalSnapshot& historicalSnapshot);

    Geom computeGeometryForObject(TOid complexObjectId) const;
    bool needWriteToDb(TOid complexObjectId) const;
    void updateGeometryForComplexObject(TOid complexObjectId);
    void updateGeometry(const TOIds& objectIdsToUpdateGeom);
    TOid applyRevision(const revision::ObjectRevision& revision);

    BBoxContext context_;
    BBoxWriter writer_;

    //object ids involved
    TOIds topLevelComplexObjectIds_;
    std::string topLevelCategoryId_;

    TOIds allComplexObjectIds_;
    StringSet allComplexObjectCategoryIds_;
    std::unordered_map<TOid, ComplexObjectInfo> complexObjectInfos_;

    TOIds geomPartObjectIds_;

    //history revision data
    std::map<TCommitId, std::vector<revision::ObjectRevision>> commitToRevisions_;

    //current data
    TCommitId currentCommitId_;
    std::unordered_map<TOid, TOIds> currentSlaves_;
    std::unordered_map<TOid, TOIds> currentMasters_;
    std::unordered_map<TOid, Geom> currentGeometries_;
};

} // namespace wiki
} // namespace maps
