#include "envelope_info.h"

#include <maps/wikimap/mapspro/services/editor/src/objects/relation_object.h>
#include <maps/wikimap/mapspro/services/editor/src/configs/config.h>
#include <yandex/maps/wiki/configs/editor/categories.h>

namespace maps::wiki {

EnvelopeInfo::EnvelopeInfo(
    const GeoObjectCollection& collection, ObjectsCache& cache)
{
    std::map<TRevisionId, ObjectPtr> geomDiffObjects;
    const auto& categoriesCfg = cfg()->editor()->categories();
    for (const auto& obj : collection) {
        if (!obj->geom().isNull()) {
            geomDiffObjects.insert({obj->revision(), obj});
            if (obj->hasExistingOriginal()) {
                geomDiffObjects.insert({obj->original()->revision(), obj->original()});
            }
        } else if (is<RelationObject>(obj)) {
            auto rel = as<RelationObject>(obj);
            const auto& role =
                categoriesCfg[rel->masterCategoryId()].slaveRole(rel->role());
            if (role.geomPart()) {
                auto slave = cache.getExisting(rel->slaveId());
                geomDiffObjects.insert({slave->revision(), slave});
            }
        }
    }
    for (const auto& idObjPair : geomDiffObjects) {
        objects_.push_back(idObjPair.second);
        auto objectEnvelope = idObjPair.second->envelope();
        if (!objectEnvelope.isNull()) {
            envelope_.expandToInclude(&objectEnvelope);
        }
    }

    auto primaryObj = collection.primaryObject();
    if (primaryObj) {
        if (objects_.empty()) {
            objects_.push_back(primaryObj);
        }
        if (envelope_.isNull()) {
            envelope_ = primaryObj->envelope();
        }
    }

    if (envelope_.isNull()) {
        for (const auto& object : collection) {
            auto objEnvelope = object->envelope();
            envelope_.expandToInclude(&objEnvelope);
        }
    }
}
} // namespace maps::wiki
