#include "generate_edges_from_tracks.h"

#include "edge.h"
#include "generate_edges.h"
#include "signal.h"
#include "clustering.h"
#include "link.h"
#include "split_into_tracks.h"
#include "turn.h"
#include "turn_visitor.h"
#include "save.h"

#include <maps/libs/log8/include/log8.h>

#include <string>
#include <fstream>

namespace maps {
namespace wiki {
namespace signals_graph {

std::vector<Edge> generateEdgesFromTracks(
    const std::vector<Signal> signals,
    const std::string& outputFilePrefix,
    bool saveIntermediateData
) {
    INFO() << "Loading tracks...";
    std::vector<Track> tracks = splitIntoTracks(signals);
    DEBUG() << "Tracks   count: " << tracks.size();

    INFO() << "Finding turns...";
    TurnVisitor turnVisitor;
    visitTracks(tracks, turnVisitor);
    std::vector<Turn> turns = turnVisitor.validTurns();
    DEBUG() << "Turns    count: " << turns.size();

    INFO() << "Clustering turn samples into turns...";
    auto clusters = clusterTurns(turns);
    DEBUG() << "Clusters count: " << clusters.size();

    INFO() << "Clustering turns into crosses...";
    auto crosses = clusterClusters(clusters);
    DEBUG() << "Crosses  count: " << crosses.size();

    auto links = generateLinks(tracks, turns, clusters);

    sortLinks(links);

    auto edges = generateEdges(tracks, links, crosses);
    INFO() << "Edges    count: " << edges.size();

    if (saveIntermediateData) {
        std::ofstream turnsFile(outputFilePrefix + "turns");
        drawTurns(turns, turnsFile);

        std::ofstream clustersFile(outputFilePrefix + "clusters");
        drawTurns(clusters, clustersFile);

        std::ofstream crossesFile(outputFilePrefix + "crosses");
        drawTurns(crosses, crossesFile);

        std::ofstream edgesFile(outputFilePrefix + "_edges");
        drawEdges(edgesFile, edges);
        saveData(tracks, links, edges, outputFilePrefix + "links", outputFilePrefix + "samples");
    }

    return edges;
}

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