# -*- shell-script -*-

################################################################################

§class "terminal" --with-interface \
    --properties "name" \
                 "command" \
                 "classname" \
                 "geometry=80x24" \
                 "font" \
                 "boldfont" \
                 "foreground" \
                 "background" \
                 "options" \
                 "match:a" \
                 "cache:t"

################################################################################

§function.clone "§terminal.set_match" "§terminal._set_match"
§function.clone "§terminals.init" "§terminals._init"
§function.clone "§terminal.get_command" "§terminal._get_command"

function §terminal.set_match {

    eval "$(§terminal.get_match matches)"

    if (( ${#matches[*]} == 0 )); then
	matches=("$@")
    else
	matches=("${matches[@]}" "$@")
    fi
    §terminal._set_match "${matches[@]}"
}

function §terminals.init {
    bashrun_terminals_used="$(§terminals.used)"
    §terminals._init
}

function §terminal.init {
   
    §terminal.set_cache ""
    local self="$(§terminal.get_name)";
    
    # use the default terminal's command if --command is omitted
    if [[ -z "$(§terminal._get_command)" ]]; then
	if §terminals.seek "default"; then
	    local default="$(§terminal._get_command)"
	    §terminals.seek "$self"
	    §terminal.set_command "$default"
	fi
    fi
    
    §terminal.get_command &>/dev/null
}

function §terminal.get_command {
    
    local command="$(§terminal._get_command)"
    local cached="$(§terminal.get_cache)"

    if [[ -z "$cached" ]]; then
	local classname="$(§terminal.get_classname)"
	local geometry="$(§terminal.get_geometry)"
	local font="$(§terminal.get_font)"
	local boldfont="$(§terminal.get_boldfont)"
	local foreground="$(§terminal.get_foreground)"
	local background="$(§terminal.get_background)"
	local options="$(§terminal.get_options)"
	
	cached="$(§terminal.expand "$command" "" "$classname" "$geometry" "$font" "$boldfont" "$foreground" "$background" "$options")"
	§terminal.set_cache "$cached"	
    fi
    printf '%s' "$cached"
}

function §terminal.expand {
    
    local template="$1"
    local command="$2"
    local classname="$3"
    local geometry="$4"
    local font="$5"
    local boldfont="$6"
    local foreground="$7"
    local background="$8"
    local options="$9"
    
    local word="" tmp="" method=""
    declare -i i=0

    local type="execute"
    if [[ -n "$command" ]]; then
	type="bashrun"
    fi

    if §templates.seek "$template"; then
	template="$(§template.create_commandline \
                    "execute" "$classname" "$geometry" \
                    "$font" "$boldfont" "$foreground" "$background" "$options")"
    fi

    # insert classname, geometry, font and options
    if [[ "$template" =~ [^\\]%n ]]; then
	template="$(§replace "$template" "%n" "$classname")"
    fi

    if [[ "$template" =~ [^\\]%g ]]; then
	template="$(§replace "$template" "%g" "$geometry")"
    fi

    if [[ "$template" =~ [^\\]%f ]]; then
	§quote font
	template="$(§replace "$template" "%f" "$font")"
    fi

    if [[ "$template" =~ [^\\]%b ]]; then
	§quote boldfont
	template="$(§replace "$template" "%b" "$boldfont")"
    fi

    if [[ "$template" =~ [^\\]%F ]]; then
	§quote foreground
	template="$(§replace "$template" "%F" "$foreground")"
    fi

    if [[ "$template" =~ [^\\]%B ]]; then
	§quote background
	template="$(§replace "$template" "%B" "$background")"
    fi

    if [[ "$template" =~ [^\\]%o ]]; then
	template="$(§replace "$template" "%o" "$options")"
    fi

    if [[ "$template" =~ [^\\]%% ]]; then
	template="$(§replace "$template" "%%" "%")"
    fi

    # insert command if given...

    # %* insert command split into words
    # %@ insert command as a single word (one level of quoting)
    # %@@, %@@@, ... add two, three, etc. levels of quoting
    if [[ -n "$command" ]]; then
	if [[ "$template" =~ [^\\]%((@|\*)+) ]]; then
	    method="${BASH_REMATCH[1]}"
	    
	    if [[ "$method" =~ @ ]]; then
		§quote ${#method} command
	    fi
	    
	    # insert command into template
	    template="$(§replace "$template" "%$method" "$command")"
	    
	else
	# append unquoted command to template
	    template+=" $command"
	fi
    fi

    printf '%s' "$template"
}

function §terminal.binary {
    local binary=""
    for binary in $(§terminal.get_command); do break; done
    printf '%s' "$binary"
}

function §terminal.list {
    local opt="$1"

    if [[ "$opt" == "-l" ]]; then
	local key
	for key in ${_bashrun_terminals_keys[@]}; do
	    if [[ "$key" == "command" ]]; then
		printf '%s\n' "$key: $(§terminal._get_command)"
	    else
		printf '%s\n' "$key: $(§terminal.get $key)"
	    fi
	done;
	printf '\n'
    else
	printf '%s\n' "$(§terminal.id)"
    fi
}

function §terminals.used {
    local used=""
    local saved="$(§terminal.get_name)"
    local binary=""

    §terminals.seek_start
    while §terminals.next?; do
	
	binary="$(§terminal.binary)"	
	if [[ ! " $used " =~ $binary ]]; then
	    used="$binary $used"
	fi
	§terminals.next
    done
    §terminals.seek "$saved"
    
    printf '%s' "$used"
}

function §terminals.get_match {
    local saved="$(§terminal.get_name)"
    local match=()
    local data=""

    §terminals.seek_start
    while §terminals.next?; do
        eval "$(§terminal.get_match m)"
	match=( "${match[@]}" "${m[@]}" )
	§terminals.next
    done

    §terminals.seek "$saved"

    local data="$(declare -p match)"
    data="${data:18:${#data}-19}"    
    data="declare -a $1=$data"
    printf '%s' "$data"
}
