#!/usr/bin/env bash

note() {
    echo -E "$@"
}

warn() {
    echo -E "$@">&2
}

die() {
    warn "$@"
    exit 1
}

dotless() {
    [[ "${1:0:1}" == "." ]] && REPLY="${1:1}" || REPLY="$1"
}

backup() {
    note "backing up $1"
    mkdir -p "${backup_dir:?backup_dir unset}/$(dirname "$1")"
    [ -e "$backup_dir/$1" ] && die "backup already exists"
    mv "$1" "$backup_dir/$1"
}

hardlink() {
    if [ -e "$1" ]; then
        [ "$1" -ef "$2" ] && return
        [ -h "$1" ] && note "removing symbolic link $1" && rm "$1"
        if [ -s "$1" ]; then
            backup "$1" || die "$1 already exists"
        fi
    fi

    ln "$2" "$1" || die "couldn't hardlink $1"
}

softlink_nix() {
    if [ -e "$1" ]; then
        if [ -h "$1" ]; then
            [ "$(readlink "$1")" == "$2" ] && return
            note "removing symbolic link $1"
            rm "$1"
        else
            die "$1 already exists and is not a symbolic link"
        fi
    fi

    ln -s "$2" "$1" || die "couldn't symlink $1"
}

softlink_pseudo() {
    [ -d "$2" ] || die "$1 is not a directory to softlink"

    if [ ! -d "$1" ]; then
        mkdir "$1" || die "couldn't mkdir $1"
    fi

    ls -A "$2" | while read -r; do
        local d1="$1/$REPLY"
        local d2="$2/$REPLY"
        if [ -d "$d2" ]; then
            softlink_pseudo "$d1" "$d2"
        elif [ -f "$d2" ]; then
            hardlink "$d1" "$d2"
        else
            die "i don't know how to pseudo-symlink $d2"
        fi
    done

    ls -A "$1" | while read -r; do
        local d1="$1/$REPLY"
        local d2="$2/$REPLY"
        if [ -d "$d2" ]; then
            :
        elif [ ! "$d1" -ef "$d2" ]; then
            [ "$d1" == ".vim/swp" ] && continue
            [ "$d1" == ".vim/undo" ] && continue
            [ "$d1" == ".vim/.netrwhist" ] && continue
            warn "new destination file. consider manually moving it:"
            warn "$d1"
        fi
    done
}

softlink() {
    if [ -n "$MSYSTEM" ]; then
        # MSYS2 does not have nor emulate symbolic links.
        softlink_pseudo "$@"
    else
        softlink_nix "$@"
    fi
}

which readlink >/dev/null || exit 1

rc="$(readlink -f "$(dirname "$0")" )"
cd "$HOME"
PATH="${PATH:?No existing PATH}:$rc/sh"

backup_dir="$rc/backup-$(date '+%s')"

for f in .bashrc .zshrc .-shrc .streamcrap .ea .vimrc \
  .inputrc .Xresources .screenrc .indent.pro .uncrustify.cfg; do
    dotless "$f"
    r="$rc/home/$REPLY"
    hardlink "$f" "$r"
done

for d in sh .vim .mpv; do
    dotless "$d"
    r="$rc/$REPLY"
    softlink "$d" "$r"
done

grep .bashrc .bash_profile >/dev/null 2>&1 \
 || echo -e '\n[[ -f ~/.bashrc ]] && . ~/.bashrc' >> .bash_profile

for d in Desktop Documents Downloads Music Pictures Public Templates Video Videos; do
    [ -d "$d" ] || continue
    is_empty "$d" && rm -r "$d" || note "skipping unempty $d"
done

mkdir -p opt/local/bin src work play