#include "worker.h"

#include <yandex/maps/wiki/common/default_config.h>
#include <yandex/maps/wiki/common/extended_xml_doc.h>
#include <yandex/maps/wiki/common/retry_duration.h>

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/mongo/include/init.h>
#include <maps/libs/common/include/exception.h>
#include <maps/tools/grinder/worker/include/api.h>

namespace common = maps::wiki::common;
namespace worker = maps::grinder::worker;

namespace {

constexpr size_t WORKER_CONCURRENCY = 1;
const auto DEFAULT_RETRY_DURATION = std::chrono::hours(8);

std::unique_ptr<common::ExtendedXmlDoc> getConfig(
    const maps::cmdline::Option<std::string>& configFilename)
{
    std::unique_ptr<common::ExtendedXmlDoc> configXml;
    if (configFilename.defined()) {
        configXml.reset(new common::ExtendedXmlDoc(configFilename));
    } else {
        configXml = common::loadDefaultConfig();
    }
    return configXml;
}

} // namespace

int main(int argc, char* argv[]) try
{
    maps::cmdline::Parser parser;
    auto workerConfig = parser.string("config")
            .help("path to worker configuration");
    auto syslogTag = parser.string("syslog-tag")
            .help("redirect log output to syslog with given tag");
    auto grinderConfig = parser.string("grinder-config")
            .help("path to grinder configuration file");

    parser.parse(argc, argv);

    common::RetryDurationPolicy::setDefaultDuration(DEFAULT_RETRY_DURATION);
    if (syslogTag.defined()) {
        maps::log8::setBackend(maps::log8::toSyslog(syslogTag));
    }

    maps::mongo::init();

    auto config = getConfig(workerConfig);
    maps::wiki::validation_export::Worker w(*config);

    worker::Options workerOpts;

    if (grinderConfig.defined()) {
        workerOpts.setConfigLocation(grinderConfig);
    }

    workerOpts.on(maps::wiki::validation_export::TASK_NAME,
            [&](const worker::Task& task) {
                w.run(task);
            }
        ).setConcurrencyLevel(WORKER_CONCURRENCY);

    worker::run(std::move(workerOpts));

    return EXIT_SUCCESS;
} catch (const maps::Exception& e) {
    FATAL() << "Worker failed: " << e;
    return EXIT_FAILURE;
} catch (const std::exception& e) {
    FATAL() << "Worker failed: " << e.what();
    return EXIT_FAILURE;
}
