# COMMON FUNCTIONS
# JDE
# 2025-05-03

# This file is available TO ***ALL*** templates, as ${AGENT_PATH}/_common.sh

# ----------------------------------------------------------------------------------------------------------

# summary of functions:
#   _die "message"                         : Prints an error message in red and exits with status code 1.
#   _grey_start                            : Switches terminal output color to grey.
#   _grey_end                              : Resets terminal output color from grey.
#   _create_and_start_container "<run_cmd>" <container_name> : Creates/starts a container, verifying it runs.
#   _create_folder <folder_path>           : Creates a directory if it doesn't exist (chmod 777).
#   _check_docker_installed               : Checks if Docker is installed, running, and user has permission. Returns 1 on failure.
#   _is_container_exists <container_name> : Checks if a container (any state) exists. Returns 1 if not found.
#   _is_container_running <container_name>: Checks if a container is currently running. Returns 1 if not running.
#   _get_container_id <container_name>    : Prints the ID of the named container.
#   _get_container_status <container_name>: Prints the status string of the named container.
#   _start_container <container_name>     : Starts an existing, stopped container.
#   _stop_container <container_name>      : Stops a running container.
#   _remove_container <container_name>    : Stops (if needed) and removes a container.
#   _get_container_logs <container_name>  : Prints the logs for a container.
#   _check_required_env_vars "VAR1" ...    : Checks if listed environment variables are set; calls _die() if any are missing.
#   _root_remove_tree <path>              : Removes a path using a root Docker container (for permissions).

# ----------------------------------------------------------------------------------------------------------

# Prints an error message in red and exits with status code 1.
_die() {
    echo -e "Error: $1"
    exit 1
}

# Creates/starts a container, verifying it runs.
_create_and_start_container() {
    if [ -z "$1" ] || [ -z "$2" ]; then
        _die "Template error: create_and_start_container <run_cmd> <container_name>"
    fi

    local run_cmd="$1"
    local container_name="$2"

    if _is_container_exists "$container_name"; then
        _is_container_running "$container_name" && return 0
        _start_container "$container_name"
    else
        $run_cmd
    fi

    if ! _is_container_running "$container_name"; then
        _die "Container ${container_name} failed to start"
    fi

    ID=$(_get_container_id "$container_name")
    echo "Container ${container_name} is running with ID ${ID}"
}

# Creates a directory if it doesn't exist (chmod 777).
_create_folder() {
    local folder="$1"
    if [ -d "$folder" ]; then
        return 0
    fi
    if ! mkdir -p "$folder"; then
        _die "Failed to create folder: $folder"
    fi
    chmod 777 "$folder"
    echo "Folder created: $folder"
}

# Checks if Docker is installed, running, and user has permission. Returns 1 on failure.
_check_docker_installed() {
    if ! command -v docker &> /dev/null; then
        echo "Docker is not installed"
        return 1
    fi

    # check if docker daemon is running
    if ! docker info &> /dev/null; then
        echo "Docker daemon is not running"
        return 1
    fi

    # check if user has permission to run docker
    if ! docker run --rm hello-world &> /dev/null; then
        echo "User does not have permission to run docker"
        return 1
    fi

    return 0
}

# Checks if a container (any state) exists. Returns 1 if not found.
_is_container_exists() {
    [ -n "${1:-}" ] || { echo "_is_container_exists: Container name is empty" >&2; return 1; }
    if ! docker ps -a --format "{{.Names}}" | grep -q "^$1$"; then
        return 1
    fi
    return 0
}

# Checks if a container is currently running. Returns 1 if not running.
_is_container_running() {
    [ -n "${1:-}" ] || { echo "_is_container_running: Container name is empty" >&2; return 1; }
    if ! docker ps --format "{{.Names}}" | grep -q "^$1$"; then
        return 1
    fi
    return 0
}

# Prints the ID of the named container.
_get_container_id() {
    docker ps --format "{{.ID}}" --filter "name=$1"
}

# Prints the status string of the named container.
_get_container_status() {
    docker ps --format "{{.Status}}" --filter "name=$1"
}

# Starts an existing, stopped container.
_start_container() {
    _is_container_exists "$1" || return 1
    _is_container_running "$1" && return 0
    docker start "$1"
}

# Stops a running container.
_stop_container() {
    _is_container_running "$1" || return 0;
    docker stop "$1"
}   

# Stops (if needed) and removes a container.
_remove_container() {
    _stop_container "$1"
    _is_container_exists "$1" || return 0;
    docker rm "$1"
}

# Prints the logs for a container.
_get_container_logs() {
    if ! _is_container_exists "$1"; then
        echo "Container $1 does not exist"
        return 1
    fi

    docker logs "$1"
}

# Checks if listed environment variables are set; calls _die() if any are missing.
_check_required_env_vars() {
    local required_vars=("$@")
    for var in "${required_vars[@]}"; do
        if [ -z "${!var:-}" ]; then
            _die "Required environment variable $var is not set"
        fi
    done
}

# Removes a path using a root Docker container (for permissions).
_root_remove_tree() {
    local to_remove="$1"
    parent=$(dirname "$to_remove")
    abs_parent=$(realpath "$parent")
    child=$(basename "$to_remove")
    docker run --rm -v "$abs_parent":/data alpine rm -rf "/data/$child"
}


# Load autocommands
source "${AGENT_PATH}/datacommands.sh"