#include "directories.hpp"
#include "config.hpp"
#include "server_env_manager.hpp"
#include <iostream>
#include <string>
#include <filesystem>

namespace fs = std::filesystem;

namespace dropshell {


namespace localfile {

    std::string dropshell_json() {
        // Try ~/.config/dropshell/dropshell.json
        std::string homedir = localpath::current_user_home();
        if (!homedir.empty()) {
            fs::path user_path = fs::path(homedir) / ".config" / "dropshell" /  "dropshell.json";
            return user_path.string();
        }
        return std::string();
    }

    std::string server_json(const std::string &server_name) {
        std::string serverpath = localpath::server(server_name);
        return (serverpath.empty() ? "" : (fs::path(serverpath) / "server.json").string());
    }

    std::string service_env(const std::string &server_name, const std::string &service_name) {
        std::string servicepath = localpath::service(server_name, service_name);
        return (servicepath.empty() ? "" : (fs::path(servicepath) / "service.env").string());
    }

    std::string template_info_env(const std::string &server_name, const std::string &service_name)
    {
        std::string servicepath = localpath::service(server_name, service_name);
        return (servicepath.empty() ? "" : (fs::path(servicepath) / ".template_info.env").string());
    }

} // namespace localfile


// ------------------------------------------------------------------------------------------

namespace localpath {
        std::string server(const std::string &server_name) {
            if (server_name.empty()) return "";
            for (std::filesystem::path dir : gConfig().get_local_server_definition_paths()) 
                if (fs::exists(dir / server_name))
                    return dir / server_name;
            return "";
        }

        std::string service(const std::string &server_name, const std::string &service_name) {
            std::string serverpath = localpath::server(server_name);
            return ((serverpath.empty() || service_name.empty()) ? "" : (serverpath+"/"+service_name));
        }

        std::string remote_versions(const std::string &server_name, const std::string &service_name)
        {
            std::string template_cache_path = gConfig().get_local_template_cache_path();
            return ((template_cache_path.empty() || service_name.empty()) ? "" : 
               (template_cache_path+"/remote_versions/"+service_name+".json"));
        }
        std::string local_bin(){
            return current_user_home() + "/.local/bin";
        }
        std::string current_user_home(){
            char * homedir = std::getenv("HOME");
            if (homedir)
            {
                std::filesystem::path homedir_path(homedir);
                return fs::canonical(homedir_path).string();
            }
            std::cerr << "Warning: Couldn't determine user directory" << std::endl;
            return std::string();
        }
} // namespace localpath

// ------------------------------------------------------------------------------------------

    // remote paths
    // DROPSHELL_DIR
    //   |-- service name
    //      |-- config
    //          |-- service.env
    //          |-- (user config files)
    //      |-- template
    //          |-- (script files)
    //      |-- backups


namespace remotefile {

    std::string service_env(const std::string &server_name, const std::string &service_name)
    {
        return remotepath::service_config(server_name, service_name) + "/service.env";
    }

}

namespace remotepath {
    std::string DROPSHELL_DIR(const std::string &server_name)
    {            
        return server_env_manager(server_name).get_DROPSHELL_DIR();
    }

    std::string services(const std::string &server_name)
    {
        std::string dsp = DROPSHELL_DIR(server_name);
        return (dsp.empty() ? "" : (dsp + "/services"));
    }

    std::string service(const std::string &server_name, const std::string &service_name)
    {
        std::string services_path = services(server_name);
        return (services_path.empty() ? "" : (services_path + "/" + service_name));
    }

    std::string service_config(const std::string &server_name, const std::string &service_name) 
    {
        std::string service_path = service(server_name, service_name);
        return (service_path.empty() ? "" : (service_path + "/config"));
    }

    std::string service_template(const std::string &server_name, const std::string &service_name) 
    {
        std::string service_path = service(server_name, service_name);
        return (service_path.empty() ? "" : (service_path + "/template"));
    }

    std::string backups(const std::string &server_name) 
    {
        std::string dsp = DROPSHELL_DIR(server_name);
        return (dsp.empty() ? "" : (dsp + "/backups"));
    }

    std::string service_env(const std::string &server_name, const std::string &service_name) 
    {
        std::string service_path = service_config(server_name, service_name);
        return (service_path.empty() ? "" : (service_path + "/service.env"));
    }
} // namespace remotepath


// ------------------------------------------------------------------------------------------
// Utility functions

std::string get_parent(const std::string &path)
{
    if (path.empty())
        return std::string();
    return fs::path(path).parent_path().string();
}

} // namespace dropshell
