#include "../include/task.h"

#include <boost/lexical_cast.hpp>

#include <yandex/maps/wiki/common/yt.h>
#include <maps/libs/geolib/include/conversion.h>
#include <maps/libs/geolib/include/serialization.h>

namespace maps::wiki::guide_pedestrian {

namespace {

double calculatePerimeterMeters(const geolib3::Polygon2& polygonMerc)
{
    if (polygonMerc.totalPointsNumber() == 0) {
        return 0;
    }
    auto ratio = geolib3::MercatorRatio::fromMercatorPoint(polygonMerc.pointAt(0));
    return ratio.toMeters(polygonMerc.perimeter());
}

std::string asGeoWKT(const geolib3::Polygon2& polygonMerc)
{
    return geolib3::WKT::toString(geolib3::convertMercatorToGeodetic(polygonMerc));
}

} // unnamed namespace

void enqueueAddressTasks(
    const AddressTasks& addressTasks,
    const std::string& ytProxy,
    const std::string& ytPath)
{
    if (addressTasks.empty()) {
        return;
    }
    auto client = common::yt::createYtClient(TString(ytProxy));
    auto writer = client->CreateTableWriter<NYT::TNode>(NYT::TRichYPath(TString(ytPath)).Append(true));

    for (const auto& task: addressTasks) {
        writer->AddRow(
            NYT::TNode()
            ("timestamp", maps::chrono::sinceEpoch<std::chrono::seconds>(task.timePoint))
            ("lon", task.lon)
            ("lat", task.lat)
            ("buildingId", TString(task.buildingId))
            ("taskId", TString(task.taskId))
            ("buildingPerimeter", calculatePerimeterMeters(task.polygonMerc))
            ("buildingShape", TString(asGeoWKT(task.polygonMerc)))
        );
    }
    writer->Finish();
}

void enqueueEntranceTasks(
    const EntranceTasks& entranceTasks,
    const std::string& ytProxy,
    const std::string& ytPath)
{
    if (entranceTasks.empty()) {
        return;
    }
    auto client = common::yt::createYtClient(TString(ytProxy));
    auto writer = client->CreateTableWriter<NYT::TNode>(NYT::TRichYPath(TString(ytPath)).Append(true));

    for (const auto& task: entranceTasks) {
        auto node = NYT::TNode()
            ("timestamp", maps::chrono::sinceEpoch<std::chrono::seconds>(task.timePoint))
            ("lon", task.lon)
            ("lat", task.lat)
            ("buildingId", TString(task.buildingId))
            ("taskId", TString(task.taskId))
            ("buildingPerimeter", calculatePerimeterMeters(task.polygonMerc))
            ("buildingShape", TString(asGeoWKT(task.polygonMerc)))
        ;
        if (task.address) {
            node("address", TString(*task.address));
        }
        writer->AddRow(node);
    }
    writer->Finish();
}

} // namespace maps::wiki::guide_pedestrian
