#!/usr/bin/bash

# Shared color definitions and utility functions for demo scripts
# Source this file in other scripts with: source "$(dirname "$0")/colors.sh"

# https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
# FG Colors
_fg_black='\033[0;30m'
_fg_red='\033[0;31m'
_fg_green='\033[0;32m'
_fg_yellow='\033[0;33m'
_fg_blue='\033[0;34m'
_fg_magenta='\033[0;35m'
_fg_cyan='\033[0;36m'
_fg_white='\033[0;37m'
_fg_bright_black='\033[0;90m'
_fg_gray=$_fg_bright_black
_fg_bright_red='\033[0;91m'
_fg_bright_green='\033[0;92m'
_fg_bright_yellow='\033[0;93m'
_fg_bright_blue='\033[0;94m'
_fg_bright_magenta='\033[0;95m'
_fg_bright_cyan='\033[0;96m'
_fg_bright_white='\033[0;97m'

#BG Colors
_bg_black='\033[0;40m'
_bg_red='\033[0;41m'
_bg_green='\033[0;42m'
_bg_yellow='\033[0;43m'
_bg_blue='\033[0;44m'
_bg_magenta='\033[0;45m'
_bg_cyan='\033[0;46m'
_bg_white='\033[0;47m'
_bg_bright_black='\033[0;100m'
_bg_bright_red='\033[0;101m'
_bg_bright_green='\033[0;102m'
_bg_bright_yellow='\033[0;103m'
_bg_bright_blue='\033[0;104m'
_bg_bright_magenta='\033[0;105m'
_bg_bright_cyan='\033[0;106m'
_bg_bright_white='\033[0;107m'

# Text styles
_bold='\033[1m'
_dim='\033[2m'
_italic='\033[3m'
_underline='\033[4m'
_blink='\033[5m'
_reverse='\033[7m'

# No Color
NC='\033[0m'

LINE_LENGTH=${LINE_LENGTH:-80}

# Semantic color definitions (configurable)
C_HEADER=${C_HEADER:-$_fg_cyan}
C_HEADER_TEXT=${C_HEADER_TEXT:-$_fg_white$_bold}
C_SUCCESS=${C_SUCCESS:-$_fg_green}
C_ERROR=${C_ERROR:-$_fg_red}
C_WARNING=${C_WARNING:-$_fg_yellow}
C_INFO=${C_INFO:-$_fg_blue}
C_DEBUG=${C_DEBUG:-$_fg_magenta}
C_COMMAND=${C_COMMAND:-$_fg_red}
C_COMMAND_TEXT=${C_COMMAND_TEXT:-$_fg_white}
C_DEBUG_TEXT=${C_DEBUG_TEXT:-$_fg_gray$_italic}
C_TEXT=${C_TEXT:-$_fg_yellow}
C_BULLET=${C_BULLET:-$_fg_green}
C_PROMPT=${C_PROMPT:-$_dim$_fg_cyan}
C_INTERACTIVE=${C_INTERACTIVE:-$_fg_magenta}
C_SEPARATOR=${C_SEPARATOR:-$_dim$_fg_cyan}

# Configurable symbols
S_BULLET=${S_BULLET:-"➤"}
S_SUCCESS=${S_SUCCESS:-"✓"}
S_INFO=${S_INFO:-"ℹ"}
S_WARNING=${S_WARNING:-"⚠"}
S_ERROR=${S_ERROR:-"✗"}
S_DEBUG=${S_DEBUG:-"$"}
S_COMMAND=${S_COMMAND:-"$"}

_script=false

# Print debug info and exit with error
_debug_info() {
    echo "DEBUG: $DEBUG"
    echo "DRYRUN: $DRYRUN"
    echo "EXPORT_FORMAT: $EXPORT_FORMAT"
    echo "QUIET: $QUIET"
    echo "CLEAN: $CLEAN"
    echo "OFFLINE: $OFFLINE"
    echo "GOON: $GOON"
    exit 1
}

_trim() {
    local var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"
    printf '%s' "$var"
}

_sequence() {
    local length="$1"
    if [[ -z "$length" ]]; then
        length="$LINE_LENGTH"
    fi
    for ((i = 0; i < length; i++)); do
        printf '='
    done
}

