#!/usr/bin/env bash

brt_run_shell() {
  local sh="${SHELL:-/bin/bash}"
  local base="${sh##*/}"

  case "$base" in
    zsh) zsh -ic "$1" ;;
    bash) bash -ic "$1" ;;
    *) bash -c "$1" ;;
  esac
}

brt_run_split_chain() {
  local chain="$1"
  local part
  local IFS=';'
  read -ra parts <<< "$chain"
  for part in "${parts[@]}"; do
    part="${part#"${part%%[![:space:]]*}"}"
    part="${part%"${part##*[![:space:]]}"}"
    [[ -n "$part" ]] || continue
    printf '%s\0' "$part"
  done
}

brt_run_build_script() {
  local -a parts=("$@")
  local part script="" idx=1

  for part in "${parts[@]}"; do
    if [[ "$part" =~ ^wait[[:space:]]+([0-9]+(\.[0-9]+)?)$ ]]; then
      local secs="${BASH_REMATCH[1]}"
      script+="printf '%b\\n' '\033[36m●\033[0m Waiting ${secs}s...'; sleep ${secs};"
      continue
    fi
    if [[ "$part" == wait ]]; then
      brt_error "wait requires seconds: wait 5"
      exit 1
    fi
    script+="printf '%b\\n' '\033[36m●\033[0m [${idx}] ${part//\'/\'\\\'\'}';"
    script+="${part};"
    script+='_brt_run_rc=$?; if (( _brt_run_rc != 0 )); then exit $_brt_run_rc; fi;'
    ((idx++))
  done

  printf '%s' "$script"
}

brt_run_from_args() {
  local -a parts=()
  local buf=""

  while (($#)); do
    if [[ "$1" == "wait" ]]; then
      [[ -n "$buf" ]] && parts+=("$buf") && buf=""
      if (( $# < 2 )) || ! [[ "$2" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
        brt_error "wait requires seconds: brt -run ... wait 2 ..."
        exit 1
      fi
      parts+=("wait $2")
      shift 2
      continue
    fi
    if [[ -n "$buf" ]]; then
      buf+=" $1"
    else
      buf="$1"
    fi
    shift
  done
  [[ -n "$buf" ]] && parts+=("$buf")

  printf '%s\0' "${parts[@]}"
}

brt_run() {
  if (($# == 0)); then
    brt_error 'Usage: brt -run <cmd;wait N;cmd...>'
    echo 'Examples:'
    echo "  brt -run 'echo hi;wait 2;echo bye'"
    echo '  brt -run echo hi wait 2 echo bye'
    echo '  brt -run my_zsh_function wait 1 other_function'
    exit 1
  fi

  brt_info "Running command chain..."

  local -a parts=()
  if (($# == 1)) && [[ "$1" == *";"* ]]; then
    while IFS= read -r -d '' part; do
      parts+=("$part")
    done < <(brt_run_split_chain "$1")
  else
    while IFS= read -r -d '' part; do
      parts+=("$part")
    done < <(brt_run_from_args "$@")
  fi

  local script status
  script=$(brt_run_build_script "${parts[@]}")
  brt_run_shell "$script"
  status=$?
  if (( status != 0 )); then
    brt_error "Command chain failed with exit code ${status}"
    exit "$status"
  fi

  brt_ok "Chain completed"
}
