KBWDEBUG=${KBWDEBUG:-no}

function dprint {
if [[ $KBWDEBUG == yes && $- == *i* ]]; then
    #date "+%H:%M:%S $*"
    echo $SECONDS $*
fi
}
dprint alive
if [ -r "${HOME}/.bashrc.local.preload" ]; then
    dprint "Loading bashrc preload"
    source "${HOME}/.bashrc.local.preload"
fi

#########################
# Some useful functions #
#########################

function have { type "$1" &>/dev/null ; }

# This is a readlink wrapper, just in case readlink doesn't exist.
function readlink_func \
{
    if have readlink ; then
        readlink "$1"
    #elif have perl ; then # seems slower than alternative
    #  perl -e 'print readlink("'"$1"'") . "\n"'
    else
        \ls -l "$1" | sed 's/[^>]*-> //'
    fi
}

# This is a `realpath` replacement, since realpath is a rare utility.
# Essentially, you feed it a path, and it spits out the same path with all of
# the symbolic links resolved.
# This is a function, rather than broken out into a script, because its used
# by add_to_path_file(), and if it was a script, using it would cause an
# infinite loop.
function realpath_func \
{
    local input="${1}"
    local output="/"
    if [ -d "$input" -a -x "$input" ] ; then
        # All too easy...
        output=`( cd "$input"; \pwd -P )`
    else
        # sane-itize the input to the containing folder
        input="${input%%/}"
        local fname="${input##*/}"
        input="${input%/*}"
        if [ ! -d "$input" -o ! -x "$input" ] ; then
            echo "$input is not an accessible directory" >&2
            return
        fi
        output="`( cd "$input" ; \pwd -P )`/"
        input="$fname"
        # output is now the realpath of the containing folder
        # so all we have to do is handle the fname (aka "input)
        if [ ! -L "$output$input" ] ; then
            output="$output$input"
        else
            input="`readlink_func "$output$input"`"
            while [ "$input" ] ; do
                if [[ $input == /* ]] ; then
                    output="$input"
                    input=""
                elif [[ $input == ../* ]] ; then
                    output="${output%/*/}/"
                    input="${input#../}"
                elif [[ $input == ./* ]] ; then
                    input="${input#./}"
                elif [[ $input == */* ]] ; then
                    output="$output${input%${input#*/}}"
                    input="${input#*/}"
                else
                    output="$output$input"
                    input=""
                fi
                if [ -L "${output%%/}" ] ; then
                    if [ "$input" ] ; then
                        input="`readlink_func "${output%%/}"`/$input"
                    else
                        input="`readlink_func "${output%%/}"`"
                    fi
                    output="${output%%/}"
                    output="${output%/*}/"
                fi
            done
        fi
    fi
    echo "${output%%/}"
}

# Usage: add_to_path_force PATH /some/directory
# This adds /some/directory to the end of PATH, but if /some/directory is
# already in PATH, it does nothing
function add_to_path_force \
{
    if eval '[[' -z "\$$1" ']]'; then
        eval "export $1='$2'"
    elif ! eval '[[' \
        -z "\"\${$1##*:\$2:*}\"" '||' \
        -z "\"\${$1%%*:\$2}\"" '||' \
        -z "\"\${$1##\$2:*}\"" '||' \
        "\"\${$1}\"" '==' "\"$2\"" ']]'; then
        eval "export $1=\"\$$1:$2\""
    fi
}

# Usage: add_to_path PATH /some/directory
# This adds /some/directory to the end of PATH, but if /some/directory is
# already in PATH, it does nothing
function add_to_path \
{
    local folder="${2%%/}"
    [ -d "$folder" -a -x "$folder" ] || return
    folder=`( cd "$folder" ; \pwd -P )`
    add_to_path_force "$1" "$folder"
}


# Usage: add_to_path_file PATH /some/file
# This adds /some/file to the end of PATH, but if /some/file is already
# in PATH, it does nothing.
function add_to_path_file \
{
    local file="${2}"
    [ -f "$file" -a -r "$file" ] || return
    # realpath alias may not be set up yet
    file=`realpath_func "$file"`
    add_to_path_force "$1" "$file"
}

# Usage: add_to_path_first PATH /some/directory
# This adds /some/directory to the *BEGINNING* of PATH, but prevents duplicate
# entries (i.e. duplicates are removed before /some/directory is added to the
# beginning of PATH)
function add_to_path_first \
{
    local folder="${2%%/}"
    [ -d "$folder" -a -x "$folder" ] || return
    folder=`( cd "$folder" ; \pwd -P )`
    # in the middle, move to front
    if eval '[[' -z "\${$1##*:$folder:*}" ']]'; then
        eval "$1=\"$folder:\${$1//:\$folder:/:}\""
        # at the end
    elif eval '[[' -z "\${$1%%*:\$folder}" ']]'; then
        eval "$1=\"$folder:\${$1%%:\$folder}\""
        # no path
    elif eval '[[' -z "\$$1" ']]'; then
        eval "$1=\"$folder\""
        # not in the path
    elif ! eval '[[' -z "\${$1##\$folder:*}" '||' "\$$1" '==' "\"$folder\"" ']]'; then
        eval "export $1=\"$folder:\$$1\""
    fi
}

# This function takes the path named (e.g. MANPATH) and makes sure
# that each item in the path exists, and resolves all symlinks. It also
# eliminates duplicates (with the use of add_to_path).
function verify_path \
{
    # separating cmd out is stupid, but is compatible
    # with older, buggy, bash versions (2.05b.0(1)-release)
    local cmd="echo \$$1"
    local arg="`eval $cmd`"
    eval "$1=\"\""
    while [[ $arg == *:* ]] ; do
        dir="${arg%:${arg#*:}}"
        arg="${arg#*:}"
        if [ "$dir" != "." -a -d "$dir" -a -x "$dir" -a -r "$dir" ] ; then
            dir=`( \cd "$dir" ; \pwd -P )`
            add_to_path "$1" "$dir"
        fi
    done
    if [ "$arg" != "." -a -d "$arg" -a -x "$arg" -a -r "$arg" ] ; then
        arg=`( cd "$arg" ; \pwd -P )`
        add_to_path "$1" "$arg"
    fi
}

dprint Setting up conf funcs ...

function updatesetup {
(
if [ -d ~/.conf_secure/ ] ; then
    cd ~/.conf_secure
    [ "$1" ] && echo .conf_secure...
    cvs -q update
fi
if [ -d ~/.conf/ ] ; then
    cd ~/.conf/
    [ "$1" ] && echo .conf...
    cvs -q update
    bash ./setup.sh
else
    echo CONFIG IS NOT BEING MANAGED!
fi
)
}

function sendsetup {
(
if [ -d ~/.conf_secure/ ] ; then
    cd ~/.conf_secure
    cvs -q commit
fi
if [ -d ~/.conf/ ] ; then
    cd ~/.conf/
    cvs -q commit
else
    echo CONFIG IS NOT BEING MANAGED!
fi
)
}

########################################
# SYSTEM SETTINGS
########################################
dprint Loading system settings ...

# The SYSTEM_BASHRC is to make sure that the /etc/bashrc doesn't
# reload my ~/.bashrc and create a loop (I found a machine where it did)
if [[ -r /etc/bashrc && -z $SYSTEM_BASHRC ]]; then
    dprint " - loading /etc/bashrc"
    . /etc/bashrc
    export SYSTEM_BASHRC=1
fi

#########################################
# BEHAVIORAL SETTINGS
#########################################

shopt -s extglob # Fancy patterns, e.g. +()
# only interactive
if [[ $- == *i* ]]; then
    dprint setting the really spiffy stuff
    shopt -s checkwinsize # don't get confused by resized terminals
    shopt -s checkhash # if hash is broken, doublecheck it
    shopt -s cdspell # be tolerant of cd spelling mistakes
fi

##########################################
# ENVIRONMENT VARIABLES
##########################################

dprint PATH = $PATH

if [[ $TERM == *:* && ( $SSH_CLIENT || $SSH_TTY || $SSH_CLIENT2 ) ]] ; then
    dprint "Smuggled information through the TERM variable!"
    term_smuggling=( ${TERM//:/ } )
    export SSH_LANG=${term_smuggling[1]}
    TERM=${term_smuggling[0]}
    unset term_smuggling
fi

if [[ $OSTYPE == solaris* ]] ; then
    idout=(`/bin/id -a`)
    USER="${idout[0]%%\)*}"
    USER="${USER##*\(}"
    [[ $USER == ${idout[0]} ]] && USER="UnknownUser"
    GROUPNAME="UnknownGroup"
    unset idout
else
    [[ -z $GROUPNAME ]] && GROUPNAME="`id -gn`"
    [[ -z $USER ]] && USER="`id -un`"
fi

# set up the standard variables
dprint term == $TERM

# I tote my own terminfo files around with me
[ -d ~/.terminfo ] && export TERMINFO=~/.terminfo/
[ "$TERM_PROGRAM" == "Apple_Terminal" ] && export TERM=nsterm-16color

MAILPATH=""
MAILCHECK=30
add_to_path_file MAILPATH /var/spool/mail/$USER
add_to_path MAILPATH $HOME/Maildir/
[[ -z $MAILPATH ]] && unset MAILCHECK
[[ -z $HOSTNAME ]] && export HOSTNAME=`/bin/hostname` && echo 'Fake Bash!'
HISTSIZE=1000
HOST=${OSTYPE%%[[:digit:]]*}
OS_VER=${OSTYPE#$HOST}
[ -z "$OS_VER" ] && OS_VER=$( uname -r )
OS_VER=(${OS_VER//./ })
TTY=`tty`
PARINIT="rTbgq B=.,?_A_a P=_s Q=>|}+"

export USER GROUPNAME MAILPATH HISTSIZE OS_VER HOST TTY PARINIT

dprint " - umask"
if [[ $GROUPNAME == $USER && $UID -gt 99 ]]; then
    umask 002
else
    umask 022
fi

if [[ $USER == root ]] ; then
    [[ $SSH_CLIENT || $SSH_TTY || $SSH_CLIENT2  ]] && export TMOUT=600 || export TMOUT=3600
fi

if [[ -z $INPUTRC && ! -r $HOME/.inputrc && -r /etc/inputrc ]]; then
    export INPUTRC=/etc/inputrc
fi

export BASHRCREAD=1

# Source global definitions
if [[ -r /etc/profile && -z $SYSTEM_PROFILE ]]; then
    dprint "- loading /etc/profile ... "
    . /etc/profile
    export SYSTEM_PROFILE=1
fi

if [[ $- == *i* ]]; then
    if [[ $SSH_CLIENT || $SSH_TTY || $SSH_CLIENT2 ]] ; then
        PS1='(\d \T)\n[\u@\h \W]\$ '
    else
        PS1='[\u@\h \W]\$ '
    fi
fi

dprint Manipulating your path ...

verify_path PATH
add_to_path PATH "/usr/local/sbin"
add_to_path PATH "/usr/local/teTeX/bin"
add_to_path PATH "/usr/X11R6/bin"
add_to_path PATH "$HOME/bin"
add_to_path PATH /System/Library/Frameworks/Python.framework/Versions/2.3/bin
add_to_path_first PATH "/sbin"
add_to_path_first PATH "/bin"
add_to_path_first PATH "/usr/sbin"
add_to_path_first PATH "/opt/local/bin"
add_to_path_first PATH "/usr/local/bin"

if [[ $OSTYPE == darwin* ]] ; then
    add_to_path PATH "$HOME/.conf/darwincmds"

    # The XFILESEARCHPATH (for app-defaults and such) is a wonky kind of path
    [ -d /opt/local/lib/X11/app-defaults/ ] && \
        add_to_path_force XFILESEARCHPATH /opt/local/lib/X11/%T/%N
    [ -d /sw/etc/app-defaults/ ] && \
        add_to_path_force XFILESEARCHPATH /sw/etc/%T/%N
    add_to_path_force XFILESEARCHPATH /private/etc/X11/%T/%N
fi

verify_path MANPATH
add_to_path MANPATH "/usr/man"
add_to_path MANPATH "/usr/share/man"
add_to_path MANPATH "/usr/X11R6/man"
add_to_path_first MANPATH "/opt/local/share/man"
add_to_path_first MANPATH "/opt/local/man"
add_to_path_first MANPATH "/usr/local/man"
add_to_path_first MANPATH "/usr/local/share/man"

verify_path INFOPATH
add_to_path INFOPATH "/usr/share/info"
add_to_path INFOPATH "/opt/local/share/info"

export PATH MANPATH INFOPATH

dprint Setting up standard envariables ...

export PAGER='less'
have vim && export EDITOR='vim' || export EDITOR='vi'
if [[ -z $DISPLAY && $OSTYPE == darwin* ]]; then
    processes=`ps ax`
    if [[ ${processes} == *xinit* || ${processes} == *quartz-wm* ]]; then
        export DISPLAY=:0
    else
        unset DISPLAY
    fi
fi
if [[ $HOSTNAME == wizard ]] ; then
    dprint Wizards X forwarding is broken
    unset DISPLAY
fi
export TZ="US/Central"
if [ "${BASH_VERSINFO[0]}" -le 2 ]; then
    export HISTCONTROL=ignoreboth
else
    export HISTCONTROL="ignorespace:erasedups"
fi
export HISTIGNORE="&:ls:[bf]g:exit"
export GLOBIGNORE=".:.."
export CVSROOT=kyle@cvs.memoryhole.net:/home/kyle/cvsroot
export CVS_RSH=ssh
export BASH_ENV=$HOME/.bashrc
add_to_path_file MAILCAPS $HOME/.mailcap
add_to_path_file MAILCAPS /etc/mailcap
add_to_path_file MAILCAPS /usr/etc/mailcap
add_to_path_file MAILCAPS /usr/local/etc/mailcap
export EMAIL='kyle-envariable@memoryhole.net'
export GPG_TTY=$TTY
export RSYNC_RSH="ssh -2 -c arcfour -o Compression=no -x"
if [ -d /opt/local/include -a -d /opt/local/lib ] ; then
    export CPPFLAGS="-I/opt/local/include $CPPFLAGS"
    export LDFLAGS="-L/opt/local/lib $LDFLAGS"
fi
if have glibtoolize ; then
    have libtoolize || export LIBTOOLIZE=glibtoolize
fi

# this is executed before every prompt is displayed
# it's basically for setting the terminal title
if [[ $TERM == xterm* || $OSTYPE == darwin* ]]; then
    export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME/.*/}: ${PWD/${HOME}/~}\007"'
else
    unset PROMPT_COMMAND
fi

# I prefer using terminals capable of displaying UTF-8 characters
# e.g. uxterm or urxvt or whatever
# This should make sure that LC_CTYPE is set correctly
if [[ $HOSTNAME == marvin ]] ; then
    unset LANG
fi
if [[ -z $LANG ]] ; then
    dprint no LANG set
    if [[ $WINDOWID ]] && have xprop ; then
        dprint querying xprop
        __bashrc__wmlocal=(`xprop -id $WINDOWID -f WM_LOCALE_NAME 8s ' $0' -notype WM_LOCALE_NAME`)
        export LANG=`eval echo ${__bashrc__wmlocal[1]}`
        unset __bashrc__wmlocal
    elif [[ $OSTYPE == darwin* ]] ; then
        dprint "I'm on Darwin"
        if [[ ( $SSH_LANG && \
            ( $SSH_LANG == *.UTF* || $SSH_LANG == *.utf* ) || \
            $TERM_PROGRAM == Apple_Terminal ) && \
            -d "/usr/share/locale/en_US.UTF-8" ]] ; then
            export LANG='en_US.UTF-8'
        elif [ -d "/usr/share/locale/en_US" ] ; then
            export LANG='en_US'
        else
            export LANG=C
        fi
    elif [[ $TERM == linux || $TERM_PROGRAM == GLterm ]] ; then
        if [ -d "/usr/share/locale/en_US" ] ; then
            export LANG='en_US'
        else
            export LANG=C # last resort
        fi
    else
        if have locale ; then
            dprint checking locale from big list
            locales=`locale -a`
            if [[ $SSH_LANG == C ]] ; then
                export LANG=C
            else
                case "$locales" in
                    *en_US.utf8[[:space:]]*|*en_US.utf8)
                    export LANG='en_US.utf8'
                    export LESSCHARSET=utf-8
                    ;;
                    *en_US.utf-8[[:space:]]*|*en_US.utf-8)
                    export LANG='en_US.utf-8'
                    export LESSCHARSET=utf-8
                    ;;
                    *en_US[[:space:]]*|*en_US)
                    export LANG='en_US'
                    ;;
                    *)
                    export LANG=C
                    unset LESSCHARSET
                    ;;
                esac
            fi
            unset locales
        fi
    fi
else
    dprint LANG IS ALREADY SET!
fi
dprint LANG is $LANG

########
# Fink #
########

if [[ -r /sw/bin/init.sh ]] ; then
    dprint Loading fink stuff ...
    . /sw/bin/init.sh
fi

#######################################
# User specific aliases and functions #
#######################################
dprint Setting up aliases ...

function exec_cvim {
/Applications/Vim.app/Contents/MacOS/Vim -g "$@" &
}

# use the new md* commands to use the spotlight database :D
# It's done as a function so I can use command-line arguments
# and single and double quotes.
function darwin_locate { mdfind "kMDItemDisplayName == '$@'wc"; }
if [[ $- == *i* && $OSTYPE == darwin* && ${OS_VER[0]} -ge 8 ]] ; then
alias locate=darwin_locate
fi

# this function is just darn useful sometimes
function printargs { for F in "$@" ; do echo "$F" ; done ; }
function printarray {
for ((i=0;$i<`eval 'echo ${#'$1'[*]}'`;i++)) ; do
    echo $1"[$i]" = `eval 'echo ${'$1'['$i']}'`
done
}

if [[ $- == *i* ]]; then
    alias back='cd $OLDPWD'
    # GNU ls check
    if [[ $OSTYPE == darwin* ]]; then
        dprint "- DARWIN ls"
        alias ls='/bin/ls -FG'
        alias ll='/bin/ls -lhFG'
    elif have colorls ; then
        dprint "- BSD colorls"
        alias ls='colorls -FG'
        alias ll='colorls -lhFG'
    else
        __kbwbashrc__lsarray=(`\type -ap ls`)
        __kbwbashrc__lsfound=no
        for ((i=0;$i<${#__kbwbashrc__lsarray[*]};i=$i+1)) ; do
            if ${__kbwbashrc__lsarray[$i]} --version &>/dev/null ; then
                dprint "- found GNU ls: ${__kbwbashrc__lsarray[$i]}"
                alias ls="${__kbwbashrc__lsarray[$i]} --color -F"
                alias ll="${__kbwbashrc__lsarray[$i]} --color -F -lh"
                __kbwbashrc__lsfound=yes
                break
            fi
        done
        if [ "$__kbwbashrc__lsfound" == no ] ; then
            if ls -F &>/dev/null ; then
                dprint "- POSIX ls"
                alias ls='ls -F'
                alias ll='ls -lhF'
            else
                alias ll='ls -lh'
            fi
        fi
        unset __kbwbashrc__lsarray __kbwbashrc__lsfound
    fi
    if [[ $OSTYPE == linux* ]] ; then
        # actually, just Debian, but this works for now
        alias gv="gv --watch --antialias"
    else
        alias gv="gv -watch -antialias"
    fi
    if have gsed ; then
        alias sed=gsed
    elif have gnused ; then
        alias sed=gnused
    fi
    if have gmake ; then
        alias make=gmake
    elif have gnumake ; then
        alias make=gnumake
    fi
    # Detect the kind of ps
    if [[ $OSTYPE == darwin* ]] ; then
        _PSARGS="-a -w -w -x"
    elif [[ $OSTYPE == linux* ]] ; then
        _PSARGS="awx"
    elif ps awx &>/dev/null ; then
        _PSARGS="awx"
    else
        _PSARGS="ax"
    fi
    eval "function psq { ps ${_PSARGS} | grep -i \$@ | grep -v grep ; }"
    unset _PSARGS
    alias macfile="perl -e 'tr/\x0d/\x0a/'"
    have tidy && alias tidy='tidy -m -c -i'
    have vim && alias vi='vim'
    alias vlock='vlock -a'
    alias fastscp='scp -c arcfour -o Compression=no' # yay speed!
    alias startx='nohup ssh-agent startx & exit'
    alias whatlocale='printenv | grep ^LC_'
    alias fixx='xauth generate $DISPLAY'
    alias whatuses='fuser -v -n tcp'
    alias which=type
    alias ssh='env TERM="$TERM:$LANG" ssh'
    have realpath || alias realpath=realpath_func
    if have readlink ; then
        unset -f readlink_func
    else
        alias readlink=readlink_func
    fi
    if [[ $OSTYPE == darwin* ]]; then
        alias top='top -R -F -ocpu -Otime'
        alias cvim='exec_cvim'
        alias gvim='exec_cvim'
    fi
    if ! have uxterm ; then
        have xterm && alias uxterm="~/.conf/uxterm"
    fi
fi

# useful definitions
completion_options=(
~/.conf/bash_completion
/etc/bash_completion
/opt/local/etc/bash_completion
)
if [[ $BASH_VERSION && -z $BASH_COMPLETION && $- == *i* ]] ; then
    bash=${BASH_VERSION%.*}; bmajor=${bash%.*}; bminor=${bash#*.}
    if [ $bmajor -eq 2 -a $bminor '>' 04 ] || [ $bmajor -gt 2 ] ; then
        for bc in "${completion_options[@]}" ; do
            if [[ -r $bc ]] ; then
                dprint Loading the bash_completion file
                [[ ${BASH_COMPLETION} ]] || BASH_COMPLETION="$bc"
                #COMP_CVS_REMOTE=yes
                export COMP_CVS_ENTRIES=yes
                source "$bc"
                break
            fi
        done
    fi
    unset bash bminor bmajor
fi
unset completion_options
# I want to keep this function available, but it gets undefined
# by the standard bash_completion files.
function have { type "$1" &>/dev/null ; }

dprint checking for bashrc.local in $HOME
if [[ -r ${HOME}/.bashrc.local ]]; then
    dprint Loading local bashrc
    source "${HOME}/.bashrc.local"
fi

if [[ $TMOUT && $- == *i* ]]; then
    echo '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
    echo You will be autologged out after:
    echo -e -n '\t'
    seconds=$TMOUT
    days=$((seconds/60/60/24))
    seconds=$((seconds-days*24*60*60))
    hours=$((seconds/60/60))
    seconds=$((seconds-hours*60*60))
    minutes=$((seconds/60))
    seconds=$((seconds-minutes*60))
    [[ $days != 0 ]] && echo -n "$days days "
    [[ $hours != 0 ]] && echo -n "$hours hours "
    [[ $minutes != 0 ]] && echo -n "$minutes minutes "
    [[ $seconds != 0 ]] && echo -n "$seconds seconds "
    echo
    echo ... of being idle.
    unset days hours minutes seconds
fi
unset -f verify_path
unset SYSTEM_BASHRC SYSTEM_PROFILE

dprint BASHRC_DONE
# vim:set ft=sh