_check_env() {
    if [[ "$EXPORT" = "true" ]]; then
        _print_warning "EXPORT is deprecated, use EXPORT_FORMAT instead"
    fi

    if [[ -n "$EXPORT_FORMAT" ]]; then
        # EXPORT_FORMAT must be 'sh' or 'md'
        if [[ "$EXPORT_FORMAT" != "sh" ]] && [[ "$EXPORT_FORMAT" != "md" ]]; then
            [[ "$_script" = true ]] && \
                _print_error "--export takes 'sh' or 'md', got: '$EXPORT_FORMAT'" && \
                usage
            _print_error "EXPORT_FORMAT must be 'sh' or 'md', got: '$EXPORT_FORMAT'"
            _debug_info
        fi

        # EXPORT_FORMAT can't be set with QUIET or DRYRUN
        # exit if set together
        #
        # EXPORT_FORMAT can't be set with EXPORT
        # exit if set together
        if [[ "$QUIET" = "true" ]] || [[ "$DRYRUN" = "true" ]]; then
            temp_export_format="$EXPORT_FORMAT"
            temp_quiet="$QUIET"
            temp_dryrun="$DRYRUN"
            unset EXPORT_FORMAT
            unset QUIET
            unset DRYRUN
            [[ "$_script" = true ]] && \
                _print_error "--export can't be set with --quiet or --dryrun" && \
                usage
            _print_error "EXPORT_FORMAT can't be set with QUIET or DRYRUN"
            EXPORT_FORMAT="$temp_export_format"
            QUIET="$temp_quiet"
            DRYRUN="$temp_dryrun"
            _debug_info
        fi
    fi
    if [[ "$CLEAN" = true ]] && [[ "$OFFLINE" = true ]]; then
        [[ "$_script" = true ]] && \
            _print_error "--clean and --offline can't be set together" && \
            usage
        _print_error "CLEAN and OFFLINE can't be set together"
        _debug_info
    fi
}

_check_env

_export_sh_intestation() {
    echo "#!/bin/bash"
    echo
}

_export_intestation() {
    [[ -z "$EXPORT_FORMAT" ]]
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_intestation && return
    [[ "$EXPORT_FORMAT" = "md" ]] && return
}

# Global history file for demo commands
_demo_histfile=$(mktemp)

_print_sigint_ctrl_c() {
    if [[ \
        "$EXPORT_FORMAT" = "sh" || \
        "$EXPORT_FORMAT" = "md" \
        ]]; then
        : # do nothing
    elif [[ "$QUIET" = "true" ]]; then
        : # do nothing
    else
        echo -e "\n${C_INTERACTIVE}Ctrl+C detected \
- press Ctrl+C again within 2 seconds to exit demo${NC}"
    fi
}

_print_entering_bash() {
    [[ -n "$EXPORT_FORMAT" ]] && return
    [[ "$QUIET" = "true" ]] && return
    echo -e "${C_INTERACTIVE}Entering bash...${NC}\n"
}

_print_exiting_bash() {
    if [[ \
        "$EXPORT_FORMAT" = "sh" || \
        "$EXPORT_FORMAT" = "md" \
        ]]; then
        : # do nothing
    elif [[ "$QUIET" = "true" ]]; then
        : # do nothing
    else
        echo -e "${C_INTERACTIVE}Exiting bash...${NC}\n"
    fi
}

_print_press_enter_to_continue() {
    [[ "$EXPORT_FORMAT" = "sh" ]] || [[ "$EXPORT_FORMAT" = "md" ]] && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_PROMPT}Press Enter to continue...${NC}"
}

