#!/bin/bash -

# File: setup-links-to-dropbox.sh
# Copyright (c) 2018-2019 Justin Hanekom <justin_hanekom@yahoo.com>
# Licensed under the MIT License

# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# Setup a safe Bash scripting environment

set -o errexit      # Exit immediately if an error occurs
set -o noclobber    # Do not allow files to be overwritten via redirect
set -o nounset      # Do not allow unset variables

# Set the exit code of a pipeline to the rightmost non-zero on error
set -o pipefail
#set -o xtrace       # Trace script execution (i.e., debug mode)
# Set the internal field separator to newline or tab, but not space
IFS=$'\n\t'

# Setup a secure Bash scripting environment by: setting a secure path;
# clearing all aliases; clearing the command path hash; setting the hard limit
# to 0 to turn off core dumps; and setting a secure umask

PATH=$(PATH='/bin:/usr/bin' getconf PATH); export PATH
builtin unalias -a
hash -r
ulimit -H -c 0 --

UMASK=002
umask ${UMASK}

# Constant definitions

readonly COMMON_LINK_DIRS=( 'Documents' 'Music' 'Pictures' 'src' 'Videos' )

readonly LINUX_LINK_DIRS=( 'bin' 'Downloads' '.gnupg' '.m2' '.pki' 'sbin' \
    '.ssh' '.vim' 'VirtualBox VMs' )

readonly ALL_LINK_DIRS=( "${COMMON_LINK_DIRS[@]}" "${LINUX_LINK_DIRS[@]}" )

readonly LINUX_LINK_FILES=( '.bash_justin' '.gitconfig' '.gitignore' \
    '.hgignore' '.hgrc' '.perltidyrc' 'hosts' '.tmux.conf' '.vimrc' )
readonly STARTED_AT=$(date '+%s')

################################################################################
# Function:     chomp_slash
# Description:  Removes any trailing slash ("/") from a string
# Arguments:    $1 :- String from which to remove any trailing slashes
# Ouputs:       Prints string with trailing slashes removed
function chomp_slash {
    local dir="$1"
    while [ "${dir:(-1)}" = '/' ]; do
        dir=${dir::-1}
    done
    echo "$dir"
}

################################################################################
# Function:     trim
# Description:  Trims any/all whitespace from the beginning and end of a string
# Arguments:    $1 :- The string from which to trim whitespace
# Outputs:      Prints string with any leading/trailing whitespace removed
function trim {
    local str="$1"
    str="${str#"${str%%[![:space:]]*}"}"
    str="${str%"${str##*[![:space:]]}"}"
    echo "$1"
}

# Parse the command-line options

readonly OPTIONS='s:d:rv'
readonly LONGOPTS='srcdir:,destdir:,test-run,remove,verbose'

if ! readonly PARSED_OPTIONS=$(getopt --options=${OPTIONS} \
                                --longoptions=${LONGOPTS} \
                                --name "$(basename "$0")" -- "$@"); then
    echo 'Unknown error parsing getopt options. Exiting.' >&2
    exit 2
fi

eval set -- "${PARSED_OPTIONS}"

# Extract command-line options and their arguments, if applicable

destdir=$(chomp_slash "${HOME}")
srcdir=$(chomp_slash "${destdir}/Dropbox/Justin")
is_remove=''
is_verbose=''

while (( $# >= 1 )); do
    case "$1" in
        -s|--srcdir)
            srcdir=$(chomp_slash "$(trim "$2")") ; shift 2
            ;;
        -d|--destdir)
            destdir=$(chomp_slash "$(trim "$2")") ; shift 2
            ;;
        -r|--remove)
            is_remove='true' ; shift
            ;;
        -v|--verbose)
            is_verbose='true' ; shift
            ;;
        --)
            shift ; break
            ;;
        *)
            echo "Unrecognized option: <$1>. Exiting" >&2 ; exit 3
            ;;
    esac
done

readonly COMMON_DIR="${srcdir}/Common"
readonly LINUX_DIR="${srcdir}/Linux"

if [ -n "${is_verbose}" ]; then
    readonly VERBOSE_FLAG='--verbose'
else
    readonly VERBOSE_FLAG=''
fi

# Optionally remove any files or directories
# that would cause this script to abort

if [ -n "${is_remove}" ]; then
    for d in "${ALL_LINK_DIRS[@]}" ; do
        sudo rm --force --recursive ${VERBOSE_FLAG} "${destdir}/$d"
    done

    for f in "${LINUX_LINK_FILES[@]}" ; do
        sudo rm --force ${VERBOSE_FLAG} "${destdir}/$f"
    done
fi

# Create symbolic links from each of the Dropbox common directories

for d in "${COMMON_LINK_DIRS[@]}" ; do
    sudo ln --symbolic ${VERBOSE_FLAG} "${COMMON_DIR}/$d" "${destdir}/$d"
done

# Create symbolic links from each of the Dropbox Linux directories

for d in "${LINUX_LINK_DIRS[@]}" ; do
    sudo ln --symbolic ${VERBOSE_FLAG} "${LINUX_DIR}/$d" "${destdir}/$d"
done

# Create symbolic links from each of the Dropbox Linux files

for f in "${LINUX_LINK_FILES[@]}" ; do
    sudo ln --symbolic ${VERBOSE_FLAG} "${LINUX_DIR}/$f" "${destdir}/$f"
done

# Report that we are done, and how long the script took

if [ -n "$IS_VERBOSE" ]; then
    readonly ENDED_AT=$(date '+%s')
    readonly DIFF=$(( ${ENDED_AT} - ${STARTED_AT} ))
    echo "Done, in ${DIFF} seconds"!
fi

# vim: set filetype=sh autoread expandtab smarttab softtabstop=4 shiftwidth=4 tabstop=4 autoindent smartindent