#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/common/include/exception.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/pg_locks.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/wiki_config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/object/include/revision_loader.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/feature_publisher/lib/context.h>
#include <yandex/maps/pgpool3utils/pg_advisory_mutex.h>
#include <yandex/maps/wiki/common/extended_xml_doc.h>

int main(int argc, char* argv[])
try {
    auto parser = maps::cmdline::Parser(
        "tool calculates the positions of the photos and publishes them");
    auto syslog = parser.string("syslog-tag")
                      .help("redirect log output to syslog with given tag");
    auto configPath = parser.string("config").help("path to configuration");
    auto wikiConfigDirPath = parser.string("wiki-config-dir")
            .defaultValue(maps::mrc::common::WIKI_TEMPLATE_CONFIG_DIR)
            .help("path to services config template for wikimap");
    auto wikiConfigPath =
        parser.string("wiki-config")
            .help("path to services config for wikimap");
    auto roadGraphPath = parser.string("road-graph")
                             .defaultValue("/usr/share/yandex/maps/graph")
                             .help("directory road graph data is loaded from");
    auto pedestrianGraphPath =
        parser.string("pedestrian-graph")
            .defaultValue(
                "/var/lib/yandex/maps/ecstatic/data/"
                "yandex-maps-pedestrian-graph-fb")
            .help("directory pedestrian graph data is loaded from");
    parser.parse(argc, argv);
    if (syslog.defined()) {
        maps::log8::setBackend(maps::log8::toSyslog(syslog));
    }
    INFO() << "starting";
    auto config = maps::mrc::common::templateConfigFromCmdPath(configPath);
    auto wikiConfig = wikiConfigPath.defined()
        ? maps::wiki::common::ExtendedXmlDoc(wikiConfigPath)
        : maps::mrc::common::makeWikiConfig(wikiConfigDirPath);
    auto wikiPoolHolder =
        maps::wiki::common::PoolHolder{wikiConfig, "long-read", "long-read"};
    auto objectLoader = maps::mrc::object::makeRevisionLoader(
        wikiPoolHolder.pool().slaveTransaction());
    auto regionPrivacy = maps::mrc::privacy::makeCachingRegionPrivacy(
        *objectLoader, config.externals().geoIdCoveragePath());
    auto cameraDeviationClassifier = std::make_unique<
        maps::mrc::feature_publisher::CameraDeviationClassifier>();
    auto ctx = maps::mrc::feature_publisher::Context(
        config,
        roadGraphPath,
        pedestrianGraphPath,
        std::move(regionPrivacy),
        std::move(cameraDeviationClassifier));
    auto mutex = maps::pgp3utils::PgAdvisoryXactMutex(
        ctx.pool(),
        static_cast<int64_t>(maps::mrc::common::LockId::FeaturePublisher));
    if (!mutex.try_lock()) {
        INFO() << "another process is ongoing";
        return EXIT_SUCCESS;
    }
    ctx.processClassifiedPhotos();
    INFO() << "shutting down";
    return EXIT_SUCCESS;
}
catch (const maps::Exception& e) {
    ERROR() << e;
    return EXIT_FAILURE;
}
catch (const std::exception& e) {
    ERROR() << e.what();
    return EXIT_FAILURE;
}
