#include "categories_holder.h"
#include <maps/wikimap/mapspro/services/editor/src/configs/config.h>
#include <maps/wikimap/mapspro/services/editor/src/objects/category_traits.h>

#include <yandex/maps/wiki/configs/editor/categories.h>
#include <yandex/maps/wiki/configs/editor/slave_role.h>

namespace maps {
namespace wiki {

CategoriesHolder::CategoriesHolder()
{
    processCategories(cfg()->editor()->categories().idsByFilter(Categories::CachedGeom));
}

CategoriesHolder::CategoriesHolder(StringSet initialCategoryIds)
{
    processCategories(std::move(initialCategoryIds));
}

void CategoriesHolder::processCategories(StringSet categoryIds)
{
    size_t oldCategoriesCount = 0;

    // Go up in the categories hierarchy
    do {
        oldCategoriesCount = categoryIds.size();
        for (const auto& categoryId : cfg()->editor()->categories().idsByFilter(Categories::All)) {
            const auto& category = cfg()->editor()->categories()[categoryId];
            for (const auto& slaveRoleId : category.geomSlaveRoleIds()) {
                if (categoryIds.count(category.slaveRole(slaveRoleId).categoryId())) {
                    categoryIds.insert(categoryId);
                }
            }
        }
    } while (categoryIds.size() > oldCategoriesCount);

    // Go down in the categories hierarchy
    do {
        oldCategoriesCount = categoryIds.size();
        for (const auto& categoryId : categoryIds) {
            const auto& category = cfg()->editor()->categories()[categoryId];
            for (const auto& slaveRoleId : category.geomSlaveRoleIds()) {
                categoryIds.insert(category.slaveRole(slaveRoleId).categoryId());
            }
        }
    } while (categoryIds.size() > oldCategoriesCount);

    for (const auto& categoryId : categoryIds) {
        const auto& category = cfg()->editor()->categories()[categoryId];
        if (category.complex()) {
            if (category.cacheGeomPartsThreshold()) {
                complexCategoryIds_.insert(categoryId);
            }
        } else if (isSimpleGeomCategory(category)) {
            geoCategoryIds_.insert(categoryId);
        }
    }
}

} // namespace wiki
} // namespace maps
