#pragma once

#include <maps/libs/common/include/exception.h>

#include <string>
#include <map>
#include <set>
#include <memory>

namespace maps {
namespace wiki {
namespace topology_fixer {

enum class TopologyGroupId {
    Ad,
    Vegetation,
    HydroContour,
    HydroLn,
    Urban,
    UrbanRoadnet,
    Relief,
    Landmark,
    TransportRailway
};

const std::string AD = "ad";
const std::string VEGETATION = "vegetation";
const std::string CONTOUR_HYDROGRAPHY = "hydro_contour";
const std::string LINEAR_HYDROGRAPHY = "hydro_ln";
const std::string URBAN = "urban";
const std::string URBAN_ROADNET = "urban_roadnet";
const std::string RELIEF = "relief";
const std::string LANDMARK = "landmark";
const std::string TRANSPORT_RAILWAY = "transport_railway";

typedef uint16_t FtTypeId;

enum class TopologyType { Linear, Contour };

class TopologyGroup {
public:
    typedef std::set<FtTypeId> FtTypes;

    TopologyGroup(
            TopologyGroupId id,
            const std::string& name,
            const FtTypes& ftTypes,
            TopologyType topologyType)
        : id_(id)
        , name_(name)
        , ftTypes_(ftTypes)
        , topologyType_(topologyType)
    {}

    TopologyGroupId id() const { return id_; }
    const std::string& name() const { return name_; }
    const FtTypes& ftTypes() const { return ftTypes_; }
    const TopologyType& topologyType() const { return topologyType_; }

    const std::string& masterTable() const;

    std::string sqlFtTypeFilter(const std::string& ftTypeIdField) const;

private:
    TopologyGroupId id_;
    std::string name_;
    FtTypes ftTypes_;
    TopologyType topologyType_;
};

typedef std::shared_ptr<const TopologyGroup> TopologyGroupPtr;

typedef std::vector<TopologyGroupPtr> TopologyGroups;


class UnknownTopologyGroupException : public maps::Exception {};

class TopologyGroupsRegistry {
public:
    TopologyGroupsRegistry();

    TopologyGroupPtr operator [] (TopologyGroupId groupId) const;

    TopologyGroupPtr operator [] (const std::string& groupName) const;

    TopologyGroups allGroups() const;

private:
    typedef std::map<TopologyGroupId, TopologyGroupPtr> TopologyGroupsMap;
    typedef std::map<std::string, TopologyGroupPtr> TopologyGroupsByNamesMap;

    TopologyGroupsMap groups_;
    TopologyGroupsByNamesMap groupsByNames_;
};


const TopologyGroupsRegistry& topologyGroupsRegistry();


} // namespace topology_fixer
} // namespace wiki
} // namespace maps
