#include "matcher.h"
#include "camera_angle.h"
#include "segmentation.h"

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/libs/common/include/exception.h>
#include <mapreduce/yt/interface/client.h>


int main(int argc, char* argv[]) try {
    NYT::Initialize(argc, argv);

    maps::cmdline::Parser parser("Matches track to graph using Matcher");
    auto input = parser.string("input")
        .required()
        .help("Path to yt table with input data");

    auto output = parser.string("output")
        .required()
        .help("Path to yt output table");

    auto minInterval = parser.option<std::chrono::seconds>("min-interval")
        .required()
        .help("Minimum time interval between consecutive frames (seconds)");

    auto minDistance = parser.real("min-distance")
        .required()
        .help("Minimum euclidean distance between consecutive frames (meters)");

    auto matchToGraph = parser.flag("match-to-graph")
        .help("Match gps positions to graph")
        .defaultValue(true);

    auto runSegmentation = parser.flag("run-segmentation")
        .help("Run car segmentation on images and fill mask column of output table")
        .defaultValue(false);

    auto refineHeadings = parser.flag("refine-headings")
        .help("Refine headings with vanishing point method")
        .defaultValue(false);

    parser.parse(argc, argv);
    auto client = NYT::CreateClient("hahn");
    TString inputTable = input.c_str();
    TString outputTable = output.c_str();

    // Filter and match coordinates
    maps::mrc::opensfm_experiment::refinePositions(*client, inputTable, outputTable, minInterval, minDistance, matchToGraph);

    if (runSegmentation) {
        maps::mrc::opensfm_experiment::segmentCars(*client, outputTable, outputTable);
    }
    if (refineHeadings) {
        maps::mrc::opensfm_experiment::refineCameraHeadings(*client, outputTable, outputTable);
    }

    return EXIT_SUCCESS;
}
catch (const maps::Exception& e) {
    ERROR() << e;
    return EXIT_FAILURE;
}
catch (const std::exception& e) {
    ERROR() << e.what();
    return EXIT_FAILURE;
}
catch (...) {
    ERROR() << "unknown error";
    return EXIT_FAILURE;
}
