#!/usr/bin/bash

# This project is licensed under the MIT License (see LICENSE).

set -euo pipefail

readonly VERSION=v0.2.0

TOOLBOX_DOCKERFILE="${TOOLBOX_DOCKERFILE:-Dockerfile.toolbox}"
TOOLBOX_SSHFILE="${TOOLBOX_SSHFILE:-.ssh.toolbox}"
RPKG_SPEC_EXT="${RPKG_SPEC_EXT:-rpkg.spec}"

usage() {
    echo 'usage: tb [command]

With no command, enter toolbox.

commands:
  init IMAGE      Initialize Dockerfile based on IMAGE
  create [IMAGE]  Create container (from IMAGE if provided)
  recreate        Remove and recreate container
  build           Build image
    options:
      -n NAME       Name of image
      -c            Build without cache
  rebuild         Remove container and rebuild image
    options:
      -n NAME       Name of image
      -c            Build without cache
  stop            Stop container
  rm              Remove container
  rmi             Remove image
  rpkg            Build rpm via rpkg
    options:
      -n NAME       rpkg spec template name
      -e EXT        rpkg spec template extension
  rpkg-install    Build and install rpm via rpkg
    options:
      -n NAME       rpkg spec template name
      -e EXT        rpkg spec template extension
      -r NAME       Name of produced rpm to install
  run COMMAND     Run COMMAND in toolbox
  version         Show version'
}

dir_name() {
    echo "${PWD##*/}"
}

image_name() {
    echo "$(dir_name)"-toolbox
}

container_name() {
    echo "$(image_name)"-latest
}

img_exists() {
    podman image exists "$1"
}

enter() {
    c="$(container_name)"
    echo 'Entering toolbox...'
    if [[ -n "${SSH_CONNECTION-}" ]]; then
        echo "# Generated by toolboxcutter.
export HOSTNAME="$HOSTNAME"
export SSH_CONNECTION='$SSH_CONNECTION'" > "$TOOLBOX_SSHFILE"
    fi
    podman container exists "$c" || create && toolbox enter --container "$c"
    [[ -e "$TOOLBOX_SSHFILE" ]] && rm -f "$TOOLBOX_SSHFILE"
    exit $?
}

init() {
    if [[ -z "${1-}" ]]; then
        echo 'requires image argument' >&2
        return 1
    fi
    if [[ -e "$TOOLBOX_DOCKERFILE" ]]; then
        echo "$TOOLBOX_DOCKERFILE already exists" >&2
        return 1
    fi
    echo "FROM $1" > "$TOOLBOX_DOCKERFILE"
    $EDITOR "$TOOLBOX_DOCKERFILE"
    enter
}

build() {
    while getopts ':cn:' opt "$@"; do
        case $opt in
            c) no_cache=true ;;
            n) name="$OPTARG" ;;
        esac
    done

    if [[ -e "$TOOLBOX_DOCKERFILE" ]]; then
        podman build ${no_cache+--no-cache} \
          -f "$TOOLBOX_DOCKERFILE" \
          -t "${name:-$(image_name)}" .
    else
        echo "$f does not exist" >&2
        return 1
    fi
}

create() {
    local i="$(image_name)"
    local cmd=(toolbox create)
    if [[ -n "${1-}" ]]; then
        cmd+=(--image "$1")
    elif img_exists "$i" || build -n "$i"; then
        cmd+=(--image "$i":latest)
    else
        return 1
    fi
    ${cmd[@]}
}

container() {
    local c="$(container_name)"
    if [[ "$1" == rm || "$1" == stop ]]; then
        podman ps | grep -q "$c" && podman container stop "$c"
    fi
    if [[ "$1" == rm ]] && podman container exists "$c"; then
        podman container rm "$c"
    fi
}

rm_image() {
    local i="$(image_name)"
    container rm
    img_exists "$i" && podman image rm "$i"
}

rpkg_local() {
    local cmd=$1
    shift

    local spec_name="$(dir_name)"
    local spec_ext="$RPKG_SPEC_EXT"

    while getopts ':n:e:r:' opt "$@"; do
        case $opt in
            n) spec_name="$OPTARG" ;;
            e) spec_ext="$OPTARG" ;;
            r) rpm_name="$OPTARG" ;;
        esac
    done

    local i="$(image_name)"
    img_exists "$i" || build -n "$i" || return 1

    local spec="$(find . -maxdepth 2 -name "$spec_name.$spec_ext")"
    if [[ -z "$spec" ]]; then
        echo 'rpkg spec template not found' >&2
        return 1
    fi

    local out="$(mktemp --tmpdir -d "$spec_name"-XXX)"

    podman run --rm -v "$out":/out:Z -v "$PWD":/rpkg:Z -w /rpkg \
        "$(image_name)" rpkg local --spec "$spec" --outdir /out

    [[ $? -eq 0 ]] || return $?

    if [[ ${cmd-} == 'install' ]]; then
        local rpms="$(find $out \
            -regextype posix-extended \
            -regex \
            "$out/($(uname -m)|noarch)/${rpm_name-$spec_name}"'-[0-9\.].*\.rpm')"
        if [[ -z "$rpms" ]]; then
            echo 'no rpms found' >&2
            return 1
        fi
        sudo dnf install --setopt=install_weak_deps=False $rpms
    fi
}

if [[ -n "${TOOLBOX_PATH-}" ]]; then
    echo 'Already in a toolbox' >&2
    exit 2
fi

[[ $# -eq 0 ]] && enter

case "$1" in
    init) shift; init "${1-}" ;;
    create) shift; create "${1-}" ;;
    recreate) container rm; create ;;
    build) shift; build "$@" ;;
    rebuild) shift; container rm; build "$@"; create ;;
    stop|rm) container "$1" ;;
    rmi) rm_image ;;
    rpkg) shift; rpkg_local build "$@";;
    rpkg-install) shift; rpkg_local install "$@";;
    run) shift; toolbox run -c "$(container_name)" "$@" ;;
    version) echo "$VERSION"; exit ;;
    *) usage >&2; exit 2
esac
