# Prompt
# vim: ft=zsh
autoload -U colors && colors

nullexec() { "$@" &>/dev/null; }

precmd.title() {
	printf '%b' "\e]2;$1\a"
}

precmd.svn() {
	if [[ -f .novcsprompt ]]; then
		return 0
	fi

	if nullexec svn info; then
		while IFS= read -r line; do
			case $line in
				(M*|A*|D*) svn_unstaged=1;;
				(\!*) svn_missing=1;;
				(\?*) svn_untracked=1;;
			esac
		done < <( svn st )

		(( svn_unstaged )) && {
			svn_st+='c'
			svn_st_col='red'
		}

		(( svn_missing )) && {
			svn_st+='m'
			svn_st_col='red'
		}

		(( svn_untracked )) && {
			svn_st+='f'
			svn_st_col='red'
		}

		svn_st_col=${svn_st_col:-"green"}
		svn_st=${svn_st:-"ok"}

		printf '%s' "(%F{cyan}svn%f:%F{$svn_st_col}$svn_st%f) "
	fi
}

precmd.is_git_repo() {
	declare _pwd=$PWD

	while [[ -n $_pwd ]]; do
		if [[ -r "$_pwd/.git/HEAD" ]]; then
			return 0
		else
			_pwd=${_pwd%/*}
		fi
	done

	return 1
}

precmd.git() {
	declare git_branch_info git_unstaged git_untracked git_status_short git_status_colour git_prompt_msg

	[[ -f .novcsprompt ]] && return 0
	precmd.is_git_repo || return 0

	declare line
	while IFS= read -r line; do
		[[ $line[1,2] == '##' ]] && git_branch_info=$line[4,-1]
		[[ $line[1,2] == '??' ]] && (( git_untracked++ ))
		[[ $line[1,2] =~ .[MD] ]] && (( git_unstaged++ ))
		[[ $line[1,2] =~ [MDARC]. ]] && (( git_staged++ ))
	done < <(git status --porcelain -bu 2>/dev/null)

	git_branch_name=${git_branch_info%%...*}
	[[ $git_branch_info =~ ahead\ ([0-9]+) ]] && git_ahead=$match[1]
	[[ $git_branch_info =~ behind\ ([0-9]+) ]] && git_behind=$match[1]

	git_status_colour='green'

	_c() { printf '%%F{%s}%s%%f' "$@" }
	(( git_ahead )) && git_status_short+=$(_c yellow a)
	(( git_behind )) && git_status_short+=$(_c yellow b)
	(( git_staged )) && git_status_short+=$(_c red s)
	(( git_unstaged )) && git_status_short+=$(_c red c)
	(( git_untracked )) && git_status_short+=$(_c red f)

	git_status_short=${git_status_short:-"ok"}
	git_prompt_msg="(%F{cyan}$git_branch_name%f[%F{$git_status_colour}${git_status_short}%f]) "

	printf '%s' $git_prompt_msg
}

rprompt() {
	{ precmd.svn; precmd.git } > "$XDG_RUNTIME_DIR/zsh_rprompt_$$.tmp"
	kill -s USR1 $$
}

TRAPUSR1() {
	prompt_async_data=$(<"$XDG_RUNTIME_DIR/zsh_rprompt_$$.tmp")
	draw_prompt
	zle && zle reset-prompt
}

draw_prompt() {
	prompt_custom=(
		"%F{$cmd_colour}$cmd_msg%f"
		"%F{$user_colour}$USER%f $HOST:${PWD//$HOME/~}"
		"$prompt_async_data%F{$user_colour}>%f"
	)

	PROMPT=" $prompt_custom "
}

precmd() {
	declare last_exit_code=$?
	declare -g cmd_colour cmd_msg
	
	if (( last_exit_code )); then
		cmd_colour='red'
		cmd_msg='!'
	else
		cmd_colour='green'
		cmd_msg='.'
	fi

	if (( UID )); then
		user_colour='green'
	else
		user_colour='red'
	fi

	precmd.title "$USER@$HOST ${PWD//$HOME/~}"

	draw_prompt

	rprompt &!
}
