#!/usr/bin/env bash

##############################################################
#                                                            #
#  Darkcloud Vim Config: update script                       #
#                                                            #
#  By: Kevin MacMartin (prurigro@gmail.com)                  #
#  Website: https://github.com/prurigro/darkcloud-vimconfig  #
#                                                            #
#  License: MIT                                              #
#                                                            #
##############################################################

cd $(dirname "$0")

### BEGIN: VARIABLES ###
# user variables (these can be edited)
ERRORLOG="update-errors.log" # set the error log filename

# script variables (these should not be touched)
VERSION=$(printf "%s.r%s" "$(git show -s --format=%ci master | sed 's/\ .*//g;s/-//g')" "$(git rev-list --count HEAD)")
SCRIPT_NAME=$(grep -o -e "[^\/]*$" <<< "$0")
SCRIPT_HOME=$(pwd)
### END: VARIABLES ###

### BEGIN: FUNCTIONS ###
# command_parse "$@": configures environment using arguments
function command_parse {
    for param in $@; do
        case "$param" in
            -n|--no-color|--no-colour)
                NO_COLOUR=true
                ;;
            -h|--help)
                SHOW_HELP=true
                ;;
            -v|--version)
                SHOW_VERSION=true
                ;;
            *)
                ERROR="\"${param}\" is not a valid argument"
                ;;
        esac
    done
}

# error "file/command" "error output" "note": output and log error
function error() {
    echo -e "${HEADINGCOLOUR} ${RESETCOLOUR}${ERRORCOLOUR} ! ERROR: ${RESETCOLOUR}${FAILCOLOUR} ${2} "
    echo -e "${HEADINGCOLOUR} ${RESETCOLOUR}${ERRORCOLOUR} ! COMMAND: ${RESETCOLOUR} ${NOACTIONCOLOUR}=> ${1}${RESETCOLOUR}"
    [[ -n "$3" ]] && echo -e "${HEADINGCOLOUR} ${RESETCOLOUR}${ERRORCOLOUR} ! OUTPUT: ${RESETCOLOUR}${NOACTIONCOLOUR} ${3}"

    echo "DATE: @ $(date)" >> "${SCRIPT_HOME}/${ERRORLOG}"
    echo "ERROR: ${2}" >> "${SCRIPT_HOME}/${ERRORLOG}"
    echo "COMMAND: ${1}" >> "${SCRIPT_HOME}/${ERRORLOG}"
    [[ -n "$3" ]] && echo "OUTPUT: ${3}" >> "${SCRIPT_HOME}/${ERRORLOG}"
    echo >> "${SCRIPT_HOME}/${ERRORLOG}"
}

# show_version: displays version information
function show_version() {
    echo -e "Update tool for darkcloud-vimconfig (${SCRIPT_NAME}) v${VERSION}\n"
}

# show_help: this function displays help output
function show_help() {
    echo -e "Usage: ${SCRIPT_NAME} [OPTION]\n"
    echo "    Options:"
    echo -e "\t-n, --no-colour (or --no-color)\n\t\tdisable colour output\n"
    echo -e "\t-v, --version\n\t\toutput version information and exit\n"
    echo -e "\t-h, --help\n\t\tdisplay this help and exit\n"
    echo -e "\tRun with no arguments to update darkcloud-vimconfig\n"
}
### END: FUNCTIONS ###

### BEGIN: SETUP ###
# change to the base darkcloud-vimconfig folder
cd "$SCRIPT_HOME"

# delete old error log if it exists
[[ -f "$ERRORLOG" ]] && rm "${SCRIPT_HOME}/${ERRORLOG}"

# parse for arguments (then handle them below)
[[ ! -z "$@" ]] && command_parse "$@"

# set colour for output unless an argument was given to disable it
if [ ! "$NO_COLOUR" = "true" ]; then
    TITLECOLOUR="\e[40m"
    HEADINGCOLOUR="\e[44m"
    SUBHEADINGCOLOUR="\e[43m"
    SUCCESSCOLOUR="\e[1;32m"
    FAILCOLOUR="\e[1;31m"
    NOACTIONCOLOUR="\e[1;37m"
    ERRORCOLOUR="\e[1;41m"
    RESETCOLOUR="\e[0m"
else
    HEADINGCOLOUR="#"
fi

