#include "metrics.h"

#include "difference_result.h"
#include "../edge.h"
#include "grid.h"
#include "buffer_difference.h"

#include <maps/libs/geolib/include/polyline.h>

namespace maps {
namespace wiki {
namespace signals_graph {

Metrics calculateMetrics(
    const std::vector<geolib3::Polyline2>& revisionEdges,
    const std::vector<Edge>& gpsEdges,
    const std::vector<common::Geom>& diffGeometries,
    const Grid& grid
) {
    Metrics result;

    auto revisionIndices = calculateIndices(grid, revisionEdges);

    for (size_t i = 0; i < grid.heightCells; ++i) {
        for (size_t j = 0; j < grid.widthCells; ++j) {
            auto cellGraph = cutCellEdgesGeoms(
                revisionEdges, revisionIndices[i][j], grid.boxes[i][j]);

            for (const auto& geom : cellGraph) {
                result.targetLength += geom.geosGeometryPtr()->getLength();
            }
        }
    }

    for (const auto& edge : gpsEdges) {
        result.inputLength += geolib3::length(edge.polyline);
    }

    for (const auto& diff : diffGeometries) {
        if (!diff.isNull()) {
            result.uncoveredTargetLength += diff.geosGeometryPtr()->getLength();
        }
    }

    return result;
}

void printMetrics(const Metrics& result) {
    INFO() << "--- Metric ---";
    INFO() << "Graph length: " << result.targetLength;
    INFO() << "Hyps  length: " << result.inputLength;
    INFO() << "NoCov length: " << result.uncoveredTargetLength;

    double recall = 1 - result.uncoveredTargetLength / result.targetLength;
    double precision =
        (result.targetLength - result.uncoveredTargetLength) / result.inputLength;
    double f_measure = 2 * recall * precision / (precision + recall);
    double f2_measure = 5 * recall * precision / (4 * precision + recall);

    INFO() << "Recall:       " << recall;
    INFO() << "Precision:    " << precision;
    INFO() << "F-measure:    " << f_measure;
    INFO() << "F2-measure:    " << f2_measure;
    INFO() << "--------------";
}

} // namespace signals_graph
} // namespace wiki
} // namespace maps
