#!/bin/sh
########################################
# name: wyrics
# desc: fetch lyrics by URL or query
#       from lyrics.wikia.com
# main: Jenga Phoenix
#       <jadedctrl@teknik.io>
# lisc: CC 0
########################################

# --------------------------------------
# generic

# NIL --> STRING
# read from stdin until eof hit; return all input
# good for writing functions that take piped info
function reade {
        local stack=""

        while read input; do
		stack="$(printf '%s\n%s' "$stack" "$input")"
	done

	echo "$stack"
}

# NUMBER STRING --> [BOOLEAN]
# have the user choose a number, up to a given max, with prompt.
function number_choose {
	local max=$1
	local prompt="$2"

	printf "$prompt" >&2
	read response

	if test $response -lt $max; then
		return $response
	else
		number_choose $max "$prompt"
	fi
}

# NUMBER NUMBER --> NUMBER
# add two numbers together. pretty obvious.
function add {
	local operator=$1
	local operatee=$2

	echo "$1 + $2" \
	| bc
}

# NUMBER NUMBER --> NUMBER
# subtract two numbers. pretty obvious.
function subtract {
	local operator=$1
	local operatee=$2

	echo "$1 - $2" \
	| bc
}



# --------------------------------------
# searching

# STRING --> STRING
# return a result-list from a search query
function search {
	local query="$1"
	local query="$(echo "$query" | sed 's/ /+/g')"

	gendl "https://lyrics.wikia.com/wiki/Special:Search?query=${query}" \
	| sed '1,/Results/d' \
	| grep "result-link" \
	| search_parse
}

# |STRING  --> STRING
# take slightly-trimmed search HTML and turn it into result-list
function search_parse {
	local html="$(reade)"

	local stack=""
	local i=0
	IFS='
'
	for line in $html; do
		i=$(add $i 1)
		local url="$(echo "$line" \
				| sed 's/.*href=\"//' \
				| sed 's/\" class.*//')"
		local title="$(echo "$line" \
				| sed 's%.*">%%' \
				| sed 's%</a>%%')"

		if echo "$title" | grep "http" > /dev/null; then
			i=$(subtract $i 1)
		else
			stack="$(printf '%s\n%s@%s@%s' \
				"$stack"  "$i" "$url" "$title")"
		fi
	done

	echo "$stack" \
	| head -11
}



# --------------------------------------
# result manipulation

# |STRING --> STRING
# return the title of a result
function result_title {
	local result="$(reade)"

	echo "$result" \
	| awk -F "@" '{ print $3 }' \
	| tr -d '\n'
}

# |STRING --> STRING
# return the ID of a result
function result_index {
	local result="$(reade)"

	echo "$result" \
	| awk -F "@" '{ print $1 }' \
	| tr -d '\n'
}

# |STRING --> STRING
# return the URL of a result
function result_url {
	local result="$(reade)"

	echo "$result" \
	| awk -F "@" '{ print $2 }' \
	| tr -d '\n'
}

# |STRING [STRING] --> STRING
# display all results in a result-list to stderr.
# if second argument is 'long', then URLs are printed, too.
function results_display {
	local results="$(reade)"
	local long="$1"
	
	IFS='
'
	for result in $results; do
		local index="$(echo "$result" | result_index)"
		local title="$(echo "$result" | result_title)"
		local url="$(echo "$result" | result_url)"

		echo "$index	$title" >&2
		if test "$long" = "long"; then
			echo "$url" >&2
		fi
	done
}


# STRING --> STRING
# have the user choose a single result from the result-list
function result_choose {
	local results="$1"
	local max="$(echo "$results" | wc -l)"

	number_choose $max ">> "
	local response=$?

	echo "$results" \
	| grep "^$response@"
}



# --------------------------------------

# STRING --> STRING
# return the lyrics of a given URL
function lyrics {
	local url="$1"

	gendl "$url" \
	| grep "class=\'lyricbox" \
	| sed 's/.*lyricbox.>//' \
	| sed 's/;<div.*//' \
	| lynx -stdin -dump \
	| sed 's/^   //g'
}



# --------------------------------------
# invocation

# NIL --> STRING
# print usage and abort
function usage {
	echo "usage: wyrics -s query"
	echo "       wyrics -u url"
	exit 2
}

# --------------------------------------

case "$1" in
	"-u")
		lyrics "$2"
		;;
	"-s")	
		results="$(search "$2")"

		echo "$results" | results_display
		url="$(result_choose "$results" | result_url)"

		lyrics "$url"
		;;
#	*)
#		usage
#		;;

esac