#include "context.h"
#include "options.h"
#include "tool.h"

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/drive/firmware_updater/libs/config/include/config.h>

#include <maps/libs/common/include/exception.h>
#include <yandex/maps/wiki/common/string_utils.h>

#include <optional>
#include <sstream>
#include <string>

using namespace maps::fw_updater;
using storage::cli::Options;
using storage::cli::Command;

int main(int argc, const char** argv) try {
    maps::cmdline::Parser parser(Options::helpText(argv[0]));

    parser.section("Common options");
    auto configPath = parser.string("config")
        .help("path to firmware updater config");
    auto secretVersion = parser.string("secret-version")
        .help("version for secrets from yav.yandex-team.ru");
    auto logLevel = parser.string("log-level")
        .defaultValue("warning")
        .help("logging level, one of {debug|info|warning|error|fatal}");

    parser.section("Tool options");
    Options options(parser);
    parser.parse(argc, const_cast<char**>(argv));
    options.validate();

    maps::log8::setLevel(logLevel);

    const auto config = config::templateConfigFromCmdPath(secretVersion, configPath);
    storage::cli::Context context(config);

    auto command = options.command();
    switch(command) {
        case Command::Firmware:
            handleFirmwareCommand(context, options);
            break;
        case Command::FirmwareUpload:
            handleFirmwareUploadCommand(context, options);
            break;
        case Command::Rollout:
            handleRolloutCommand(context, options);
            break;
        case Command::DeviceBranch:
            handleDeviceBranchCommand(context, options);
            break;
    }

    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() << "Caught unknown exception";
    return EXIT_FAILURE;
}
