#pragma once

#include <yandex/maps/wiki/diffalert/object.h>
#include <yandex/maps/wiki/diffalert/revision/diff_context.h>
#include <yandex/maps/wiki/diffalert/revision/snapshot.h>
#include <yandex/maps/wiki/diffalert/storage/stored_message.h>

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

#include <shared_mutex>

#include <unordered_set>
#include <unordered_map>

namespace maps::wiki::diffalert {

/**
Search for the russian name of the object
*/
class ObjectLabeler
{
public:
    explicit ObjectLabeler(const configs::editor::ConfigHolder& editorConfig);

    std::string nameForObject(LongtaskSnapshot& snapshot, Object& object);

private:
    using MasterRoleIds = std::unordered_set<std::string>;

    std::string loadName(LongtaskSnapshot& snapshot, Object& object);
    std::string loadDirectName(LongtaskSnapshot& snapshot, Object& object);
    std::string loadIndirectName(LongtaskSnapshot& snapshot, Object& object, const MasterRoleIds& masterRoleIds);

    std::string loadAddrName(LongtaskSnapshot& snapshot, Object& object);

    std::shared_mutex cacheMutex_;
    std::map<TId, std::string> nameCache_;
    std::set<TId> noNameCache_;

    std::unordered_set<std::string> categoriesWithDirectNames_;
    std::unordered_map<std::string, MasterRoleIds> categoryToMasterRoles_;
};

class DiffLabeler
{
public:
    explicit DiffLabeler(const configs::editor::ConfigHolder& editorConfig);

    /**
     * @returns a pair of the name of the object and a boolean flag indicating if this object has its own name
     */
    std::pair<std::string, HasOwnName> nameForObject(const LongtaskDiffContext& diffContext);

private:
    const configs::editor::ConfigHolder& editorConfig_;
    ObjectLabeler oldObjectLabeler_;
    ObjectLabeler newObjectLabeler_;
};

} // maps::wiki::diffalert
