// server_env.hpp
//
// read the server.env file and provide a class to access the variables

#ifndef __SERVER_ENV_HPP
#define __SERVER_ENV_HPP

#include <string>
#include <map>
#include <memory>
#include "utils/envmanager.hpp"
namespace dropshell {

// class to hold a command to run on the remote server.
class sCommand {
    public:
        sCommand(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> & env_vars) : 
            mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars) {}
        sCommand(std::string command_to_run) : 
            mDir(""), mCmd(command_to_run), mVars({}) {}


        std::string get_directory_to_run_in() const { return mDir; }
        std::string get_command_to_run() const { return mCmd; }
        const std::map<std::string, std::string>& get_env_vars() const { return mVars; }

        void add_env_var(const std::string& key, const std::string& value) { mVars[key] = value; }

        std::string construct_safecmd() const;

    private:
        std::string mDir;
        std::string mCmd;
        std::map<std::string, std::string> mVars;
};

std::string makesafecmd(const std::string& command);

// reads path / server.env and provides a class to access the variables.
// each env file is required to have the following variables:
// SSH_HOST
// SSH_USER
// SSH_PORT
// the following replacements are made in the values:
// ${USER} -> the username of the user running dropshell
class server_env_manager {
    public:
        server_env_manager(const std::string& server_name);
        std::string get_variable(const std::string& name) const;

        // trivial getters.
        const std::map<std::string, std::string>& get_variables() const { return variables; }
        std::string get_SSH_HOST() const { return get_variable("SSH_HOST"); }
        std::string get_SSH_USER() const { return get_variable("SSH_USER"); }
        std::string get_SSH_PORT() const { return get_variable("SSH_PORT"); }
        std::string get_DROPSHELL_DIR() const { return get_variable("DROPSHELL_DIR"); }
        bool is_valid() const { return mValid; }

// helper functions
    public:
        bool check_remote_dir_exists(const std::string &dir_path) const;
        bool check_remote_file_exists(const std::string& file_path) const;
        bool check_remote_items_exist(const std::vector<std::string>& file_paths) const;

        bool run_remote_template_command(const std::string& service_name, const std::string& command, std::vector<std::string> args, bool silent=false) const;
        bool run_remote_template_command_and_capture_output(const std::string& service_name, const std::string& command, std::vector<std::string> args, std::string & output, bool silent=false) const;

    public:
        bool execute_ssh_command(const sCommand& command) const;
        bool execute_ssh_command_and_capture_output(const sCommand& command, std::string & output) const;

        static bool execute_local_command(const sCommand& command);
        static bool execute_local_command_and_capture_output(const sCommand& command, std::string & output);

    private:
        std::string construct_ssh_cmd() const;
        std::string construct_standard_command_run_cmd(const std::string& service_name, const std::string& command, std::vector<std::string> args, bool silent) const;

    private:
        void get_all_service_env_vars(const std::string& service_name, std::map<std::string, std::string> & all_env_vars) const;

    private:
        std::string mServer_name;
        std::map<std::string, std::string> variables;
        bool mValid;
        std::unique_ptr<envmanager> m_env_manager;
};

} // namespace dropshell


#endif // __SERVER_ENV_HPP  