# -*- shell-script -*-

function §message.init {
    local method
    local methods="zenity kdialog notify-send xmessage printf"
 
   for method in $methods; do
	if type $method &>/dev/null; then
	    bashrun_message_method=$method
	    break
	fi
    done
}
§message.init

function §message.wrap {

    local input width chunk ifs p word 
    declare -a chunks
    declare -i i k

    width=72
    if [[ "$1" =~ ^[0-9]+$ ]]; then
	width="$1"
	shift
    fi
    input="$1"

    # split input into chunks at \n\n
    input=${input//$'\n'$'\n'/__SePaRaToR__}
    input=${input//$'\n'/ }
    input=${input//__SePaRaToR__/$'\n'}
    ifs=$IFS; IFS=$'\n'; chunks=( $input ); IFS=$ifs

    for (( i=0; i<${#chunks[@]}; i++ )); do
	chunk="${chunks[i]}"
	
	# allow \n's to be inserted in between two words,
	# e.g "foo\nbar", or at the end of a word (i.e. line)
	while [[ "$chunk" =~ ([^\ ])\\n ]]; do	    
	    chunk="${chunk//[^ ]\\n/${BASH_REMATCH[1]} \n }"
	done

	while [[ "$chunk" =~ ([^\ ])\\n([^\ ]) ]]; do	    
	    chunk="${chunk//[^ ]\\n[^ ]/${BASH_REMATCH[1]} \n ${BASH_REMATCH[2]}}"
	done

	# strip literal newlines from chunk
	chunk="${chunk//$'\n'/ }"

	p=(); k=0
	for word in $chunk; do
	    if [[ "$word" == "\n" ]]; then
		p[k]+="\n"
		k+=1
	    else
		if [[ $(( ${#p[k]} + ${#word} ))  -lt $width ]]; then
		    if [[ -z "${p[k]}" ]]; then
			p[k]+="$word"
		    else
			p[k]+=" $word"
		    fi
		else
		    k+=1
		    p[k]+=$'\n'"$word"
		fi
	    fi
	done

	if [[ i -eq 0 ]]; then 
	    printf '%s\n' "${p[@]}"
	else
	    printf '\n'
	    printf '%s\n' "${p[@]}"
	fi
    done    
}

function §message {
    
    local title="$1"
    shift

    local text=""
    local method="$bashrun_message_method"
    
    # prepare text depending on method
    case "$method" in 
	dialog|xmessage|kdialog|printf)
	    # prewrap text to 76 columns 
	    # (80 - 4 (dialog border and margin))
	    text="$(§message.wrap 76 "$@")"
	    ;;
	zenity|notify-send)
            # split input into chunks at \n\n
	    text="$1"
	    text="$(printf '%s\n' "$text" | sed 's/^ *//g')"
	    text=${text//$'\n'$'\n'/__SePaRaToR__}
	    text=${text//$'\n'/ }
	    text=${text//__SePaRaToR__/$'\n\n'}	    
    esac
    text="${text//\\n /\\n}"

    # xmessage and notify-send don't interpret \n
    # replace them with literal newlines
    if [[ "$method" =~ xmessage|notify-send ]]; then
	text="${text//\\n/$'\n'}"
    fi

    case "$method" in

	dialog)
	    declare -i height=0
	    local dialog=""
	    local tmp=""

	    # find height by counting literal newline characters
	    tmp="${text//[^$'\n']}/}"
            height=${#tmp}

	    # add number of escaped newlines (\n) to height
	    tmp="${text//\\n/}"
	    (( height += ((${#text} - ${#tmp}) / 2) ))

	    # encode newlines for dialog
	    text="${text//$'\n'/\\n}"

	    # escape literal double quotes
	    text="${text//\"/\\\"}"

	    # escape literal backticks
	    text="${text//\`/\\\`}"

	    # add leading and closing blank lines
	    text="\n${text}\n"
            
            # adjust height (2 lines above + 3 lines in dialog)
	    (( height += 5 )) 

	    # construct dialog
	    dialog="dialog --no-shadow "
	    dialog+="--title \" Bashrun - $title \" "
	    dialog+="--msgbox \"$text\" $height 80"

	    if (type §window.terminal? &>/dev/null && §window.terminal?); then
		# we're inside bashrun, so we just use it's terminal
		
		# remember previous size
		local prev_size="$(§window.size)"

		# resize to 80 x height
		§window.size --hint 80 $height
	    
		# run dialog here
		eval "$dialog"

		# reset window size and clear
		§window.size --hint $prev_size
		tput clear

	    else	    
		# we're outside of bashrun, so we need a terminal
		local term=""
		for term in urxvt xterm rxvt mrxvt; do
		    if type -p $term &>/dev/null; then  
			$term -g 80x$height+0+0 -e bash -c "$dialog"
			break
		    fi
		done
	    fi
	    ;;
	xmessage)
	    xmessage "Bashrun2 $title:"$'\n\n'"$text" &>/dev/null
	    ;;
	
	zenity)
	    local type="--info"
	    [[ "$title" =~ rror ]] && type="--error"
	    [[ "$title" =~ arning ]] && type="--warning"

	    zenity $type --title "Bashrun2 $title" --text "$text" &>/dev/null
	    ;;
	
	kdialog)
	    local type="--msgbox"
	    [[ "$title" =~ rror ]] && type="--error"
	    [[ "$title" =~ arning ]] && type="--sorry"

	    kdialog --title "Bashrun2 $title" $type "$text"$'\n' &>/dev/null
	    ;;

	notify-send)
	    notify-send -t 0 "$title" "$text" &>/dev/null
	    ;;

	printf)	    	    
	    printf '%b' "\x07"
	    printf '%b\n' "Bashrun2 $title:\n\n$text"
    esac
}

