/*
 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
 *
 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
 *
*/
#include <atomic>
#include <boost/algorithm/string.hpp>
#include <docopt.h>
#include <iostream>
#include <optional>
#include <replxx.hxx>
#include <sstream>
#include "NETCONF_CLI_VERSION.h"
#include "interpreter.hpp"
#include "proxy_datastore.hpp"
#include "yang_schema.hpp"
#if defined(SYSREPO_CLI)
#include "sysrepo_access.hpp"
#define PROGRAM_NAME "sysrepo-cli"
static const auto usage = R"(CLI interface to sysrepo

Usage:
  sysrepo-cli [-d <datastore_target>]
  sysrepo-cli (-h | --help)
  sysrepo-cli --version

Options:
  -d <datastore_target>   can be "running", "startup" or "operational" [default: operational])";
#elif defined(YANG_CLI)
#include <boost/spirit/home/x3.hpp>
#include <filesystem>
#include "yang_access.hpp"
#define PROGRAM_NAME "yang-cli"
static const auto usage = R"(CLI interface for creating local YANG data instances

  The <schema_file_or_module_name> argument is treated as a file name if a file
  with such a path exists, otherwise it's treated as a module name. Search dirs
  will be used to find a schema for that module.

Usage:
  yang-cli [--configonly] [-s <search_dir>] [-e enable_features]... [-i data_file]... <schema_file_or_module_name>...
  yang-cli (-h | --help)
  yang-cli --version

Options:
  -s <search_dir>       Set search for schema lookup
  -e <enable_features>  Feature to enable after modules are loaded. This option can be supplied more than once. Format: <module_name>:<feature>
  -i <data_file>        File to import data from
  --configonly          Disable editing of operational data)";
#elif defined(NETCONF_CLI)
// FIXME: improve usage
static const auto usage = R"(CLI interface for NETCONF

Usage:
  netconf-cli [-v] [-d <datastore_target>] [-p <port>] <host>
  netconf-cli [-v] [-d <datastore_target>] --socket <path>
  netconf-cli (-h | --help)
  netconf-cli --version

Options:
  -v         enable verbose mode
  -p <port>  port number [default: 830]
  -d <datastore_target>   can be "running", "startup" or "operational" [default: operational])";
#include "cli-netconf.hpp"
#include "netconf_access.hpp"
#define PROGRAM_NAME "netconf-cli"
// FIXME: this should be replaced by C++20 std::jthread at some point
struct PoorMansJThread {
    ~PoorMansJThread()
    {
        if (thread.joinable()) {
            thread.join();
        }
    }
    std::thread thread;
};
#else
#error "Unknown CLI backend"
#endif

const auto HISTORY_FILE_NAME = PROGRAM_NAME "_history";

