#!/usr/bin/env bash

THISSCRIPT=$(realpath $0)
RUNDIR=$(dirname $THISSCRIPT)

ALL_ARGS=("$@")
ARG_COUNT=$#

exit_cleanup() {
    unset -f escape_string
    unset -f temp_filename
    unset -f load_config
    unset -f exec_subcommand

    unset SSPT_DEST_DIR
    unset SSPT_DB_DIR
    unset SSPT_SUB_DIR
    unset SSPT_DL_DIR

    unset SSPT_SRC_DB_FILE
    unset SSPT_BIN_DB_FILE
    unset SSPT_BIN_DB_DIR

    exit $@
}

escape_string() {
    printf '%s' "$@" | sed 's/[.[\*^$()+?{|]/\\&/g'
}
export -f escape_string
temp_filename() {
    echo "/tmp/ssbt-$(cat /dev/urando | head -c 4 | base64)"
}
export -f temp_filename

print_version() {
    (>&2 echo "sspt v0.0.0")
}

print_help() {
    print_version
    (>&2 cat <<EOF
sspt - manage upstream repositories
Usage: $0 [-h|-?|--help]
           Print this help text and exit.
     - $0 [-V|--version]
           Print the version of sspt and exit.
     - $0 [-c|--config] <file>
           Use the specified file as configuration, instead of
           \$XDG_CONFIG_HOME/sspt.conf
     - $0 --mk-default-config
           Create a default config file. The file is placed in
           \$XDG_CONFIG_HOME/sspt.conf , unless --config was specified.
     - $0 --list-subcommands
           List all available subcommands. Subcommands work like they
           do in git, one can define them by creating a sspt-<subcommand>
           and placing it in \$SSPT_SUB_DIR (defined in the sspt config
           file). Note that calling the subcommand files directly is a
           bad idea as the main ssbt script sets up the environment.
     - $0 <subcommand> <options...>
           Execute a subcommand. Use \`$0 <subcommand> --help\' for more
           information about a particular subcommand.
EOF
)
}

if [ $# -eq 0 ]; then
    print_help
    exit_cleanup
fi

CONFIG_PATH="$XDG_CONFIG_HOME"
if [ -z "$CONFIG_PATH" ]; then
    CONFIG_PATH="$HOME/.config"
fi
CONFIG_FILE="$CONFIG_PATH/sspt.conf"

load_config() {
    if ! [ -f "$CONFIG_FILE" ]; then
        (>&2 echo "Config file '$CONFIG_FILE' does not exist!")
        exit_cleanup 1
    fi

    source "$CONFIG_FILE"
}
export -f load_config

exec_subcommand () {
    if [ -z "$SSPT_DEST_DIR" ] || [ -z "$SSPT_DB_DIR" ] || [ -z "$SSPT_SUB_DIR" ] || [ -z "$SSPT_DL_DIR" ]; then
        (>&2 echo "\$SSPT_DEST_DIR or \$SSPT_DB_DIR or \$SSPT_SUB_DIR or \$SSPT_DL_DIR not defined.")
        exit_cleanup 1
    fi

    export SSPT_SRC_DB_FILE="$SSPT_DB_DIR/sources"
    export SSPT_BIN_DB_FILE="$SSPT_DB_DIR/installs"

    if ! [ -f "$SSPT_SRC_DB_FILE" ]; then   touch "$SSPT_SRC_DB_FILE"; fi
    if ! [ -f "$SSPT_BIN_DB_FILE" ]; then   touch "$SSPT_BIN_DB_FILE"; fi

    export SSPT_BIN_DB_DIR="$SSPT_DB_DIR/files"

    if ! [ -d "$SSPT_BIN_DB_DIR" ]; then    mkdir -p "$SSPT_BIN_DB_DIR"; fi

    local SUB_FILE="$SSPT_SUB_DIR/sspt-$1"
    local ALL_ARGS_=("$@")

    command -v "$SUB_FILE" >/dev/null 2>&1 || { (>&2 echo "File '$SUB_FILE' does not exist, cannot execute subcommand '$1'.") } && exit_cleanup 1

    exec $SUB_FILE "${ALL_ARGS_[@]:1}"
    return $?
}
export -f exec_subcommand

ISSUBCMD=""
parse_arg() {
    case $1 in
        -c|--config)
            if [ $# -lt 2 ]; then
                (>&2 echo "No config file path given.")
                exit_cleanup 1
            fi

            CONFIG_FILE="$2"
            return 2
            ;;
        -h|--help|-?)
            print_help
            ;;
        # TODO: -V is borked?
        -V|--version)
            print_version
            ;;
        --list-subcommands)
            # I'm lazy
            load_config
            find -type f -name "sspt-*" "$SSPT_SUB_DIR/"
            ;;
        --mk-default-config)
            if ! [ -d "$CONFIG_PATH" ]; then
                mkdir -p "$CONFIG_PATH"
            fi
            cat > "$CONFIG_FILE" <<EOF
# SSPT_DEST_DIR controls e.g. the PREFIX variable in makefile builds.
# NOTE: This variable is used when configuring packages. If you change
# this, it will not have any effect unless you reconfigure all packages.
export SSPT_DEST_DIR="\$XDG_CONFIG_HOME"
# This directory contains all the subcommand scripts.
export SSPT_SUB_DIR="\$XDG_CONFIG_HOME/libexec/sspt"
# This directory contains all the database files.
export SSPT_DB_DIR="\$XDG_CONFIG_HOME/share/sspt"
# This is where sspt stores the source code of all pacakges.
# You might want to change this.
export SSPT_DL_DIR="\$HOME/src/sspt"
EOF
            ;;
        *)
            load_config
            ISSUBCMD=1
            exec_subcommand $@
            return $?
            ;;
    esac

    return 0
}

main() {
    parse_arg $@
    local RETVAL=$?
    if [ $RETVAL -gt 0 ] && [ -z "$ISSUBCMD" ]; then
        # TODO: make this work with s/2/\$RETVAL/
        local NEW_ARGS="${ALL_ARGS[@]:2}"
        if [ ${#NEW_ARGS[@]} -eq 0 ]; then
            print_help
            exit_cleanup
        fi

        parse_arg ${NEW_ARGS[@]}
    fi
}

main $@

