#!/usr/bin/env bash

send_os_command()
{
	_splat=""
	_suffix=""
	echo -n ']'
	while [ -n "${1}" ]
	do
		[ -n '${_splat}' ] && echo -n ';'
		echo -n "${1}"
		shift 1
	done
	echo -n "${suffix}"
}

send_csi_command()
{
	_splat=""
	_suffix="${1}"
	shift 1

	
	echo -n ""
	echo -n "[${1}"

	# First one no ';' prefix....
	#echo -n "${1}"
	shift 1

	while [ -n "${1}" ]
	do
		[ -n '${_splat}' ] && echo -n ';'
		echo -n "${1}"
		shift 1
	done
	echo -n "${_suffix}"
}

##### START DECCRA Block ############

# These two functions expect DECCRA (DEC Copy Rectangular Area)
# to work.  It also requires a second page to copy to.
# I haven't gotten them working, it seems.

save_block()
{
	_T=$1
	_L=$2
	_B=$3
	_R=$4
	send_csi_command '$v' $_T $_L $_B $_R 1 1 140 1
}

restore_block()
{
	_T=$1
	_L=$2
	_B=$3
	_R=$4
	_W=$(( ${_R} - ${_L} + 1 ))
	_H=$(( ${_B} - ${_T} + 1 ))
	send_csi_command '$v' 1 140 $_H $(( 140 + $_W - 1 )) 1 $_T $_L 1
}

##### END DECCRA Block ##############

erase_block()
{
	send_csi_command '*x' 2
	fill_block_attributes ${*} 0
	send_csi_command '${' ${*}
}

fill_block_attributes()
{
	send_csi_command '$r' ${*}
}

fill_block_raw()
{
	send_csi_command '$x' ${*}
}

fill_block()
{
	_code=`printf '%d' "'$1"`
	shift 1
	fill_block_raw ${_code} ${*}
}

write_char_raw()
{
	fill_block_raw $1 $2 $3 $2 $3
}

write_char()
{
	_code=`printf '%d' "'$1"`
	shift 1
	write_char_raw ${_code} ${*}
}

write_string()
{
	_str=$1
	shift 1
	_row=$1
	shift 1
	_col=$1
	shift 1
	while [ -n "$_str" ]
	do
		_ch=${_str:0:1}
		_str=${_str:1}
		_code=`printf '%d' "'$_ch"`
		write_char_raw $_code $_row $_col
		if [ -n "${*}" ]
		then
			fill_block_attributes ${_row} ${_col} ${_row} ${_col} ${*}
		fi
		_col=$(( ${_col} + 1 ))
	done
}

draw_box()
{
	# T L B R
	_T=$1
	_L=$2
	_B=$3
	_R=$4
	write_char + $_T $_L
	write_char + $_T $_R
	write_char + $_B $_L
	write_char + $_B $_R

	fill_block - $_T $(( $_L + 1 )) $_T $(( $_R - 1 ))
	fill_block - $_B $(( $_L + 1 )) $_B $(( $_R - 1 ))

	fill_block '|' $(( $_T + 1 )) $_L $(( $_B - 1 )) $_L
	fill_block '|' $(( $_T + 1 )) $_R $(( $_B - 1 )) $_R
}

###############
#
# Builds a box of specified dimensions
# (and clears the middle).
#
###############
build_box()
{
	erase_block $*
	draw_box $*
}


# Read a single keypress in raw terminal mode.
# It will read all codes from the input.
#
# Due to read timeouts, it may give odd
# results on non-interactive terminals.
read_key()
{
	seq=""
	read -sN 1 key
	code=`printf "%x" "'$key"`
	seq=K${code}
	while read -t 0
	do
		read -sN 1 key
		code=`printf "%x" "'$key"`
		seq="${seq}${code}"
	done

	eval $1=\"${seq}\"
}

declare -A _keycodes
_keycodes["K9"]="Tab"
_keycodes["K20"]="Space"
_keycodes["K1b"]="Escape"
_keycodes["K1b5b41"]="Up"
_keycodes["K1b5b42"]="Down"
_keycodes["K1b5b44"]="Left"
_keycodes["K1b5b43"]="Right"
_keycodes["K30"]="0"

translate_key()
{
	if [[ ! -v _keycodes[$1] ]];
	then
		echo "MISS ($1)" > /dev/fd/2
		echo "$1"
	else
		_key="${_keycodes[${1}]}"
		#echo "HIT (${_key})" > /dev/fd/2
		echo ${_key}
	fi
}
	


#erase_block 20 20 30 30
#fill_block X 21 21 29 29
#write_char Y 25 25