_print_header() {
    [[ "$EXPORT_FORMAT" = "sh" ]] && _export_sh_header "$@" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && _export_md_header "$@" && return
    [[ "$QUIET" = "true" ]] && return

    # the first argument is the header level and it's internal only
    shift
    local header_string="$*"
    local header_length=${#header_string}
    if (( header_length + 2 < LINE_LENGTH )); then
        echo -e "${C_HEADER}$(_sequence $((header_length + 2)))${NC}"
        echo -e " ${C_HEADER_TEXT}$header_string${NC}"
        echo -e "${C_HEADER}$(_sequence $((header_length + 2)))${NC}"
    else
        echo -e "${C_HEADER}$(_sequence "$LINE_LENGTH")${NC}"
        echo "$header_string" | fold -s -w $((LINE_LENGTH - 2)) | while IFS= read -r line; do
            echo -e "${C_HEADER_TEXT}$( _trim "$line" )${NC}"
        done
        echo -e "${C_HEADER}$(_sequence "$LINE_LENGTH")${NC}"
    fi
}

_print_first_line() {
    # Print the first line. Handle exporting and quiet
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "$@" && return

    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "$@" && return

    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_BULLET}${S_BULLET}${NC} ${C_TEXT}$*${NC}"
}


_print_line() {
    # Print a line. Handle exporting and quiet
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "$@" && return

    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "$@" && return

    [[ "$QUIET" = "true" ]] || \
        echo -e "  ${C_TEXT}$*${NC}"
}

_print_newline() {
    # Print a newline if not exporting or quiet
    [[ "$QUIET" = "true" ]] && return
    echo
}

_print_lines() {
    local first_line=true
    echo "$1" | fold -s -w "$LINE_LENGTH" | while IFS= read -r line; do
        if [[ "$first_line" = true ]]; then
            _print_first_line "$(_trim "$line")"
            first_line=false
        else
            _print_line "$(_trim "$line")"
        fi
    done
    _print_newline

}

_print_lines_preserve_indent() {
    local first_line=true
    while IFS= read -r line; do
        # trim trailing whitespace only — preserve leading spaces
        line="${line%"${line##*[![:space:]]}"}"
        if [[ "$first_line" = true ]]; then
            _print_first_line "$line"
            first_line=false
        else
            _print_line "$line"
        fi
    done <<< "$1"
    _print_newline
}

# Sentinels set by _parse_p_flags — consumed immediately by the caller
_P_MD=false
_P_SH=false
_P_DEMO=false
_P_SHIFT=0
_P_PRESERVE_INDENT=false

_parse_p_flags() {
    # Parse --markdown / --shell / --demo / --preserve-indent from "$@".
    # Sets _P_MD, _P_SH, _P_DEMO, _P_SHIFT, _P_PRESERVE_INDENT in global scope.
    # Caller must: shift "$_P_SHIFT" after calling this.
    _P_MD=false; _P_SH=false; _P_DEMO=false; _P_SHIFT=0; _P_PRESERVE_INDENT=false
    local _any=false
    while [[ "${1-}" == --markdown || "${1-}" == --shell || "${1-}" == --demo || "${1-}" == --preserve-indent ]]; do
        case "$1" in
            --markdown)        _P_MD=true;             _any=true ;;
            --shell)           _P_SH=true;             _any=true ;;
            --demo)            _P_DEMO=true;            _any=true ;;
            --preserve-indent) _P_PRESERVE_INDENT=true ;;
        esac
        shift
        ((_P_SHIFT++))
    done
    # No flags given → all three channels active (default / backward-compat)
    if [[ "$_any" = false ]]; then
        _P_MD=true; _P_SH=true; _P_DEMO=true
    fi
}

_targeted_print() {
    # Gate a print call by output channel before dispatching.
    # Args: <want_md> <want_sh> <want_demo> <inner_fn> [inner_fn_args...]
    local _want_md="$1" _want_sh="$2" _want_demo="$3" _fn="$4"
    shift 4

    [[ "$EXPORT_FORMAT" = "md" && "$_want_md" = false ]] && return
    [[ "$EXPORT_FORMAT" = "sh" && "$_want_sh" = false ]] && return
    [[ -z "$EXPORT_FORMAT"    && "$_want_demo" = false ]] && return

    "$_fn" "$@"
}

_clear() {
    # Print a clear screen if not exporting or quiet
    [[ "$EXPORT_FORMAT" = "sh" || \
       "$EXPORT_FORMAT" = "md" || \
       "$QUIET" = "true" ]] && return
    clear
}

