#pragma once

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

#include <maps/libs/geolib/include/bounding_box.h>
#include <maps/libs/geolib/include/direction.h>
#include <maps/libs/geolib/include/polyline.h>
#include <maps/libs/geolib/include/segment.h>

namespace maps::mrc::db {

using Segments = std::vector<geolib3::Segment2>;

struct Ray {
    geolib3::Point2 pos;
    geolib3::Direction2 direction;
};

Ray getRay(geolib3::Point2 pos,
           geolib3::Direction2 moveDirection,
           CameraDeviation cameraDeviation);

Ray getRay(const Feature& feature);

/**
 * @return rectangular isosceles triangle
 *
 *    A
 *   /|\
 *  /_|_\
 * C  H  B
 *
 * A - camera position
 * AH - camera direction
 */
geolib3::Polygon2 fieldOfView(const Ray& ray);

/// @return true if @param track intersects visible space of @param feature (direction sensitive)
bool isVisible(const Feature& feature, const geolib3::Polyline2& track);

bool isVisible(const Feature& feature, const Segments& track);

bool isVisible(const geolib3::Point2& geodeticPos,
    const geolib3::Direction2& moveDirection,
    const CameraDeviation cameraDeviation,
    const geolib3::Polyline2& track);

bool isVisible(
    const geolib3::Point2& pos,
    const geolib3::Direction2& moveDirection,
    const CameraDeviation cameraDeviation,
    const Segments& segments);

geolib3::BoundingBox expandBbox(const geolib3::BoundingBox& bbox, double meters);

/// @return rectangle within a visibility distance from @param bbox
geolib3::BoundingBox addVisibilityMargins(const geolib3::BoundingBox& bbox);

geolib3::Direction2 direction(const Feature& feature);

double length(const Segments& segments);

double geoLength(const Segments& segments);

/// @return the invisible part of the @param segments
Segments getUncovered(const Feature& feature, const db::Segments& segments);

Segments getUncovered(const geolib3::Point2& pos,
    const geolib3::Direction2& moveDirection,
    const CameraDeviation cameraDeviation,
    const Segments& segments);

} // namespace maps::mrc::db