# display an error, help then exit when invalid argument(s) are given
[[ -n "$ERROR" ]] && error "$ERROR" "Invalid option supplied at runtime" && echo && show_help && exit 1

# show the help and exit when an argument has been given to do so
[[ "$SHOW_HELP" = "true" ]] && show_version && show_help && exit 0

# show version information and exit when an argument has been given to do so
[[ "$SHOW_VERSION" = "true" ]] && show_version && exit 0

echo -e "\n${TITLECOLOUR} ~~~ DarkCloud Vimconfig Update Tool ~~~ ${RESETCOLOUR}"

# create vim/bundle.user and vim/vimrc.user if either don't exist
if [ ! -d vim/bundle.user ]; then
    echo -n -e "\n${HEADINGCOLOUR} >> Creating User Plugin Directory:${RESETCOLOUR}"
    PROCESS_STATUS=$(install -d vim/bundle.user 2>&1)
    if [ $? = 0 ]; then
        echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
    else
        echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
        error "install -d vim/bundle.user" "User plugin directory couldn't be created" "$PROCESS_STATUS"
    fi
fi
if [ ! -e vim/vimrc.user ]; then
    echo -n -e "\n${HEADINGCOLOUR} >> Creating User Config File:${RESETCOLOUR}"
    PROCESS_STATUS=$(touch vim/vimrc.user 2>&1)
    if [ $? = 0 ]; then
        echo -e '"Autostart Filer in empty buffers: (*1:filer loads in new empty buffers | 0:filer must be triggered)\n"let g:autostartfiler=1\n' >> vim/vimrc.user
        echo -e '"Autocheck syntax checking: (1:start toggled on | *0:start toggled off)\n"let g:autostartchecker=0\n' >> vim/vimrc.user
        echo -e '"Autoload Tagbar: (1:start open | *0:start closed)\n"let g:autostarttagbar=0\n' >> vim/vimrc.user
        echo -e '"Disable automatic tag generation and highlighting: (1:force disabled tag generation and highlighting | *0:enable automatic tag generation and highlighting)\n"let g:disableautotags=0\n' >> vim/vimrc.user
        echo -e '"Disable automatic linebreaking: (1:force disabled globally | *0:let the filetype decide)\n"let g:disablelinebreaks=0\n' >> vim/vimrc.user
        echo -e '"Enable Powerline fonts: (1:expect powerline font | *0:expect regular font)\n"let g:powerlinefonts=0 "(set powerline font for gvim and terminal when enabled)\n' >> vim/vimrc.user
        echo -e '"GVim font selection: (Escaping spaces and use powerline if appropriate)\nset guifont=Monospace\ 12' >> vim/vimrc.user
        echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
    else
        echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
        error "touch vim/vimrc.user" "User config couldn't be created" "$PROCESS_STATUS"
    fi
fi
### END: SETUP ###

### BEGIN: REPO UPDATE ###
echo -n -e "\n${HEADINGCOLOUR} >> Updating Repository:${RESETCOLOUR}"
PROCESS_STATUS=$(git pull origin master 2>&1)
if [ $? = 0 ]; then
    echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
else
    echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
    error "git pull origin master" "Git failed to sync the repo" "$PROCESS_STATUS"
    exit 1
fi
### END: REPO UPDATE ###

### BEGIN: SUBMODULE UPDATE ###
# synchronize the repo urls for each submodule using the ones in .gitmodules
echo -e "\n${HEADINGCOLOUR} >> Updating Plugin Submodules >> ${RESETCOLOUR}"
echo -n -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} + Updating Plugin URLs:${RESETCOLOUR}"
PROCESS_STATUS=$(git submodule sync 2>&1)
if [ $? = 0 ]; then
    echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
else
    echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
    error "git submodule sync" "Git failed to sync the submodules" "$PROCESS_STATUS"
fi

# update each submodule to the new head and run 'git fetch --all'
echo -n -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} + Fetching Updates:${RESETCOLOUR}"
PROCESS_STATUS=$(git submodule foreach git fetch --all 2>&1)
if [ $? = 0 ]; then
    PROCESS_STATUS=$(git submodule update --init --recursive 2>&1)
    if [ $? = 0 ]; then
        echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
    else
        echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
        error "git submodule update --init --recursive" "Git failed to update the submodules" "$PROCESS_STATUS"
    fi
