#include <maps/wikimap/mapspro/tools/traffic_analyzer/lib/graph_load.h>
#include <maps/wikimap/mapspro/tools/traffic_analyzer/lib/hyp_converter.h>
#include <maps/wikimap/mapspro/tools/traffic_analyzer/lib/hyp_serialize.h>
#include <maps/wikimap/mapspro/tools/traffic_analyzer/lib/hypotheses.h>
#include <maps/wikimap/mapspro/tools/traffic_analyzer/lib/revision_roads_miner_db.h>
#include <maps/wikimap/mapspro/tools/traffic_analyzer/lib/revision_snapshot_holder.h>

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/common/include/exception.h>
#include <maps/libs/log8/include/log8.h>
#include <yandex/maps/wiki/common/extended_xml_doc.h>

#include <iostream>

namespace mwc = maps::wiki::common;
namespace mwr = maps::wiki::revision;
namespace mwt = maps::wiki::traffic_analyzer;

/*
    stdin:  hypothesis in terms of static road graph. Json
    stdout: hypothesis in terms of revision. Json
*/
int main(int argc, char* argv[]) try
{
    maps::cmdline::Parser parser;

    auto revisionConfig = parser.string("revision-config")
        .help("Path to revision db configuration file")
        .required();

    auto graphVersion = parser.string("graph-version")
        .help("Graph version")
        .required();
    parser.parse(argc, argv);

    INFO() << "Creating Revision Shapshot";
    mwc::ExtendedXmlDoc xmlDoc(revisionConfig);
    mwt::RevisionSnapshotHolder snapshotHolder(xmlDoc);

    INFO() << "Loading static road graph";
    mwt::GraphMmapped graph = mwt::loadGraph(graphVersion);

    auto revRoadsMiner = std::make_unique<mwt::RevisionRoadsMinerDB>(
        snapshotHolder.snapshot());
    mwt::OnewayHypothesisConverter converter(graph, std::move(revRoadsMiner));

    INFO() << "Converting hypotheses from graph to revision";
    std::string hypGraphStr;
    while (std::cin >> hypGraphStr) {
        mwt::OnewayHypothesisGraph hypGraph =
            mwt::fromJson<mwt::OnewayHypothesisGraph>(hypGraphStr);

        REQUIRE(hypGraph.roadTraffic.graphVersion == graphVersion,
            "Hypotethis graph version differs from the loaded graph version");

        auto hypRev = converter.convert(hypGraph);
        if (hypRev) {
            std::cout << mwt::toJson(*hypRev) << "\n";
        }
    }

    return 0;

} catch (const maps::Exception& e) {
    std::cout << e << "\n";
    return 0;
} catch (const std::exception& e) {
    std::cout << e.what() << "\n";
    return 0;
}