_print_success() {
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "$@" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "$@" && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_SUCCESS}${S_SUCCESS} $*${NC}\n"
}

_print_error() {
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "ERR: $*" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "ERR: $*" && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_ERROR}${S_ERROR} $*${NC}\n"
}

_print_warning() {
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "WRN: $*" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "WRN: $*" && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_WARNING}${S_WARNING} $*${NC}\n"
}

_print_info() {
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "INF: $*" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "INF: $*" && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_INFO}${S_INFO} $*${NC}"
}

_print_separator() {
    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_comment "----------------------------------------" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_comment "---" && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_SEPARATOR}----------------------------------------${NC}"
}

_print_debug_short_separator() {
    # Print debug short separator if DEBUG is true
    # Return 1 otherwise
    [[ "$DEBUG" = "true" ]] && \
        echo -e "${C_DEBUG}---${NC}"
}

_print_command() {
    # Print command with $ in front
    # if EXPORT is true, print the command as a comment
    # if QUIET is true, do not print the command
    # if DRYRUN is true, print the command
    # _print_command will understand the EXPORT, QUIET, and DRYRUN vars

    # Examples:
    # _print_command "echo 'This is a command'"
    # $ echo 'This is a command'
    # EXPORT_FORMAT='sh' _print_command "echo 'This is a command'"
    # # echo 'This is a command'
    # QUIET=true _print_command "echo 'This is a command'"
    # DRYRUN=true _print_command "echo 'This is a command'"
    # echo 'This is a command'

    [[ "$EXPORT_FORMAT" = "sh" ]] && \
        _export_sh_command "$@" && return
    [[ "$EXPORT_FORMAT" = "md" ]] && \
        _export_md_command "$@" && return
    [[ "$QUIET" = "true" ]] || \
        echo -e "${C_COMMAND}${S_COMMAND}${NC} ${C_COMMAND_TEXT}$*${NC}"
}

_print_debug() {
    # Print debug message if DEBUG is true
    # Return 1 otherwise
    [[ "$DEBUG" = "true" ]] && \
        echo -e "${C_DEBUG}${S_DEBUG}${NC} ${C_DEBUG_TEXT}$*${NC}"
}

# Signal handling for Ctrl+C
handle_sigint() {
    _print_sigint_ctrl_c

    # Temporarily change trap to exit on second Ctrl+C
    trap 'echo -e "\n${C_ERROR}Double Ctrl+C \
- exiting demo${NC}"; exit 130' SIGINT

    # Wait 2 seconds for second Ctrl+C, then enter interactive mode
    sleep 2
    trap 'handle_sigint' SIGINT
    _print_entering_bash
    b
    _print_press_enter_to_continue
}

# --- --- --- Export functions --- --- ---

