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

_noism_mediakey_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
app_dir="${NOISM_APP_DIR:-${_noism_mediakey_dir:-$PWD}}"
export NOISM_APP_DIR="$app_dir"

# shellcheck disable=SC1090
source "$app_dir/noism.sh" >/dev/null 2>&1

runtime_root() {
  local uid run_root cache_root env_root candidate

  uid="$(id -u)"
  run_root="/run/user/$uid/noism"
  cache_root="$HOME/.cache/noism"
  env_root=""
  if [[ -n "${XDG_RUNTIME_DIR:-}" ]]; then
    env_root="${XDG_RUNTIME_DIR}/noism"
  fi

  for candidate in "$env_root" "$run_root" "$cache_root"; do
    [[ -n "$candidate" ]] || continue
    if [[ -f "$candidate/state" ]]; then
      printf '%s\n' "$candidate"
      return 0
    fi
  done

  if [[ -n "$env_root" ]]; then
    printf '%s\n' "$env_root"
  elif [[ -d "/run/user/$uid" ]]; then
    printf '%s\n' "$run_root"
  else
    printf '%s\n' "$cache_root"
  fi
}

runtime_root="$(runtime_root)"
state_file="$runtime_root/state"
control_fifo="$runtime_root/control"

load_state() {
  [[ -f "$state_file" ]] || return 1
  # shellcheck disable=SC1090
  source "$state_file"
  [[ "${NOISM_APP_DIR:-}" == "$app_dir" ]] || return 1
}

write_state() {
  mkdir -p "$runtime_root"
  {
    printf 'NOISM_APP_DIR=%q\n' "${NOISM_APP_DIR:-$app_dir}"
    printf 'NOISM_SHELL_PID=%q\n' "${NOISM_SHELL_PID:-}"
    printf 'NOISM_FFPLAY_PID=%q\n' "${NOISM_FFPLAY_PID:-}"
    printf 'NOISM_PLAY_STATE=%q\n' "${NOISM_PLAY_STATE:-stopped}"
    printf 'NOISM_ACTIVE_TRACK=%q\n' "${NOISM_ACTIVE_TRACK:-}"
    printf 'NOISM_ACTIVE_VOLUME=%q\n' "${NOISM_ACTIVE_VOLUME:-}"
    printf 'NOISM_ACTIVE_CROSSFADE=%q\n' "${NOISM_ACTIVE_CROSSFADE:-}"
  } >"$state_file"
}

pid_running() {
  local pid="${1:-}"
  [[ -n "$pid" ]] || return 1
  ps -p "$pid" -o stat= 2>/dev/null | grep -qv '^[[:space:]]*$'
}

adjacent_track() {
  local direction="$1"
  local current="${NOISM_ACTIVE_TRACK:-$_noism_default_track}"
  local i count

  _noism_load_tracks 'All' || return 1
  count="${#NOISM_TRACKS[@]}"
  (( count > 0 )) || return 1

  if [[ -z "$current" ]]; then
    printf '%s\n' "${NOISM_TRACKS[0]}"
    return 0
  fi

  for i in "${!NOISM_TRACKS[@]}"; do
    if [[ "${NOISM_TRACKS[$i]}" == "$current" ]]; then
      if [[ "$direction" == "next" ]]; then
        printf '%s\n' "${NOISM_TRACKS[$(((i + 1) % count))]}"
      else
        printf '%s\n' "${NOISM_TRACKS[$(((i - 1 + count) % count))]}"
      fi
      return 0
    fi
  done

  printf '%s\n' "${NOISM_TRACKS[0]}"
}

noism_active() {
  [[ -p "$control_fifo" ]] || return 1
  load_state || return 1
  [[ -n "${NOISM_SHELL_PID:-}" ]] || return 1
  pid_running "$NOISM_SHELL_PID"
}

start_controller() {
  local track="${1:-${NOISM_ACTIVE_TRACK:-$_noism_default_track}}"
  local volume="${2:-${NOISM_ACTIVE_VOLUME:-$_noism_default_volume}}"

  nohup env NOISM_APP_DIR="$app_dir" "$app_dir/noism-channel" "$track" "$volume" >/dev/null 2>&1 </dev/null &

  for _ in 1 2 3 4 5 6 7 8 9 10; do
    if noism_active; then
      return 0
    fi
    sleep 0.1
  done

  return 1
}

send_action() {
  local action="$1"
  printf '%s\n' "$action" >"$control_fifo"
}

usage() {
  cat <<'EOF'
Usage: noism-mediakey <play-pause|play|pause>
EOF
}

if [[ $# -eq 0 ]]; then
  usage >&2
  exit 2
fi

case "$1" in
  -h|--help|help)
    usage
    exit 0
    ;;
esac

load_state || {
  NOISM_APP_DIR="$app_dir"
  NOISM_SHELL_PID=""
  NOISM_FFPLAY_PID=""
  NOISM_PLAY_STATE="stopped"
  NOISM_ACTIVE_TRACK="$_noism_default_track"
  NOISM_ACTIVE_VOLUME="$_noism_default_volume"
  NOISM_ACTIVE_CROSSFADE=""
}

case "$1" in
  play-pause)
    if noism_active; then
      send_action play-pause
    else
      start_controller
    fi
    ;;
  play)
    if noism_active; then
      send_action play
    else
      start_controller
    fi
    ;;
  pause)
    noism_active && send_action pause || true
    ;;
  *)
    usage >&2
    exit 2
    ;;
esac