int main(int argc, char* argv[])
{
    auto args = docopt::docopt(usage,
                               {argv + 1, argv + argc},
                               true,
                               PROGRAM_NAME " " NETCONF_CLI_VERSION,
                               true);
    WritableOps writableOps = WritableOps::No;

    using replxx::Replxx;
    Replxx lineEditor;
    std::atomic<int> backendReturnCode = 0;

    // For some reason, GCC10 still needs [[maybe_unused]] because of conditional compilation...
    [[maybe_unused]] auto datastoreTarget = DatastoreTarget::Operational;
    if (const auto& ds = args["-d"]) {
        if (ds.asString() == "startup") {
            datastoreTarget = DatastoreTarget::Startup;
        } else if (ds.asString() == "running") {
            datastoreTarget = DatastoreTarget::Running;
        } else if (ds.asString() == "operational") {
            datastoreTarget = DatastoreTarget::Operational;
        } else {
            std::cerr << PROGRAM_NAME << ": unknown datastore target: " << ds.asString() << "\n";
            return 1;
        }
    }

    auto datastoreTargetString = args["-d"] ? args["-d"].asString() : std::string("operational");

#if defined(SYSREPO_CLI)
    auto datastore = std::make_shared<SysrepoAccess>();
    std::cout << "Connected to sysrepo [datastore target: " << datastoreTargetString << "]" << std::endl;
#elif defined(YANG_CLI)
    auto datastore = std::make_shared<YangAccess>();
    if (args["--configonly"].asBool()) {
        writableOps = WritableOps::No;
    } else {
        writableOps = WritableOps::Yes;
        std::cout << "ops is writable" << std::endl;
    }
    if (const auto& search_dir = args["-s"]) {
        datastore->addSchemaDir(search_dir.asString());
    }
    for (const auto& schemaFile : args["<schema_file_or_module_name>"].asStringList()) {
        if (std::filesystem::exists(schemaFile)) {
            datastore->addSchemaFile(schemaFile);
        } else if (schemaFile.find('/') == std::string::npos) { // Module names cannot have a slash
            datastore->loadModule(schemaFile);
        } else {
            std::cerr << "Cannot load YANG module " << schemaFile << "\n";
        }
    }
    if (const auto& enableFeatures = args["-e"]) {
        namespace x3 = boost::spirit::x3;
        auto grammar = +(x3::char_-":") >> ":" >> +(x3::char_-":");
        for (const auto& enableFeature : enableFeatures.asStringList()) {
            std::pair<std::string, std::string> parsed;
            auto it = enableFeature.begin();
            auto res = x3::parse(it, enableFeature.cend(), grammar, parsed);
            if (!res || it != enableFeature.cend()) {
                std::cerr << "Error parsing feature enable flags: " << enableFeature << "\n";
                return 1;
            }
            try {
                datastore->enableFeature(parsed.first, parsed.second);
            } catch (std::runtime_error& ex) {
                std::cerr << ex.what() << "\n";
                return 1;
            }
        }
    }
    if (const auto& dataFiles = args["-i"]) {
        for (const auto& dataFile : dataFiles.asStringList()) {
            datastore->addDataFile(dataFile);
        }
    }
#elif defined(NETCONF_CLI)
    auto verbose = args.at("-v").asBool();
    if (verbose) {
        NetconfAccess::setNcLogLevel(NC_VERB_DEBUG);
    }

    SshProcess process;
    PoorMansJThread processWatcher;
    std::shared_ptr<NetconfAccess> datastore;

    if (args.at("--socket").asBool()) {
        try {
            datastore = std::make_shared<NetconfAccess>(args.at("<path>").asString());
        } catch (std::runtime_error& ex) {
            std::cerr << "UNIX socket connection failed: " << ex.what() << std::endl;
            return 1;
        }
    } else {
        try {
            process = sshProcess(args.at("<host>").asString(), args.at("-p").asString());
            processWatcher.thread = std::thread{std::thread{[&process, &lineEditor, &backendReturnCode] () {
                process.process.wait();
                backendReturnCode = process.process.exit_code();
                // CTRL-U clears from the cursor to the start of the line
                // CTRL-K clears from the cursor to the end of the line
                // CTRL-D send EOF
                lineEditor.emulate_key_press(replxx::Replxx::KEY::control('U'));
                lineEditor.emulate_key_press(replxx::Replxx::KEY::control('K'));
                lineEditor.emulate_key_press(replxx::Replxx::KEY::control('D'));
            }}};
            datastore = std::make_shared<NetconfAccess>(process.std_out.native_source(), process.std_in.native_sink());
        } catch (std::runtime_error& ex) {
            std::cerr << "SSH connection failed: " << ex.what() << std::endl;
            return 1;
        }
    }
    std::cout << "Connected via NETCONF [datastore target: " << datastoreTargetString << "]" << std::endl;
#else
#error "Unknown CLI backend"
#endif

    datastore->setTarget(datastoreTarget);

#if defined(SYSREPO_CLI) || defined(NETCONF_CLI)
    auto createTemporaryDatastore = [](const std::shared_ptr<DatastoreAccess>& datastore) {
        return std::make_shared<YangAccess>(std::static_pointer_cast<YangSchema>(datastore->schema()));
    };
#elif defined(YANG_CLI)
    auto createTemporaryDatastore = [](const std::shared_ptr<DatastoreAccess>&) {
        return nullptr;
    };
#endif

    ProxyDatastore proxyDatastore(datastore, createTemporaryDatastore);
    auto dataQuery = std::make_shared<DataQuery>(*datastore);
    Parser parser(datastore->schema(), writableOps, dataQuery);

    lineEditor.bind_key(Replxx::KEY::meta(Replxx::KEY::BACKSPACE), [&lineEditor](const auto& code) {
        return lineEditor.invoke(Replxx::ACTION::KILL_TO_BEGINING_OF_WORD, code);
    });
    lineEditor.bind_key(Replxx::KEY::control('W'), [&lineEditor](const auto& code) {
        return lineEditor.invoke(Replxx::ACTION::KILL_TO_WHITESPACE_ON_LEFT, code);
    });

    lineEditor.set_word_break_characters("\t _[]/:'\"=-%");

    lineEditor.set_completion_callback([&parser](const std::string& input, int& context) {
        std::stringstream stream;
        auto completions = parser.completeCommand(input, stream);

        std::vector<replxx::Replxx::Completion> res;
        std::copy(completions.m_completions.begin(), completions.m_completions.end(), std::back_inserter(res));
        context = completions.m_contextLength;
        return res;
    });

    std::optional<std::string> historyFile;
    if (auto xdgHome = getenv("XDG_DATA_HOME")) {
        historyFile = std::string(xdgHome) + "/" + HISTORY_FILE_NAME;
    } else if (auto home = getenv("HOME")) {
        historyFile = std::string(home) + "/.local/share/" + HISTORY_FILE_NAME;
    }

    if (historyFile) {
        lineEditor.history_load(historyFile.value());
    }

    while (backendReturnCode == 0) {
        auto fullContextPath = parser.currentNode();
        std::string prompt;
        if (auto activeRpcPath = proxyDatastore.inputDatastorePath()) {
            auto rpcPrefixLength = activeRpcPath->size();
            prompt = "(prepare: " + *activeRpcPath + ") " + fullContextPath.substr(rpcPrefixLength);
        } else {
            prompt = fullContextPath;
        }

        prompt += "> ";

        auto line = lineEditor.input(prompt);
        if (!line) {
            // If user pressed CTRL-C to abort the line, errno gets set to EAGAIN.
            // If user pressed CTRL-D (for EOF), errno doesn't get set to EAGAIN, so we exit the program.
            // I have no idea why replxx uses errno for this.
            if (errno == EAGAIN) {
                continue;
            } else {
                break;
            }
        }

        std::locale C_locale("C");
        std::string_view view{line};
        if (std::all_of(view.begin(), view.end(),
                        [C_locale](const auto c) { return std::isspace(c, C_locale);})) {
            continue;
        }

        try {
            command_ cmd = parser.parseCommand(line, std::cout);
            boost::apply_visitor(Interpreter(parser, proxyDatastore), cmd);
        } catch (InvalidCommandException& ex) {
            std::cerr << ex.what() << std::endl;
        } catch (DatastoreException& ex) {
            std::cerr << ex.what() << std::endl;
        } catch (std::runtime_error& ex) {
            std::cerr << ex.what() << std::endl;
        } catch (std::logic_error& ex) {
            std::cerr << ex.what() << std::endl;
        }

        lineEditor.history_add(line);
    }

    if (historyFile) {
        lineEditor.history_save(historyFile.value());
    }

    return backendReturnCode;
}
