#!/usr/bin/env bash

version=1.0
SYSTEMPONIES="/usr/share/ponysay/ponies"
HOMEPONIES="${HOME}/.local/share/ponysay/ponies"
pony="*"
wrap=""

if [ "$TERM" = "linux" ]; then
    SYSTEMPONIES="/usr/share/ponysay/ttyponies"
    HOMEPONIES="${HOME}/.local/share/ponysay/ttyponies"
fi

cmd=cowsay
[[ ${0} == *ponythink ]] && cmd=cowthink

version() {
    echo "ponysay v$version"
}

scrw=`(stty size <&2 || echo 0 0) | cut -d ' ' -f 2`
listcmd="/usr/lib/ponysay/list.pl"
truncatercmd="/usr/lib/ponysay/truncater"

haspq=1
if [[ -f './pq4ps-list' ]]; then
    function qlist
    {   ./pq4ps-list
    }
elif [[ -f '/usr/bin/pq4ps-list' ]]; then
    function qlist
    {   /usr/bin/pq4ps-list
    }
else
    haspq=0
    function qlist
    {   cat
    }
fi

list() {
    echo -e "\\e[01mponyfiles located in $SYSTEMPONIES:\\e[21m"
    perl $listcmd $scrw $(ls --color=no $SYSTEMPONIES | sed -e 's/\.pony$//' | sort) | qlist
    
    if [[ -d $HOMEPONIES ]]; then
	echo -e "\\e[01mponyfiles located in $HOMEPONIES:\\e[21m"
	perl $listcmd $scrw $(ls --color=no $HOMEPONIES | sed -e 's/\.pony$//' | sort) | qlist
    fi
}

_linklist() {
    echo -e "\\e[01mponyfiles located in $1:\\e[21m"
    files=$(ls --color=no $1 | sed -e 's/\.pony$//' | sort)
    
    args=""
    
    for file in $files; do
	target=$(readlink $1"/"$file".pony")
	if [[ $target = "" ]]; then
	    target=$file
	else
	    target=$(echo $target | sed -e 's/^\.\///g' -e 's/\.pony$//g')
	fi
	args=$(echo $args $file $target)
    done
    
    scrw=`(stty size <&2 || echo 0 0) | cut -d ' ' -f 2`
    
    perl '/dev/stdin' $(echo $args) <<EOF | sed -e 's/ /_/g' > /dev/shm/ponysay~
#!/usr/bin/perl

#Author: Mattias Andrée (maandree@kth.se)

%hash = ();
\$argc = @ARGV;

\$i = 0;
while (\$i < \$argc)
{
    \$source = \$ARGV[\$i];
    \$i += 1;
    \$target = \$ARGV[\$i];
    \$i += 1;
    if (\$source eq \$target)
    {
        \$hash{\$source} = [ () ];
    }
}

\$i = 0;
while (\$i < \$argc)
{
    \$source = \$ARGV[\$i];
    \$i += 1;
    \$target = \$ARGV[\$i];
    \$i += 1;
    unless (\$source eq \$target)
    {
        push @{ \$hash{\$target} }, \$source;
    }
}

\$i = 0;
while (\$i < \$argc)
{
    \$source = \$ARGV[\$i];
    \$i += 1;
    \$target = \$ARGV[\$i];
    \$i += 1;
    if (\$source eq \$target)
    {
        @list = @{ \$hash{\$source} };
        \$first = 1;
        print \$source;
        foreach \$link (@list)
        {
            if (\$first eq 1)
            {
                print " (".\$link;
                \$first = 0;
            }
            else
            {
                print " ".\$link;
            }
        }
        if (\$first eq 0)
        {
            print ")";
        }
        print "\n";
    }
}
EOF
    
    perl $listcmd $scrw $(cat /dev/shm/ponysay~) | sed -e 's/_/ /g' | qlist
}

linklist() {
    _linklist $SYSTEMPONIES
    if [[ -d $HOMEPONIES ]]; then
	_linklist $HOMEPONIES
    fi
}