# --- --- Export functions for markdown --- ---
_export_md_comment() {
    # Export input as a comment for markdown
    #
    # Example:
    # _export_md_comment "This is a comment"
    # # This is a comment
    if [[ "$_P_PRESERVE_INDENT" = true ]]; then
        while IFS= read -r line; do
            # trim trailing whitespace only — preserve leading spaces
            line="${line%"${line##*[![:space:]]}"}"
            echo "$line"
        done <<< "$*"
    else
        echo "$*" | fold -s -w "$LINE_LENGTH"
    fi
}

_export_md_command() {
    # Export input as a command for markdown
    #
    # Example:
    # _export_md_command "echo 'This is a command'"
    # ```bash
    # echo 'This is a command'
    # ```
    echo "\`\`\`bash"
    echo "$*"
    echo "\`\`\`"
    echo
}

_export_md_header() {
    # Export input as a header for markdown
    #
    # Example:
    # _export_md_header "This is a header"
    range="$1"
    for ((i=0; i<range; i++)); do
        echo -n "#"
    done
    echo -n " "
    shift
    echo "$*"
    echo
}

# --- --- --- Export functions for shell --- --- ---
_export_sh_comment() {
    # Export input as a comment for shell
    #
    # Example:
    # _export_sh_comment "This is a comment"
    # # This is a comment
    echo "$*" | fold -s -w "$LINE_LENGTH" | while IFS= read -r line; do
        if [[ "$_P_PRESERVE_INDENT" = true ]]; then
            line="${line%"${line##*[![:space:]]}"}"
        else
            line="$(_trim "$line")"
        fi
        echo "# $line"
    done
}

_export_sh_command() {
    # Export input as a command for shell
    #
    # Example:
    # _export_sh_command "echo 'This is a command"
    # echo 'This is a command'
    echo "$*"
    echo
}

_export_sh_header() {
    # Export input as a header for shell
    #
    # Example:
    # _export_sh_header "This is a header"
    # # ========================================"
    # #  This is a header
    # # ========================================"
    shift
    echo "# $(_sequence)"
    echo "# $1"
    echo "# $(_sequence)"
    echo
}

# Set up the trap
trap 'handle_sigint' SIGINT

# Function to print colored headers

h1() {
    if [[ "$QUIET" != "true" ]]; then
        _clear
        _print_header "1" "$@"
    fi
}

h2() {
    if [[ "$QUIET" != "true" ]]; then
        _print_header "2" "$@"
    fi
}

h3() {
    if [[ "$QUIET" != "true" ]]; then
        _print_header "3" "$@"
    fi
}

h4() {
    if [[ "$QUIET" != "true" ]]; then
        _print_header "4" "$@"
    fi
}

h5() {
    if [[ "$QUIET" != "true" ]]; then
        _print_header "5" "$@"
    fi
}

h6() {
    if [[ "$QUIET" != "true" ]]; then
        _print_header "6" "$@"
    fi
}


h() {
    h1 "$@"
}

hh() {
    h2 "$@"
}

hhh() {
    h3 "$@"
}

hhhh() {
    h4 "$@"
}

hhhhh() {
    h5 "$@"
}

hhhhhh() {
    h6 "$@"
}


# print a debug message
d() {
    _print_debug "$@"
}

# Function to print step messages
p() {
    _parse_p_flags "$@"
    shift "$_P_SHIFT"
    local _fn=_print_lines
    [[ "$_P_PRESERVE_INDENT" = true ]] && _fn=_print_lines_preserve_indent
    _targeted_print "$_P_MD" "$_P_SH" "$_P_DEMO" "$_fn" "$@"
}

# Function to print success messages
ps() {
    _parse_p_flags "$@"
    shift "$_P_SHIFT"
    _targeted_print "$_P_MD" "$_P_SH" "$_P_DEMO" _print_success "$@"
}

# Function to print error messages
pe() {
    _parse_p_flags "$@"
    shift "$_P_SHIFT"
    _targeted_print "$_P_MD" "$_P_SH" "$_P_DEMO" _print_error "$@"
}

# Function to print warning messages
pw() {
    _parse_p_flags "$@"
    shift "$_P_SHIFT"
    _targeted_print "$_P_MD" "$_P_SH" "$_P_DEMO" _print_warning "$@"
}

# Function to print info messages
pi() {
    _parse_p_flags "$@"
    shift "$_P_SHIFT"
    _targeted_print "$_P_MD" "$_P_SH" "$_P_DEMO" _print_info "$@"
}

# Function to print section separators
p-() {
    _parse_p_flags "$@"
    _targeted_print "$_P_MD" "$_P_SH" "$_P_DEMO" _print_separator
}

# Function to print command in red and execute it
# put a newline at the end
e() {
    # Print command and run it
    # if EXPORT_FORMAT is sh or md, just print the command
    # if QUIET is true, do not print the command but still run it
    # if DRYRUN is true, print the command do not run it
    # _print_command will understand the EXPORT, QUIET, and DRYRUN vars
    _print_command "$1"
    if [[ \
        "$EXPORT_FORMAT" = "sh" || \
        "$EXPORT_FORMAT" = "md" || \
        "$DRYRUN" = "true" \
        ]]; then
        return
    fi

    # Append command to global history file
    echo "$1" >> "$_demo_histfile"

    if [[ "$QUIET" = "true" ]]; then
        # run command and redirect its output to /dev/null
        bash -c "$@" >/dev/null 2>&1
    else
        # Execute with _histfile set
        bash -c "$@"
    fi
    local exit_code=$?
    _print_newline
    return $exit_code
}

# Function to print command in red and execute it with timeout
et() {
    _print_command "$1"
    if [[ \
        "$EXPORT_FORMAT" = "sh" || \
        "$EXPORT_FORMAT" = "md" || \
        "$DRYRUN" = "true" \
        ]]; then
        return
    fi

    local timeout_duration="${2:-30}"  # Default 30 seconds

    # Append command to global history file
    echo "$1" >> "$_demo_histfile"

    if [[ "$QUIET" = "true" ]]; then
        # run command and redirect its output to /dev/null
        timeout "$timeout_duration" bash -c "$@" 2>&1 /dev/null
    else
        timeout "$timeout_duration" bash -c "$@"
    fi
    local exit_code=$?
    _print_newline
    # if (( exit_code == 124 )); then
    #     pw "Command timed out after ${timeout_duration} seconds"
    # fi
}

ed() {
    #_print_debug_short_separator
    _print_debug "$1"
    #_print_debug_short_separator
    if [[ "$DEBUG" = "true" ]]; then
        echo "$1" >> "$_demo_histfile"

        bash -c "$@"
        local exit_code=$?
        _print_newline
        return $exit_code
    fi
}
# Function to pause demo execution based on GOON variable
w() {
    local timeout="$1"

    if [[ "${GOON:-false}" = "true" ]]; then
        # If GOON is true, continue without pausing
        return
    elif [[ \
        "$EXPORT_FORMAT" = "sh" || \
        "$EXPORT_FORMAT" = "md" \
        ]]; then
        return # do nothing
    elif [[ "$QUIET" = "true" ]]; then
        : # do nothing
    else
        _print_press_enter_to_continue
    fi

    if [[ -n "$timeout" ]] 2>/dev/null; then
        # Wait with timeout - user can press Enter to continue early
        read -r -t "$timeout"
    else
        # Wait indefinitely for user input
        read -r
    fi
}

b() {
    if [[ \
        "$EXPORT_FORMAT" = "sh" || \
        "$EXPORT_FORMAT" = "md" || \
        "$DRYRUN" = "true" \
        ]]; then
        : # do nothing
    elif [[ "$QUIET" = "true" ]]; then
        : # do nothing
    elif [[ "$GOON" = "true" ]]; then
        : # do nothing
    else
        if [[ -z "$_demo_name" ]]; then
            _demo='demo'
        else
            _demo=$_demo_name
        fi
        PS1="\[\[${C_INTERACTIVE}\]($_demo) \$ \[${NC}\]\]" \
            bash --rcfile <(
            echo "HISTFILE=\"$_demo_histfile\""
            echo "history -c"
            echo "history -r"
            echo "set +h"
            echo "trap 'history -w \"$_demo_histfile\"' EXIT"
            echo "# Load bash completion"
            echo "if [ -f /etc/bash_completion ]; then"
            echo "    . /etc/bash_completion"
            echo "elif [ -f /usr/share/bash-completion/bash_completion ]; then"
            echo "    . /usr/share/bash-completion/bash_completion"
            echo "fi"
        )
        _print_exiting_bash
    fi
}

# =========================================================================== #

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then

# Function to display usage
# Strip /bin if called directly
# TODO needs tests
EXEC_PATH="${0#/bin/}"

usage() {
    echo "Usage: $EXEC_PATH <demo_name> [--clean|-y]"
    echo "Examples:"
    echo "  $EXEC_PATH --help                # Show this help message"
    echo "  $EXEC_PATH mydemo                # Run demo mydemo"
    echo "  $EXEC_PATH --clean     mydemo    # Clean demo mydemo"
    echo "  $EXEC_PATH -y          mydemo    # Run demo mydemo without pausing"
    echo "  $EXEC_PATH --dryrun    mydemo    # Run everything without executing"
    echo "  $EXEC_PATH --export sh mydemo    # Export demo to stdout in shell script format"
    echo "  $EXEC_PATH --export md mydemo    # Export demo to stdout in markdown format"
    echo "  $EXEC_PATH --offline   mydemo    # Run demo mydemo offline steps (if defined)"
    echo "  $EXEC_PATH --quiet     mydemo    # Run without printing anything"
    exit 1
}

# Check if at least one argument is provided
if (( $# == 0 )); then
    usage
fi

# Initialize GOON variable
GOON=${GOON:-false}
OFFLINE=${OFFLINE:-false}
QUIET=${QUIET:-false}
EXPORT_FORMAT=${EXPORT_FORMAT:-}
DRYRUN=${DRYRUN:-false}
CLEAN=${CLEAN:-false}


if ! _valid_args=$(
    getopt -o cde:hqoy \
        --long clean,dryrun,export:,goon,help,offline,quiet -- "$@")
then
    _print_error "Invalid arguments"
    usage
fi

eval set -- "$_valid_args"
while true; do
    case "$1" in
        -c|--clean)
            CLEAN=true
            shift
            ;;
        -d|--dryrun)
            DRYRUN=true
            shift
            ;;
        -e|--export)
            EXPORT_FORMAT="$2"
            shift 2
            ;;
        -h|--help)
            usage
            ;;
        -o|--offline)
            OFFLINE=true
            shift
            ;;
        -q|--quiet)
            QUIET=true
            shift
            ;;
        -y|--goon)
            GOON=true
            shift
            ;;
        --)
            shift
            break
            ;;
    esac
