#include "autocomplete.hpp"
#include "servers.hpp"
#include "config.hpp"
#include "templates.hpp"
#include "services.hpp"
#include "servers.hpp"
#include "utils/assert.hpp"

#include <algorithm>
#include <iostream>

void dropshell::autocomplete(const std::vector<std::string> &args)
{
    if (args.size() < 3) // dropshell autocomplete ???
    {
        autocomplete_list_commands();
        return;
    }

    ASSERT(args.size() >= 3);
    std::string cmd = args[2];

    // std::cout<<" cmd = ["<<cmd<<"]"<<std::endl;

    std::string noargcmds[] = {"templates","autocomplete_list_servers","autocomplete_list_services","autocomplete_list_commands"};
    if (std::find(std::begin(noargcmds), std::end(noargcmds), cmd) != std::end(noargcmds))
        return;

    if (!dropshell::gConfig().is_config_set())
        return; // can't help without working config.

    if (args.size()==3) // we have the command but nothing else.  dropshell autocomplete command <server>
    {
        auto servers = dropshell::get_configured_servers();
        for (const auto& server : servers) 
        std::cout << server.name << std::endl;
        return;
    }

    if (args.size()==4) // we have the command and the server.  dropshell autocomplete command server <service>
    {
        std::string server = args[3];

        if (cmd=="create-service")
        { // create-service <server> <template> <service>
            std::vector<template_info> templates;
            get_templates(templates);
            for (const auto& t : templates)
                std::cout << t.template_name << std::endl;
            return;
        }

        auto services = dropshell::get_server_services_info(server);
        for (const auto& service : services) 
            std::cout << service.service_name << std::endl;
        return;
    }

    if (args.size()==5) // we have the command and the server and the service.  dropshell autocomplete command server service_name <command?>
    { 
        std::string server_name = args[3];
        std::string service_name = args[4];
        if (cmd=="restore")
        {
            std::set<std::string> backups = dropshell::list_backups(server_name, service_name);
            for (auto backup : backups) 
                std::cout << backup << std::endl;
            return;
        }

        return; // no more autocompletion possible - don't know what the argument is for.
    }

    // args>5 - no more autocompletion possible - don't know what the argument is for.
    return; // catch-all.
}

void dropshell::autocomplete_list_commands()
{
    std::set<std::string> commands;
    dropshell::get_all_used_commands(commands);

// add in commmands hard-coded and handled in main
    commands.merge(std::set<std::string>{ 
        "help","init" // these are always available.
    });
    if (dropshell::gConfig().is_config_set()) 
        commands.merge(std::set<std::string>{
            "server","templates","create-service","create-template","create-server","edit","ssh",
            "list" // only if we have a config.
        });
    for (const auto& command : commands) {
        std::cout << command << std::endl;
    }
}

