#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature.h>
#include <maps/wikimap/mapspro/services/mrc/libs/graph_matcher_adapter/include/compact_graph_matcher_adapter.h>
#include <maps/wikimap/mapspro/services/mrc/libs/track_classifier/include/track_classifier.h>

#include <functional>
#include <map>

namespace maps {
namespace mrc {
namespace adapters {

using GraphTypeToMatcherMap = std::map<db::GraphType, const Matcher*>;

using TrackPointProvider
    = std::function<db::TrackPoints(const std::string& sourceId,
                                    chrono::TimePoint startTime,
                                    chrono::TimePoint endTime)>;

using TrackClassifier
    = std::function<std::vector<track_classifier::TrackInterval>(db::TrackPoints, const GraphTypeToMatcherMap&)>;

class FeaturePositioner {
public:
    FeaturePositioner(GraphTypeToMatcherMap,
                      TrackPointProvider,
                      TrackClassifier = track_classifier::classify);

    /**
     * Detect the camera position, if possible.
     * The order of photos is unstable.
     *
     * Return: True if type of graph of any feature was changed
     */
    bool operator()(db::Features&) const;


    /**
     * Detect the camera position, if possible.
     * Features was sorted by tuple(feature.sourceId(), feature.timestamp()).
     *
     * Return: True if type of graph of any feature was changed
     */
    bool operator()(db::Features::iterator, db::Features::iterator) const;
private:
    GraphTypeToMatcherMap graphTypeToMatcherMap_;
    TrackPointProvider trackPointProvider_;
    TrackClassifier trackClassifier_;

    const Matcher* getMatcherByType(track_classifier::TrackType) const;
};

TrackClassifier classifyAs(track_classifier::TrackType);

} // adapters
} // mrc
} // maps
