#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  plugin validate
  plugin test [mix test args...]
  plugin precommit [mix precommit args...]
  plugin smoke
  plugin shell
EOF
}

fail() {
  echo "plugin: $*" >&2
  exit 1
}

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
plugin_root="$(cd "$script_dir/.." && pwd -P)"
host_root="${TRIBES_HOST_ROOT:-$plugin_root/../tribes}"
host_root="$(cd "$host_root" && pwd -P)"
host_script="$host_root/scripts/plugin"

json_field() {
  local field="$1"

  FIELD="$field" mix run --no-start -e '
    field = System.fetch_env!("FIELD")
    manifest = "manifest.json" |> File.read!() |> JSON.decode!()
    value = Map.fetch!(manifest, field)
    IO.write(value)
  '
}

run_smoke() {
  cd "$plugin_root"

  mix compile

  local otp_app
  local entry_module
  otp_app="$(json_field otp_app)"
  entry_module="$(json_field entry_module)"

  local beam_path="_build/dev/lib/$otp_app/ebin/Elixir.$entry_module.beam"
  [[ -f "$beam_path" ]] || fail "expected entry module beam at $beam_path"

  cd "$host_root"
  PLUGIN_ROOT="$plugin_root" ENTRY_MODULE="$entry_module" mix run --no-start -e '
    plugin_root = System.fetch_env!("PLUGIN_ROOT")
    entry_module = System.fetch_env!("ENTRY_MODULE")

    plugin_root
    |> Path.join("_build/dev/lib/*/ebin")
    |> Path.wildcard()
    |> Enum.each(&(:code.add_patha(String.to_charlist(&1))))

    module = String.to_atom("Elixir." <> entry_module)

    case Code.ensure_loaded(module) do
      {:module, ^module} ->
        IO.puts("Loaded #{entry_module}")

      other ->
        raise "failed to load #{entry_module}: #{inspect(other)}"
    end
  '
}

command_name="${1:-}"
if [[ -z "$command_name" ]]; then
  usage
  exit 1
fi
shift

case "$command_name" in
  validate | test | precommit | smoke | shell) ;;
  -h | --help | help)
    usage
    exit 0
    ;;
  *)
    usage
    fail "unknown command: $command_name"
    ;;
esac

[[ -x "$host_script" || -f "$host_script" ]] || fail "expected host plugin script at $host_script"

if [[ "$command_name" == "smoke" ]]; then
  run_smoke "$@"
  exit 0
fi

if [[ "${DEVENV_ROOT:-}" == "$plugin_root" ]]; then
  command -v devenv >/dev/null 2>&1 || fail "devenv is required when running from the plugin devenv shell"
  cd "$host_root"
  exec devenv shell -- bash ./scripts/plugin "$command_name" "$plugin_root" "$@"
fi

exec bash "$host_script" "$command_name" "$plugin_root" "$@"
