#include "site_and_spots_as_object_diff.h"

#include <maps/libs/geolib/include/conversion.h>
#include <yandex/maps/wiki/geom_tools/object_diff_builder.h>

namespace maps::wiki::sync_fbapi_feedback {

namespace {

geolib3::PolylinesVector makeMercatorCrosses(
    const geolib3::PointsVector& mercatorPoints)
{
    static const double CROSS_SIZE_METERS = 10;
    const double crossSize = geolib3::toMercatorUnits(CROSS_SIZE_METERS, mercatorPoints.front());

    geolib3::PolylinesVector lines;
    for (const auto& point : mercatorPoints) {
        lines.emplace_back(geolib3::PointsVector{
            geolib3::Point2(point.x() - crossSize / 2, point.y() - crossSize / 2),
            geolib3::Point2(point.x() + crossSize / 2, point.y() + crossSize / 2),
        });
        lines.emplace_back(geolib3::PointsVector{
            geolib3::Point2(point.x() + crossSize / 2, point.y() - crossSize / 2),
            geolib3::Point2(point.x() - crossSize / 2, point.y() + crossSize / 2),
        });
    }

    return lines;
}

geolib3::PolylinesVector mercatorPointsAndSiteAsGeodetic(
    const geolib3::PointsVector& points,
    const std::optional<geolib3::Polyline2>& site)
{
    geolib3::PolylinesVector result;
    if (!points.empty()) {
        result = geolib3::convertMercatorToGeodetic(makeMercatorCrosses(points));
    }
    if (site) {
        result.emplace_back(geolib3::convertMercatorToGeodetic(*site));
    }
    return result;
}

} // namespace

SiteAndSpotsAsObjectDiff& SiteAndSpotsAsObjectDiff::setMercatorSiteBefore(
    geolib3::Polyline2 mercatorSite)
{
    mercatorSiteBefore_ = std::move(mercatorSite);
    return *this;
}

SiteAndSpotsAsObjectDiff& SiteAndSpotsAsObjectDiff::setMercatorSiteAfter(
    geolib3::Polyline2 mercatorSite)
{
    mercatorSiteAfter_ = std::move(mercatorSite);
    return *this;
}

SiteAndSpotsAsObjectDiff& SiteAndSpotsAsObjectDiff::setMercatorPointsBefore(
    geolib3::PointsVector mercatorPoints)
{
    mercatorPointsBefore_ = std::move(mercatorPoints);
    return *this;
}

SiteAndSpotsAsObjectDiff& SiteAndSpotsAsObjectDiff::setMercatorPointsAfter(
    geolib3::PointsVector mercatorPoints)
{
    mercatorPointsAfter_ = std::move(mercatorPoints);
    return *this;
}

void SiteAndSpotsAsObjectDiff::json(json::ObjectBuilder builder) const
{
    geom_tools::ObjectDiffBuilder<geolib3::Polyline2> objectDiffBuilder;
    objectDiffBuilder.setBefore(mercatorPointsAndSiteAsGeodetic(mercatorPointsBefore_, mercatorSiteBefore_));
    objectDiffBuilder.setAfter(mercatorPointsAndSiteAsGeodetic(mercatorPointsAfter_, mercatorSiteAfter_));
    objectDiffBuilder.json(builder);
}

} // namespace maps::wiki::sync_fbapi_feedback
