#pragma once

#include "common.h"

#include <maps/wikimap/mapspro/libs/poi_feed/include/feed_object_data.h>

#include <maps/libs/introspection/include/comparison.h>
#include <maps/libs/chrono/include/time_point.h>

#include <boost/optional.hpp>

#include <ctime>
#include <string>
#include <tuple>
#include <vector>

namespace maps::wiki::poi {

using DBIDSet = revision::DBIDSet;
using UserID = revision::UserID;

enum class HasVerifiedCoords
{
    False,
    True
};

enum class PermalinkFromReserves
{
    False,
    True
};

struct EntranceDef {
    DBID id;
    double lon;
    double lat;
};

struct PoiDef {
    boost::optional<DBID> id;
    boost::optional<DBID> recentCommitId;
    boost::optional<chrono::TimePoint> actualizationDate;
    std::set<RubricId> rubricIds;
    boost::optional<RubricId> userDefinedRubricId;
    std::set<RubricId> userDefinedSecondaryRubricIds;
    std::set<poi_feed::LocalizedString> names;
    std::set<poi_feed::LocalizedString> shortNames;
    std::set<poi_feed::LocalizedString> synonymNames;
    std::set<std::string> phones;
    std::string url;
    std::string email;
    std::string permalink;
    std::string workingTime;
    std::string publishingStatus;
    boost::optional<double> lon;
    boost::optional<double> lat;
    DBIDSet nameIds; // to calculate actualization date
    DispClass dispClass;
    std::string mtrId;
    std::string importSource;
    boost::optional<FtTypeId> ftTypeId;
    boost::optional<UserID> modifiedBy;
    std::optional<std::vector<EntranceDef>> entrances;
    std::string indoorLevelUniversal;
    boost::optional<DBID> indoorPlanId;
    std::optional<poi_feed::FeedObjectData::IsGeoproduct> isGeoproduct;
    PermalinkFromReserves permalinkFromReserves = PermalinkFromReserves::False;
    HasVerifiedCoords hasVerifiedCoords = HasVerifiedCoords::False;
    std::string positionQuality;
};

inline auto introspect(const EntranceDef& def)
{
    return std::tie(def.lon, def.lat);
}

inline auto introspect(const PoiDef& def)
{
    return std::tie(
        def.id,
        def.rubricIds, def.userDefinedRubricId, def.userDefinedSecondaryRubricIds,
        def.names, def.shortNames, def.synonymNames,
        def.phones, def.url, def.email, def.permalink,
        def.workingTime, def.publishingStatus,
        def.lon, def.lat, def.nameIds, def.dispClass, def.mtrId,
        def.importSource, def.ftTypeId, def.modifiedBy,
        def.entrances,
        def.indoorLevelUniversal, def.indoorPlanId,
        def.isGeoproduct, def.permalinkFromReserves,
        def.hasVerifiedCoords, def.positionQuality);
}
using introspection::operator==;
using introspection::operator<;

using PoiDefs = std::vector<PoiDef>;

bool isFullMergeImplemented(const PoiDef& poiDef);

} // namespace maps::wiki::poi