else
    echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
    error "git submodule foreach git fetch --all" "Git failed to fetch the submodules from their respective remotes" "$PROCESS_STATUS"
fi

# run 'git checkout origin/master' on each submodule
echo -n -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} + Checking Out Updates:${RESETCOLOUR}"
PROCESS_STATUS=$(git submodule foreach git checkout -f origin/master 2>&1)
if [ $? = 0 ]; then
    echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
else
    echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
    error "git submodule foreach git checkout -f origin/master" "Git failed to checkout the submodules into origin/master" "$PROCESS_STATUS"
fi

# clean plugin directories and remove plugins no longer in the repo
echo -e "\n${HEADINGCOLOUR} >> Cleaning Plugin Directories >> ${RESETCOLOUR}"
echo -n -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} + Removing Untracked Files:${RESETCOLOUR}"
git submodule foreach git clean -dxf > /dev/null 2>&1 && echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}" || echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
[[ -f .gitmodules ]] && for each in vim/bundle/*; do
    if [ -d "$each" ]; then
        if [ -f "${each}/.git" ]; then
            FILE=$(echo $each | grep -o -e "[^\/]*$")
            if [ $(cat .gitmodules | grep "path = " |  grep -o -e "[^\/]*$" | grep -c -e "${FILE}$") = 0 ]; then
                [[ -z "$FIRST_OLD" ]] && export FIRST_OLD=1 && echo -n -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} + Removing Old Plugins: ${RESETCOLOUR}\n"
                PROCESS_STATUS=$(rm -rf "$each")
                if [ $? = 0 ]; then
                    echo -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} = ${RESETCOLOUR}$(echo ${each}\  | sed -re 's|^(.*)/([^/]*)$|\\e\[1;37m\1/\\e\[1;31m\2\\e\[0m|')"
                else
                    error "rm -rf ${each}" "Folder couldn't be deleted" "$PROCESS_STATUS"
                    exit 1
                fi
            fi
        fi
    fi
done && echo
### END: SUBMODULE UPDATE ###

### BEGIN: USER PLUGIN UPDATE ###
if [ -d vim/bundle.user ]; then
    if [ ! $(find vim/bundle.user | grep ".git/config" | wc -l) = 0 ]; then
        echo -e "${HEADINGCOLOUR} >> Updating User Plugins >> ${RESETCOLOUR}"
        pushd vim/bundle.user > /dev/null 2>&1
            for each in *; do
                if [ -d "$each" ]; then
                    pushd "$each" > /dev/null 2>&1
                        if [ -d .git  ]; then
                            echo -n -e "${HEADINGCOLOUR} ${RESETCOLOUR}${SUBHEADINGCOLOUR} + Updating 'vim/bundle.user/${each}':${RESETCOLOUR}"
                            PROCESS_STATUS=$(git pull origin master 2>&1)
                            if [ $? = 0 ]; then
                                if [ $(echo $PROCESS_STATUS | grep -c "Already up-to-date") = 0 ]; then
                                    echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
                                else
                                    echo -e "${NOACTIONCOLOUR} UP TO DATE ${RESETCOLOUR}"
                                fi
                            else
                                error "git pull origin master" "Failed pulling changes for ${each}" "$PROCESS_STATUS"
                            fi
                        fi
                    popd > /dev/null 2>&1
                fi
            done
        popd > /dev/null 2>&1
        echo
    fi
fi
### END: USER PLUGIN UPDATE ###

### BEGIN: GENERATE PLUGIN HELPTAGS ###
if [ $(type -P vim) ]; then
    echo -n -e "${HEADINGCOLOUR} >> Generating Plugin Help:${RESETCOLOUR}"
    timeout --foreground 2m vim -c "Helptags|qa!" &> /dev/null
    if [ $? = 0 ]; then
        echo -e "${SUCCESSCOLOUR} SUCCESS! ${RESETCOLOUR}"
    else
        reset -I
        echo -e "${FAILCOLOUR} FAIL! ${RESETCOLOUR}"
        error "vim -c \"Helptags|qa!\"" "Generating helpdocs for the submodules failed"
    fi
fi
### END: GENERATE PLUGIN HELPTAGS ###

echo -e "\n${TITLECOLOUR} ~~~ Update Complete ~~~ ${RESETCOLOUR}\n"
exit 0