#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/sensors_feature_positioner/include/types.h>

#include <vector>
#include <unordered_map>

namespace maps::mrc::sensors_feature_positioner {

using PointId = size_t;

struct Point {
    PointId id;
    geolib3::Point2 mercatorPos;
    std::vector<PointId> neighbors; // neighboring points that can describe the
                                    // same object
    std::vector<PointId> prohibitedNeighbors; // neighboring points
                                              // that belong to other
                                              // objects for sure
};
using Points = std::unordered_map<PointId, Point>;
using Cluster = std::vector<PointId>;

// Connects points with suitable neighbors and returns separate groups of points.
// The algorighm is inspired by MeanShift algorithm(https://towardsdatascience.com/the-5-clustering-algorithms-data-scientists-need-to-know-a36d136ef68)
// Algorithm:
// 1) calculate neighboring density for each point
// 2) select next unhandled point with max density
// 2.1) create new empty cluster with the center at this point
// 2.2) mark all the neighboring points as handled
// 2.3) go to step 2
// 3) now we have only clusters centers without points. For each
//    cluster we will store the list of points and the
//    list of prohibited points
// 4) iterate over points. For each point:
// 4.1) find the nearest cluster center that don't have this point in
//      the prohibited list. If there are no such clusters, create a
//      new cluster with the center at the point
// 4.2) add the point to the cluster list. Add the point's prohibited
//      neighbors to the cluster prohibited list
// 4.3) go to 4) and handle the next
std::vector<Cluster> getClusters(Points points, double maxClusterRadiusMeters);

} // namespace maps::mrc::sensors_feature_positioner
