/*
 * 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>]
  sysrepo-cli (-h | --help)
  sysrepo-cli --version

Options:
  -d <datastore>   can be "running" or "startup" [default: running])";
#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] [-p <port>] <host>
  netconf-cli [-v] --socket <path>
  netconf-cli (-h | --help)
  netconf-cli --version

Options:
  -v         enable verbose mode
  -p <port>  port number [default: 830]
)";
#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;

#if defined(SYSREPO_CLI)
    auto datastoreType = Datastore::Running;
    if (const auto& ds = args["-d"]) {
        if (ds.asString() == "startup") {
            datastoreType = Datastore::Startup;
        } else if (ds.asString() == "running") {
            datastoreType = Datastore::Running;
        } else {
            std::cerr << PROGRAM_NAME << ": unknown datastore: " << ds.asString() << "\n";
            return 1;
        }
    }
    auto datastore = std::make_shared<SysrepoAccess>(datastoreType);
    std::cout << "Connected to sysrepo [datastore: " << (datastoreType == Datastore::Startup ? "startup" : "running") << "]" << 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;
        }
    }
#else
#error "Unknown CLI backend"
#endif

#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;
}
