#!/usr/bin/env zsh
# Eryn Wells <eryn@erynwells.me>

function prompt_loquacious_help
{
    cat <<EOF
This prompt takes up two lines. At its most verbose, it looks like this:

    <user> at <host> in <cwd> on <repo>(<branch>)
    % 

By default, <host> is only shown when the SSH_CONNECTION variable is set; in
other words, when this shell session was opened via an SSH connection. The
prompt will also show the current repository and branch using vcs_info if the
current directory is in a repo.
EOF
}

function prompt_loquacious_setup
{
    typeset -ga precmd_functions
    typeset -ga preexec_functions

    autoload -U prompt_colorize
    autoload -Uz vcs_info
    autoload -U add-zsh-hook

    add-zsh-hook chpwd set_repo_name
    add-zsh-hook precmd set_xterm_title
    add-zsh-hook precmd set_tmux_window_name
    add-zsh-hook precmd print_newline
    add-zsh-hook precmd set_prompt_info

    add-zsh-hook preexec print_newline
    add-zsh-hook preexec set_tmux_window_name

    prompt_opts=(cr subst percent)

    # Set up vcs_info
    zstyle ':vcs_info:git:loquacious_chpwd:*' formats '%F{cyan}%r%f'
    zstyle ':vcs_info:git-svn:loquacious_chpwd:*' formats '[%F{red}svn%f]%F{cyan}%r%f'
    zstyle ':vcs_info:git:loquacious_precmd:*' formats '(%F{blue}%b%f)'
    zstyle ':vcs_info:git-svn:loquacious_precmd:*' formats '(%F{blue}%b%f)'

    PS1='$PS1_PLACE, $PS1_TIME $PS1_ZLE_MODE
$PS1_LINE'

    zle -N zle-keymap-select on_keymap_select
}

function prompt_loquacious_preview
{
    # TODO: Implement prompt preview.
}

#
# HELPER FUNCTIONS
#

# First prompt flag. See precmd_newline.
is_first_prompt=1

function print_newline
{
    # Don't print newlines the first time the prompt is displayed.
    if [[ -n $is_first_prompt ]]; then
        unset is_first_prompt
        [[ -z $SSH_CONNECTION ]] && return
    fi
    echo
}

function set_repo_name
{
    vcs_info loquacious_chpwd
    if [[ -n "${vcs_info_msg_0_}" ]]; then
        PS1_REPO="on ${vcs_info_msg_0_}"
    else
        PS1_REPO=""
    fi
}

function set_prompt_info
{
    PS1_TIMESTAMP="%*"
    PS1_STATUS="%(?..%F{red}[$?]%f)"
    PS1_HISTORY="№%F{blue}%!%f"
    PS1_TIME="$PS1_HISTORY$PS1_STATUS at $PS1_TIMESTAMP"

    PS1_NAME="%F{magenta}%n%f"
    PS1_HOST="%F{red}%m%f"
    PS1_CWD="%F{green}%~%f"

    PS1_PLACE="$PS1_NAME"
    if [[ -n "$SSH_CONNECTION" && "$TERM_PROGRAM" != "tmux" ]]; then
        PS1_PLACE="$PS1_PLACE at $PS1_HOST"
    fi
    PS1_PLACE="$PS1_PLACE in $PS1_CWD"


    # Get git repo information, if it exists. See setup function for
    # configuration details.
    vcs_info loquacious_precmd
    PS1_BRANCH="${vcs_info_msg_0_}"
    if [[ -n "$vcs_info_msg_0_" ]]; then
        PS1_PLACE="$PS1_PLACE $PS1_REPO$PS1_BRANCH"
    fi

    # Show background jobs, if any.
    if [[ `jobs | wc -l` -ge 1 ]]; then
        PS1_JOBS='%j'
    fi

    # Show background job count if any exist.
    RPS1="%(1j.[%F{magenta}%j%f].)"

    PS1_LINE='%(!.%F{red}.%F{default})%#%f '
}

function set_xterm_title
{
    local tmux_session_name=''
    local title='%n@%m'
    if [[ -n "$TMUX" ]]; then
        local tmux_session_name=`tmux display-message -p '#S'`
        title+=" (${tmux_session_name})"
    fi

    # Set xterm and screen titles
    if [[ -n "$DISPLAY" || -n "$TERM_PROGRAM" ]]; then
        print -Pn "\e]2;${title}\a"
    fi

    # For Apple Terminal.app, add a link to the current directory.
    if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]]; then
        print -Pn "\e]7;file://%d\a"
    fi
}

function set_tmux_window_name
{
    if [[ -z "$TMUX" ]]; then
        return
    fi

    local process="${${(z)1}[1]}"
    if [[ -n "$process" ]]; then
        tmux rename-window "$process"
    else
        tmux rename-window "`print -Pn "%2~"`"
    fi
}

function set_zle_mode_info
{
    if [[ -z "$1" || "$1" == 'viins' || "$1" == 'main' ]]; then
        PS1_ZLE_MODE="%F{black}<INS>%f"
    elif [[ "$1" == 'vicmd' ]]; then
        PS1_ZLE_MODE="%F{black}<CMD>%f"
    else
        PS1_ZLE_MODE=''
    fi
}

function on_keymap_select
{
    # Regenerate the prompt with the new mode
    set_zle_mode_info $KEYMAP

    # Redraw the prompt
    zle reset-prompt
}

# Finally, run setup to get everything going
prompt_loquacious_setup "$@"
