#pragma once

#include "camera_deviation_classifier.h"

#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/track_point.h>
#include <maps/wikimap/mapspro/services/mrc/libs/graph_matcher_adapter/include/compact_graph_matcher_adapter.h>
#include <maps/wikimap/mapspro/services/mrc/libs/privacy/include/region_privacy.h>

namespace maps::mrc::feature_publisher {

class Context {
public:
    Context(const common::Config&,
            const std::string& roadGraphPath,
            const std::string& pedestrianGraphPath,
            privacy::RegionPrivacyPtr,
            ICameraDeviationClassifierHolder);

    pgpool3::Pool& pool() { return poolHolder_.pool(); }

    size_t processClassifiedPhotos();

public:  // public for unit-test only
    void setCameraDeviationClassifier(ICameraDeviationClassifierHolder);

    void evalSize(db::Features::iterator first, db::Features::iterator last);

    void evalUserSetingsForPassage(db::Features::iterator first,
                                   db::Features::iterator last);

    void evalPositionForPassage(db::Features::iterator first,
                                db::Features::iterator last);

    void evalCameraDeviationForPassage(db::Features::iterator first,
                                       db::Features::iterator last);

private:
    wiki::common::PoolHolder poolHolder_;
    mds::Mds mds_;
    adapters::CompactGraphMatcherAdapter roadMatcher_;
    adapters::CompactGraphMatcherAdapter pedestrianMatcher_;
    privacy::RegionPrivacyPtr regionPrivacy_;
    ICameraDeviationClassifierHolder cameraDeviationClassifier_;

    db::TrackPoints loadAssignmentTrackPoints(db::TId assignmentId);

    db::TrackPoints loadTrackPoints(const std::string& sourceId,
                                    chrono::TimePoint startTime,
                                    chrono::TimePoint endTime);
    db::FeaturePrivacy evalFeatureRegionPrivacy(const db::Feature& feature) const;
    db::FeaturePrivacy evalFeaturePrivacy(const db::Feature& feature) const;

    void publishPassage(db::Features::iterator first,
                        db::Features::iterator last);

    auto loadTrackPointsFn()
    {
        return [this](const std::string& sourceId,
                      chrono::TimePoint startTime,
                      chrono::TimePoint endTime) {
            return loadTrackPoints(sourceId, startTime, endTime);
        };
    }

    common::Blob loadImage(const db::Feature&);

    std::vector<db::CameraDeviation> loadAllowedCameraDeviations(
        const db::Feature&);

    void processPhotos(db::Features /*sink*/);
};

}  // namespace maps::mrc::feature_publisher
