#!/usr/bin/env bash

version=0.3
dots_conf_file=${HOME}/.dots.conf
dots_local_repo=${HOME}/.local/share/dots
unwanted_files=( .netrwhist )

# Color scheme
R="\e[31m"  # red
G="\e[32m"  # green
Y="\e[33m"  # yellow
B="\e[94m"  # light blue
M="\e[95m"  # light magenta
C="\e[36m"  # cyan
Gr="\e[37m" # grey
N="\e[0m"   # no color
b="\e[1m"   # bold font

dots_version() {
    echo dots $version; exit 0
}

dots_help() {
    cat <<- EOF
Save and push dotfiles.

Usage: dots [-vh] command

Commands:
    save    copy dotfiles to local repo (${dots_local_repo//$HOME\//\~\/})
    push    commit and push dotfiles to remote git repo.
    show    run 'git status' and print information about local repo.
    diff    run 'git diff' in local repo.

Options:
    -v, --version   print version and exit.
    -h, --help      print this message and exit.
EOF
    exit 0
}

dots_init() {
    if [ -f "$dots_conf_file" ]; then
        :   # do nothing
    else
        echo -e "${R}${dots_conf_file} doesn't exist\n" >&2
        echo -e "${dots_conf_file} content example:" >&2
        echo "  .bashrc" >&2
        echo "  .bash_aliases" >&2
        echo -e "${N}"
        exit 1
    fi

    if [ -d "${dots_local_repo}/.git" ]; then
        :   # do nothing
    else
        echo -e "${b}Init new ropository in${N} ${dots_local_repo}"
        mkdir -p "$dots_local_repo"
        echo -e "${B}; git init${N}"
        git init "$dots_local_repo"
    fi
}

dots_clean() {
    # Remove confidential data from .bash* files.
    # `# Work` comment is trigger. Everything after this
    # comment to end of file will be deleted.

    echo -e "\nClean up restricted data from ${b}.bash*${N} files ..."
    for bashfile in `find ${dots_local_repo} -type f -name ".bash*"`; do
        lnnum=`cat "$bashfile" | grep '# Work' -n | cut -d ':' -f 1`
        if grep '# Work' "$bashfile" > /dev/null; then
            echo "--> $bashfile"
        fi
        #echo "LN: $lnnum"
        if [ "$lnnum" != "" ]; then
            sed -i "${lnnum}q" "$bashfile"
        fi
    done
}

dots_remove_unwanted() {
    echo -e "${b}Remove unwanted files ...${N}"
    echo -e "${B}; find $dots_local_repo -name {...} -delete -print${N}"
    for unwanted in "${unwanted_files[@]}"; do
        find "$dots_local_repo" -name "$unwanted" -delete -print
    done
}

dots_save() {
    dots_init

    echo -e "${b}Copy dotfiles to repo${N}..."
    echo -e "${B}; cp --parents --recursive {...} ${dots_local_repo}${N}"
    for dotfile in $(cat "$dots_conf_file"); do
        cp  --parents --recursive "${HOME}/${dotfile}" "${dots_local_repo}/"
            #echo -e "${G}${dotfile}${N}"
    done

    dots_remove_unwanted # Remove unwanted files from local repo

    echo -e "${B}; tree -a -F -I .git${N}"
    tree -a -F -I .git "$dots_local_repo"

    dots_clean  # Remove confidential data from local repo

    echo -e "\nDone!"

    echo -e "\n${b}Tips:${N}" \
        "\n    Use ${M}${b}dots show${N} to run ${C}'git status'${N}" \
            "or ${M}${b}dots diff${N} to run ${C}'git diff'${N} in local repo." \
        "\n    Use ${M}${b}dots push${N} to commit and push to remote repo."
}

dots_push() {
    echo -e "${b}---${N}"
    echo -e "${B}; git add -A${N}"
    git -C "${dots_local_repo}" add -A
    echo -e "${B}; git commit -m 'Update dotfiles'${N}"
    git -C "${dots_local_repo}" commit -m 'Update dotfiles'

    local remote="$(git -C "${dots_local_repo}" remote show)"
    if [ "$remote" == "" ]; then
        echo -e "${b}Add new remote server:${N}"
        echo -e \
        "Paste address like: ${Gr}git@github.com:user/repo.git${N} below:"
        while true; do
            read remote_addr
            if [[ "$remote_addr" =~ .*/.*\.git ]]; then
                break
            else
                echo "Please, re-enter remote address:"
            fi
        done
        echo -en "${B}; git remote add dots-repo ${remote_addr}${N} ... "
        git -C "${dots_local_repo}" remote add dots-repo "$remote_addr"
        echo -e "${G}${b}OK${N}"
    else
        :   # do nothing
    fi

    echo -e "${b}Processing${N}..."
    echo -e "${B}; git push dots-repo master${N}"
    git -C "${dots_local_repo}" push -u dots-repo master
}

dots_show() {
    echo -e "${b}Config:${N} $dots_conf_file"
    echo -e "${b}Local repo:${N} $dots_local_repo"
    echo -e "${B}; git status${N}"
    git -C "$dots_local_repo" status
}

dots_diff() {
    echo -e "${b}Config:${N} $dots_conf_file"
    echo -e "${b}Local repo:${N} $dots_local_repo"
    echo -e "${B}; git diff${N}"
    git -C "$dots_local_repo" diff "$@"
}

[[ ! "$@" ]] && dots_help

while (( "$#" )); do
    case "$1" in
        save)   shift; dots_save "$@"; shift "$#";;
        push)   shift; dots_push "$@"; shift "$#";;
        show)   shift; dots_show "$@"; shift "$#";;
        diff)   shift; dots_diff "$@"; shift "$#";;
        -v|--version)      dots_version      ;;
        -h|--help)         dots_help         ;;
        -*) echo "$1: bad option" >&2; exit 1;;
        *)  args+=("$1"); shift;;
    esac
done