done

_script=true _check_env

# strips last /
# strip first ./
# strip first /
#
# ./show examples/minimal/
# ./show examples/minimal
# ./show /examples/minimal
# ./show ./examples/minimal
#
# will result in _demo_name=examples/minimal
#
# TODO needs tests!
_demo_dir=$1
if [[ -z "$_demo_dir" ]] || [[ "$_demo_dir" = "" ]]; then
    _print_error "Please provide a demo name"
    usage
fi

_demo_name=${_demo_dir%/}
_demo_name="${_demo_name#./}"
_demo_name="${_demo_name#/}"

# Validate demo number
# case $_demo_name in
#     ansible|autocompletion|auto-update|compose|healthcheck|quadlet|auto-update-rollback)
#         ;;
#     *)
#         echo "Error: Invalid demo name '$_demo_name'"
#         echo "Valid demos are: ansible, autocompletion, auto-update, auto-update-rollback compose, farm, healthckeck"
#         exit 1
#         ;;
# esac

# Check if demo directory exists
if [[ ! -d "$_demo_dir" ]]; then
    _print_error "Demo directory '$_demo_dir' does not exist"
    exit 1
fi

# Load theme.sh from demo directory if it exists
if [[ -f "$_demo_dir/theme.sh" ]]; then
    # shellcheck source=/dev/null
    source "$_demo_dir/theme.sh" 2>/dev/null || true
