#include <maps/wikimap/mapspro/services/mrc/tools/sign-positioning-dataset/common/constants.h>

#include <maps/wikimap/mapspro/services/mrc/libs/common/include/types.h>
#include <yandex/maps/proto/offline-mrc/results.sproto.h>

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/json/include/value.h>
#include <maps/libs/log8/include/log8.h>

#include <boost/filesystem.hpp>

#include <cstdio>
#include <fstream>

using namespace maps::mrc;
namespace spresults = yandex::maps::sproto::offline::mrc::results;

namespace {

spresults::Results filter(const maps::json::Value& imagesMeta,
                          const spresults::Results& resultsIn)
{
    spresults::Results resultsOut;

    for (const auto& trackPoint : resultsIn.track()) {
        resultsOut.track().push_back(trackPoint);
    }
    for (const auto& report : resultsIn.reports()) {
        resultsOut.reports().push_back(report);
    }

    std::size_t metaIdx = 0;
    for (const auto& image : resultsIn.images()) {
        auto metaTs = imagesMeta[metaIdx]["feature_ts"].as<std::uint64_t>();

        // TODO: rebuild metadata JSON
        // Skip metadata w\o image
        while (metaTs < image.created() && imagesMeta.size() <= metaIdx) {
            ++metaIdx;
            metaTs = imagesMeta[metaIdx]["feature_ts"].as<std::uint64_t>();
            WARN() << "\"Hanging\" metadata of "
                   << imagesMeta[metaIdx]["feature_id"].as<std::uint64_t>();
        }

        // Skip images w\o metadata
        if (image.created() < metaTs) {
            continue;
        }

        resultsOut.images().push_back(image);
        if (imagesMeta.size() <= ++metaIdx) {
            break;
        }
    }
    return resultsOut;
}

} // namespace

int main(int argc, char** argv)
{
    maps::cmdline::Parser parser("A tool to visualize MRC datasets");
    auto datasetDir
        = parser.dir("dir").help("dataset directory").defaultValue(".");
    auto datasetPrefix
        = parser.string("prefix").help("dataset prefix").required();
    parser.parse(argc, argv);

    const auto metaPath
        = boost::filesystem::path{datasetDir}
          / (datasetPrefix + dataset::IMAGES_META_FILENAME_POSTFIX);
    const auto resultsPath
        = boost::filesystem::path{datasetDir}
          / (datasetPrefix + dataset::RESULTS_FILENAME_POSTFIX);

    spresults::Results mrcResults;
    std::ifstream{resultsPath.string(), std::ios::binary} >> mrcResults;
    const maps::json::Value imagesMeta
        = maps::json::Value::fromFile(metaPath.string());

    std::ofstream{resultsPath.string(), std::ios::binary}
        << filter(imagesMeta, mrcResults);

    return EXIT_SUCCESS;
}
