#pragma once

#include <maps/libs/xml/include/xml.h>

#include <optional>
#include <unordered_set>
#include <set>

namespace maps {
namespace wiki {
namespace configs {
namespace editor {

using Isocodes = std::unordered_set<std::string>;
using AttrValuePair = std::pair<std::string, std::string>;

class Country
{
public:
    class FcRangeSpeedLimits
    {
    public:
        explicit FcRangeSpeedLimits(const maps::xml3::Node& node);

        size_t inLocality() const { return inLocality_; }
        size_t outLocality() const { return outLocality_; }

        size_t minFc() const { return minFc_; }
        size_t maxFc() const { return maxFc_; }

    private:
        size_t minFc_;
        size_t maxFc_;
        size_t inLocality_;
        size_t outLocality_;
    };

    explicit Country(const maps::xml3::Node& node);

    const std::string& isocode() const
    { return isocode_; }

    std::optional<FcRangeSpeedLimits> fcRangeSpeedLimits(size_t fc) const;

    bool isProhibitedCategory(const std::string& categoryId) const
    { return 0 != prohibitedCategories_.count(categoryId); }

    const std::unordered_set<std::string>& prohibitedCategories() const
    { return prohibitedCategories_; }

    const std::set<AttrValuePair>& prohibitedAttributeValues() const
    { return prohibitedAttributeValues_; }

private:
    std::string isocode_;
    std::vector<FcRangeSpeedLimits> fcRangeSpeedLimits_;
    std::unordered_set<std::string> prohibitedCategories_;
    std::set<AttrValuePair> prohibitedAttributeValues_;
};

class Countries
{
public:
    explicit Countries(const maps::xml3::Node& node);

    bool hasCountryWithISOCODE(const std::string& isocode) const;

    const Country& findByISOCODE(const std::string& isocode) const;

    Isocodes isocodesWhereCategoryIsProhibited(const std::string& categoryId) const;
    std::unordered_set<std::string> categoriesProhibitedSomewhere() const;

    Isocodes
    isocodesWhereAttributeValueIsProhibited(const std::string& attributeId, const std::string& valueId) const;

private:
    std::map<std::string, Country> countries_;
    std::unordered_map<std::string, Isocodes> categoryProhibitedIsocodes_;
    std::unordered_set<std::string> categoriesProhibitedSomewhere_;
    std::map<AttrValuePair, Isocodes> attrValueProhibitedIsocodes_;
};

} // editor
} // configs
} // wiki
} // maps