fi

# Run all scripts in sequence
if [[ "$CLEAN" = true ]]; then
    # Clean mode
    CLEAN_SCRIPT="$_demo_dir/clean.sh"
    if [[ -f "$CLEAN_SCRIPT" ]]; then
        _export_intestation
        cd "$_demo_dir" || exit 1
        # shellcheck source=/dev/null
        source clean.sh
        exit 0
    else
        _print_warning "Clean script '$CLEAN_SCRIPT' not found"
        exit 1
    fi
fi

if [[ "$OFFLINE" = true ]]; then
    OFFLINE_SCRIPT="$_demo_dir/offline.sh"
    if [[ -f "$OFFLINE_SCRIPT" ]]; then
        _export_intestation
        cd "$_demo_dir" || exit 1
        # shellcheck source=/dev/null
        source offline.sh
        exit 0
    else
        _print_warning "Offline script '$OFFLINE_SCRIPT' not found"
        exit 1
    fi
fi

_demo_script="$_demo_dir/demo.sh"
if [[ -f "$_demo_script" ]]; then
    _export_intestation
    cd "$_demo_dir" || exit 1
    # shellcheck source=/dev/null
    GOON="$GOON" \
    EXPORT_FORMAT="$EXPORT_FORMAT" \
    _demo_name="$_demo_name" \
        source demo.sh
    exit 0
else
    _print_warning "Demo script '$_demo_script' not found"
    exit 1
fi

fi # BASH_SOURCE