usage() {
    version
    cat <<EOF

Usage:
${0##*/} [options] [message]

If [message] is not provided, reads the message from STDIN.

Options:
  -v          Show version and exit.
  -h          Show this help and exit.
  -l          List pony files.
  -L          List pony files with synonyms inside brackets.
EOF
if [[ $haspq = 1 ]]; then
    cat <<EOF
  -q          Use the pony quote feature.
EOF
fi
cat <<EOF
  -f[name]    Select a pony (either a file name or a pony name.)
  -W[column]  The screen column where the message should be wrapped.

See man ponysay(6) for more information.
EOF
}

# if no stdin and no arguments then print usage and exit
if [[ -t 0 && $# == 0 ]]; then
  usage
  exit
fi

say() {
    # Ponies use UTF-8 drawing characters. Prevent a Perl warning.
    export PERL_UNICODE=S
    
    if [ "$TERM" = "linux" ]; then
    	echo -ne '\e[H\e[2J'
    fi
    
    function wtrunc
    {
	if [ "$PONYSAY_FULL_WIDTH" = 'no' ] || [ "$PONYSAY_FULL_WIDTH" = 'n' ] || [ "$PONYSAY_FULL_WIDTH" = '0' ]; then
	    cat
	else
	    WIDTH=`(stty size <&2 || echo 0 0) | cut -d ' ' -f 2`
		$truncatercmd $WIDTH 2>/dev/null || cat
	fi
    }
    
    if [ "$PONYSAY_SHELL_LINES" = "" ]; then
	PONYSAY_SHELL_LINES=2
    fi
    function htrunchead
    {
	head --lines=$(( `stty size <&2 | cut -d ' ' -f 1` - $PONYSAY_SHELL_LINES ))
    }
    function htrunctail
    {
	tail --lines=$(( `stty size <&2 | cut -d ' ' -f 1` - $PONYSAY_SHELL_LINES ))
    }
    
    if [ "$TERM" = "linux" ] || [ "$PONYSAY_TRUNCATE_HEIGHT" = 'yes' ] || [ "$PONYSAY_TRUNCATE_HEIGHT" = 'y' ] || [ "$PONYSAY_TRUNCATE_HEIGHT" = '1' ]; then
	if [ "$PONYSAY_BOTTOM" = 'yes' ] || [ "$PONYSAY_BOTTOM" = 'y' ] || [ "$PONYSAY_BOTTOM" = '1' ]; then
	    exec "$cmd" -f "$pony" "${wrap:+-W$wrap}" | wtrunc | htrunctail
	else
	    exec "$cmd" -f "$pony" "${wrap:+-W$wrap}" | wtrunc | htrunchead
	fi
    else
	exec "$cmd" -f "$pony" "${wrap:+-W$wrap}" | wtrunc
    fi
}

ponies=()

opts="f:W:Llhv"
if [[ $haspq ]]; then
    opts=$opts"q"
fi
usepq=0
while getopts $opts OPT
do
    case ${OPT} in
        v)  version; exit ;;
        h)  usage; exit ;;
        f)  ponies+=( "$OPTARG" ) ;;
	l)  list; exit ;;
	L)  linklist; exit ;;
        W)  wrap="$OPTARG" ;;
	q)  usepq=1 ;;
        \?) usage >&2; exit 1 ;;
    esac
done
shift $((OPTIND - 1))

if [[ $usepq = 1 ]]; then
    if [[ -f './pq4ps' ]]; then
	function q
	{   ./pq4ps $@
	}
    elif [[ -f '/usr/bin/pq4ps' ]]; then
	function q
	{   /usr/bin/pq4ps $@
	}
    fi
    $0 ${wrap:+-W$wrap} $(q "$*")
    exit
fi

hash $cmd &>/dev/null; if [ $? -ne 0 ]; then
    cat >&2 <<EOF
You don't seem to have the $cmd program.
Please install it in order to use this wrapper.

Alternatively, symlink it to '$cmd' in anywhere in \$PATH
if it actually exists under a different filename.
EOF
    exit 1
fi

if [[ ! ${#ponies[@]} == 0 ]]; then
    pony="${ponies[$RANDOM%${#ponies[@]}]}"
fi

if [[ ! -f $pony ]]; then
    # Pony not a file? Search for it

    ponies=()
    [[ -d $SYSTEMPONIES ]] && ponies+=( "$SYSTEMPONIES"/$pony.pony )
    [[ -d $HOMEPONIES ]] && ponies+=( "$HOMEPONIES"/$pony.pony )

    if (( ${#ponies} < 1 )); then
        echo >&2 "All the ponies are missing! Call the Princess!"
        exit 1
    fi

    # Choose a random pony
    pony="${ponies[$RANDOM%${#ponies[@]}]}"
fi

if [[ -n "$*" ]]; then
  # Handle a message given via arguments
  say <<<"$*"
else
  say
fi