#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_env() {
    // Try ~/.config/dropshell/dropshell.env
    const char* home = std::getenv("HOME");
    if (home) {
        fs::path user_path = fs::path(home) / ".config" / "dropshell" /  "dropshell.env";
        return user_path.string();
    }
    std::cerr << "Warning: Couldn't determine user directory" << std::endl;
    return std::string();
    }

    std::string server_env(const std::string &server_name) {
        if (server_name.empty())
            return std::string();
        std::string serverpath = localpath::server(server_name);
        if (serverpath.empty()) 
            return std::string();
        return (fs::path(serverpath) / "server.env").string();
    }

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

    std::string service_hash(const std::string &server_name, const std::string &service_name) {
        std::string config_path = localpath::config();
        if (server_name.empty() || service_name.empty() || config_path.empty())
            return std::string();
        return (fs::path(config_path) / ".remote_versions" / server_name / (service_name + ".hash.env")).string();
    }

} // namespace localfile


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

namespace localpath {
        // /opt/dropshell/templates
        std::string system_templates() {
            return "/opt/dropshell/templates";
        }

        // configured by user - defaults to first config_path/backups.
        std::string backups_path() {
            return gConfig().get_local_backup_path();
        }

        int num_config_directories() {
            return gConfig().get_local_config_directories().size();
        }

        std::string config(int index) {
            return (num_config_directories()>index) ? gConfig().get_local_config_directories()[index] : "";
        }

        std::string config_templates(int index) {
            return (num_config_directories()>index) ? (gConfig().get_local_config_directories()[index]+"/templates") : "";
        }

        std::string config_servers(int index) {
            return (num_config_directories()>index) ? (gConfig().get_local_config_directories()[index]+"/servers") : "";
        }

        std::string server(const std::string &server_name) {
            for (auto &dir : gConfig().get_local_config_directories()) 
                if (fs::exists(dir + "/servers/" + server_name))
                    return dir + "/servers/" + 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() ? "" : (serverpath+"/"+service_name));
        }
} // 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(std::string path)
{
    if (path.empty())
        return std::string();
    return fs::path(path).parent_path().string();
}

} // namespace dropshell