#build_box 8 24 19 99
#write_string "Hello World" 10 26

#read -sn 1 keyA
#read -sn 1 keyB
#read -sn 1 keyC

declare -A buttons

create_button()
{
	_name=$1
	_r=$2
	_c=$3
	_text=$4
	_color=$5

	shift 1
	eval button_${_name}=\"$*\"

	_T=$_r
	_B=$(( $_r + 2 ))

	_L=$_c
	_R=$(( $_c + 3 + ${#_text} ))

	erase_block $_T $_L $_B $_R
	build_box $_T $_L $_B $_R
	write_string "$_text" $(( $_T + 1 )) $(( $_L + 2 ))
	if [ -n "$_color" ]
	then
		fill_block_attributes $_T $_L $_B $_R "3${_color}"
	fi
}

button_stat()
{
	_r=$1
	_c=$2
	_text=$3
	_color=$4
}


highlight_button()
{
	_name=$1
	eval _stat="\${button_${_name}}"
	button_stat ${_stat}

	_T=$_r
	_B=$(( $_r + 2 ))

	_L=$_c
	_R=$(( $_c + 3 + ${#_text} ))

	fill_block_attributes $_T $_L $_B $_R 0
	if [ -n "$_color" ]
	then
		fill_block_attributes $_T $_L $_B $_R "4${_color}"
	else
		fill_block_attributes $_T $_L $_B $_R '7'
	fi
}

unhighlight_button()
{
	_name=$1
	eval _stat="\${button_${_name}}"
	button_stat ${_stat}

	_T=$_r
	_B=$(( $_r + 2 ))

	_L=$_c
	_R=$(( $_c + 3 + ${#_text} ))


	fill_block_attributes $_T $_L $_B $_R 0
	if [ -n "$_color" ]
	then
		fill_block_attributes $_T $_L $_B $_R "3${_color}"
	fi
}

get_terminal_size()
{
	send_csi_command t 18
	read_key _seq


	# Consume ^[[8;

	echo "Pre Array: ${_seq}"
	_seq=(${_seq})
	echo "Array: ${_seq}"
	_seq=(${_seq[@]:4})
	echo "Trimmed Array: ${_seq}"

	_rows=0
	while [ "${_seq[ 0 ]}" != ";" ]
	do
		_rchar="${_seq[ 0 ]}"
		echo "RChar: ${_rchar}"
		_seq=${_seq[@]:1}

		#_rows=$(( ${_rows} * 16 + $( printf "\x${_rchar}" ) ))
	done


	_cols=0
	while [ "${_seq[ 0 ]}" != ";" ]
	do
		_cchar="${_seq[ 0 ]}"
		_seq=${_seq[@]:1}

		#_cols=$(( ${_cols} * 16 + $( printf "\x${_cchar}" ) ))
	done

	eval $1=\"${_rows}\"
	eval $2=\"${_cols}\"
}

#parse_color "${hex}" red green blue

declare -A _hexdigits
_hexdigits["0"]="0"
_hexdigits["1"]="1"
_hexdigits["2"]="2"
_hexdigits["3"]="3"
_hexdigits["4"]="4"
_hexdigits["5"]="5"
_hexdigits["6"]="6"
_hexdigits["7"]="7"
_hexdigits["8"]="8"
_hexdigits["9"]="9"
_hexdigits["10"]="a"
_hexdigits["11"]="b"
_hexdigits["12"]="c"
_hexdigits["13"]="d"
_hexdigits["14"]="e"
_hexdigits["15"]="f"

hexbyte()
{
	echo -n "${_hexdigits[$((${1}/16))]}${_hexdigits[$((${1}%16))]}"
}

get_color_hex()
{
	_color=$1
	_tmp=`stty -g`
	stty -echo
	echo -n ']4;'"${_color}"';?'
	read -sN 1 _ch # We know we'll get an Esc back, so drop it
	read -sN 1 _ch
	_hex=""
	while [ "${_ch}" != '' ]
	do
		_hex="${_hex}${_ch}"
		read -sN 1 _ch
	done
	stty ${_tmp}

	#echo "Hex Pre: ${_hex}"
	_hex=${_hex/]4;${_color};rgb:/}
	#echo "Hex: ${_hex}"
	_red=${_hex:0:2}
	_green=${_hex:5:2}
	_blue=${_hex:10:2}

	#echo "R: ${_red}"
	#echo "G: ${_green}"
	#echo "B: ${_blue}"

	eval $2=\"${_red}\"
	eval $3=\"${_green}\"
	eval $4=\"${_blue}\"
}

