#!/usr/bin/bash

# shellcheck disable=1090,2034,2154

set -e

export TESTML_VERSION='0.3.0'

TESTML_ROOT=${TESTML_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}
export TESTML_ROOT

main() {
  if is-tty; then
    run-cli "$@"

  else
    check-input-file "$@"

    set-testml-vars

    set-testml-bin

    exec "$TESTML_BIN" "$TESTML_INPUT"
  fi
}

testml-run() {
  testml_runner_sourced=true

  export-testml-vars

  if is-tty; then
    run-cli "$@"

  else
    set-testml-vars

    compile-testml

    set-testml-lib-vars

    testml-run-file "$TESTML_EXEC"
  fi
}

run-cli() {
  source "$TESTML_ROOT/bin/testml-cli.sh"

  testml-run-cli "$@"
}

check-input-file() {
  if [[ $1 != '-' ]]; then
    [[ $# == 1 && -n $1 ]] ||
      die "Can't determine testml source file"
    [[ -e $1 ]] ||
      die "TestML input file '$1' does not exist"
  fi

  export TESTML_INPUT=$1
}

set-testml-bin() {
  local PATH="$TESTML_ROOT/bin:$PATH"

  if [[ -n $TESTML_BIN ]]; then
    can "$TESTML_BIN" ||
      die "TESTML_BIN=$TESTML_BIN but '$TESTML_BIN' not found"
    export TESTML_BIN=$can_path
    return 0
  fi

  if [[ -n $TESTML_RUN ]]; then
    TESTML_BIN="testml-$TESTML_RUN"
    can "$TESTML_BIN" ||
      die "TESTML_RUN=$TESTML_RUN but '$TESTML_BIN' not found"
    export TESTML_RUN
    export TESTML_BIN=$can_path
    return 0
  fi

  die "
Can't determine TestML runner binary to use.
Try setting TESTML_RUN or TESTML_BIN.
See 'testml --list' for a list of runners.
"
}

set-testml-vars() {
  TESTML_DIR=$(cd "$(dirname "$TESTML_INPUT")" && pwd)
  export TESTML_DIR
  TESTML_FILENAME=$(basename "$TESTML_INPUT")
  export TESTML_FILENAME

  if [[ $TESTML_INPUT == '-' ]]; then
    export TESTML_FILE='-'
  else
    export TESTML_FILE="$TESTML_DIR/$TESTML_FILENAME"
  fi

  source-testml-config

  [[ -n $TESTML_CACHE ]] ||
    TESTML_CACHE="$(abs-dir-path "$TESTML_INPUT")/.testml"
  export TESTML_CACHE
  export TESTML_EXEC="$TESTML_CACHE/$TESTML_FILENAME.json"
}

source-testml-config() {
  if [[ -z $TESTML_CONFIG ]]; then
    if [[ -e $TESTML_DIR/.testmlrc ]]; then
      TESTML_CONFIG="$TESTML_DIR/.testmlrc"
    fi
  fi

  [[ -n $TESTML_CONFIG ]] || return 0

  [[ -f $TESTML_CONFIG ]] ||
    die "TestML config file '$TESTML_CONFIG' does not exist"

  source "$TESTML_CONFIG"

  export-testml-vars
}

export-testml-vars() {
  export TESTML_{BIN,BRIDGE,LANG,LIB,MODULE,PATH,RUN}
}

set-testml-lib-vars() {
  local dir=
  if [[ $TESTML_FILE =~ (^.*)/testml/ ]]; then
    dir=":${BASH_REMATCH[1]}"
  fi
  TESTML_LIB="${TESTML_LIB:+$TESTML_LIB:}$TESTML_DIR$dir"
  if [[ $TESTML_LANG == 'perl6' ]]; then
    TESTML_LIB=${TESTML_LIB//:/,}
  fi
  export TESTML_LIB

  export TESTML_ROOT_LIB="$TESTML_ROOT/src/$TESTML_LANG/lib"
}

compile-testml() {
  [[ $TESTML_INPUT == '-' || -e $TESTML_EXEC && ! -s $TESTML_EXEC ]] &&
    rm -f "$TESTML_EXEC"
  [[ $TESTML_EXEC -nt $TESTML_FILE ]] &&
    return 0

  : "${TESTML_COMPILER_BIN:=testml-compiler}"

  rc=0
  output=$(
    if [[ -n $testml_eval_input ]]; then
      echo "$testml_eval_input" | "${TESTML_COMPILER_BIN}" -
    else
      "${TESTML_COMPILER_BIN}" "$TESTML_FILE"
    fi
  ) || rc=$?

  if [[ -n $TESTML_EXEC ]]; then
    mkdir -p "$TESTML_CACHE"
    echo -n "$output" > "$TESTML_EXEC"
  else
    echo "$output"
  fi

  return $rc
}

is-tty() {
  [[ -t 0 || -t 1 ]]
}

can() {
  can_path=$(which "$1") || return $?
}

abs-dir-path() {
  [[ $1 != '-' ]] || { pwd; return; }
  [[ -f $1 ]] || die "'$1' is not a file"
  local file_path=$1
  local file_name=
  file_name=$(basename "$1")
  local file_dir=
  file_dir=$(cd "$(dirname -- "$1")" && (pwd -P 2>/dev/null || pwd))
  (
    cd "$file_dir"
    link=$(readlink -- "$file_name")
    if [[ -n $link ]]; then
      cd "$(dirname -- "$link")"
    fi
    pwd -P 2>/dev/null || pwd
  )
}

die() {
  if [[ $# -eq 0 ]]; then
    echo "Died" >&2
  else
    echo "$*" >&2
  fi
  exit 1
}

TESTML_SOURCED=true

[[ $0 != "${BASH_SOURCE[0]}" ]] || main "$@"

# vim: ft=sh sw=2 lisp:
