#!/usr/bin/env bash

URL_BASE="https://www.radiorecord.ru/api"
MPV_PID_FILE="/tmp/mpv_radio_pid"
RADIO_ID_FILE="/tmp/radio_id"

STATION_IDS='[507,522,523,536,537,42532,42602]'

# Custom (non-radiorecord) stations
# id must be a unique integer >= 1000000 to avoid collision with radiorecord IDs.
# icon_fill_white: URL to station icon image, or "" for none.
CUSTOM_STATIONS='[
]'

STATIONS="[]"
DEFAULT_INFO='{"artist":"","song":"","image600":""}'
DEFAULT_MEDIA='{"player":"","status":"Stopped","artist":"","title":"","art":""}'

PID=$([ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0)
RADIO_ID=$([ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0)
PAUSED=$(( PID == 0 ? 1 : 0 ))
INFO="$DEFAULT_INFO"
MEDIA="$DEFAULT_MEDIA"
STATUS="{}"

get_stations() {
  local rr
  rr=$(curl -s --compressed "$URL_BASE/stations/" 2>/dev/null \
    | jq --argjson ids "$STATION_IDS" \
        '.result.stations | map(select(.id | IN($ids[]))) | map({id, title, stream_hls, icon_fill_white, "radiorecord": true})' 2>/dev/null)
  jq -n \
    --argjson rr "${rr:-[]}" \
    --argjson custom "$CUSTOM_STATIONS" \
    '$rr + ($custom | map(. + {"radiorecord": false}))'
}

get_song() {
  curl -s --compressed "$URL_BASE/station/history/?id=$RADIO_ID" \
    | jq '.result.history[0] | {artist, song, image600}'
}

get_stream_url() {
  echo "$STATIONS" | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].stream_hls // empty'
}

get_player_info() {
  local player status artist title art
  # exclude mpv (radio) so it never appears as "external player"
  player=$(playerctl -l 2>/dev/null | grep -Ev '^mpv' | head -1)
  if [ -z "$player" ]; then
    echo '{"player":"","status":"Stopped","artist":"","title":"","art":""}'
    return
  fi
  status=$(playerctl -p "$player" status 2>/dev/null || echo "Stopped")
  artist=$(playerctl -p "$player" metadata artist 2>/dev/null || echo "")
  title=$(playerctl -p "$player" metadata title 2>/dev/null || echo "")
  art=$(playerctl -p "$player" metadata mpris:artUrl 2>/dev/null || echo "")
  jq -cnr --arg player "$player" --arg status "$status" \
    --arg artist "$artist" --arg title "$title" --arg art "$art" \
    '{player:$player, status:$status, artist:$artist, title:$title, art:$art}'
}

update_state() {
  PID=$([ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0)
  RADIO_ID=$([ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0)
  if [ "$PID" -gt 0 ] && ! kill -0 "$PID" 2>/dev/null; then
    PID=0
    rm -f "$MPV_PID_FILE"
  fi
  PAUSED=$(( PID == 0 ? 1 : 0 ))
}

emit_status() {
  jq -cnr \
    --argjson stations "${STATIONS:-[]}" \
    --argjson radio_id "${RADIO_ID:-0}" \
    --argjson is_paused "${PAUSED:-1}" \
    --argjson info "${INFO:-$DEFAULT_INFO}" \
    --argjson media "${MEDIA:-$DEFAULT_MEDIA}" \
    '{"is_paused": $is_paused, "song": $info, "radio": $radio_id, "stations": $stations, "media": $media}'
}

get_stream_node() {
  local name="$1"
  wpctl status 2>/dev/null | awk -v pat="$name" '
    /Streams:/ { in_s = 1 }
    /Sinks:|Sources:|Clients:/ { in_s = 0 }
    in_s && /[0-9]+\./ && tolower($0) ~ tolower(pat) {
      match($0, /[0-9]+/); print substr($0, RSTART, RLENGTH); exit
    }
  '
}

get_mpv_node() {
  get_stream_node "mpv"
}

get_volume() {
  if [ "$PID" -gt 0 ] && kill -0 "$PID" 2>/dev/null; then
    local node_id; node_id=$(get_mpv_node)
    [ -n "$node_id" ] && wpctl get-volume "$node_id" 2>/dev/null \
      | awk '{printf "%d", $2 * 100}'
  else
    local player; player=$(playerctl -l 2>/dev/null | grep -Ev '^mpv' | head -1)
    [ -n "$player" ] && playerctl -p "$player" volume 2>/dev/null \
      | awk '{printf "%d", $1 * 100}'
  fi
}

do_vol() {
  local vol="${1%.*}"
  if [ "$PID" -gt 0 ] && kill -0 "$PID" 2>/dev/null; then
    local node_id; node_id=$(get_mpv_node)
    [ -n "$node_id" ] && wpctl set-volume "$node_id" "${vol}%"
  else
    playerctl volume "$(awk -v v="$vol" 'BEGIN{printf "%.2f", v/100}')" 2>/dev/null
  fi
  eww update radio-vol="$vol"
}

do_mute() {
  local node_id
  if [ "$PID" -gt 0 ] && kill -0 "$PID" 2>/dev/null; then
    node_id=$(get_mpv_node)
  else
    local player; player=$(playerctl -l 2>/dev/null | grep -Ev '^mpv' | head -1)
    [ -n "$player" ] && node_id=$(get_stream_node "${player%%.*}")
  fi
  [ -z "$node_id" ] && return
  wpctl set-mute "$node_id" toggle
  if wpctl get-volume "$node_id" 2>/dev/null | grep -q MUTED; then
    eww update radio-muted=true
  else
    eww update radio-muted=false
  fi
}

do_start() {
  [ "$RADIO_ID" -le 0 ] && return
  STATIONS=$(get_stations)
  RADIO_URL=$(get_stream_url)
  [ -z "$RADIO_URL" ] || [ "$RADIO_URL" = "null" ] && return
  [ "$PID" -gt 0 ] && kill "$PID" 2>/dev/null
  nohup mpv --no-video --quiet "$RADIO_URL" >/dev/null 2>&1 &
  echo $! > "$MPV_PID_FILE"
  echo "$RADIO_ID" > "$RADIO_ID_FILE"
}

status_loop() {
  STATIONS=$(get_stations)
  echo "$(emit_status)"

  last_pid_check=0
  last_song_fetch=0
  last_media_fetch=0

  while true; do
    now=$(date -u +%s%3N)

    if (( now - last_pid_check > 1000 )); then
      update_state
      NEW_STATUS=$(emit_status)
      if [ "$NEW_STATUS" != "$STATUS" ]; then STATUS=$NEW_STATUS; echo "$STATUS"; fi
      last_pid_check=$now
    fi

    if (( now - last_song_fetch > 15000 )); then
      if [ "$PAUSED" = 0 ]; then
        IS_RR=$(echo "$STATIONS" | jq --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].radiorecord // true')
        if [ "$IS_RR" = "true" ]; then
          FETCHED=$(get_song)
          INFO=$(echo "$INFO" "$FETCHED" | jq -s '
            reduce .[] as $x ({}; . + ($x | with_entries(select(.value != null))))')
        else
          STATION_TITLE=$(echo "$STATIONS" | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].title // ""')
          INFO=$(jq -cnr --arg title "$STATION_TITLE" '{artist:"",song:$title,image600:""}')
        fi
      else
        STATION_IMG=$(echo "$STATIONS" \
          | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].icon_fill_white // ""')
        STATION_TITLE=$(echo "$STATIONS" \
          | jq -r --argjson id "$RADIO_ID" 'map(select(.id == $id))[0].title // ""')
        INFO=$(jq -cnr --arg img "$STATION_IMG" --arg title "$STATION_TITLE" \
          '{artist:"",song:$title,image600:$img}')
      fi
      NEW_STATUS=$(emit_status)
      if [ "$NEW_STATUS" != "$STATUS" ]; then STATUS=$NEW_STATUS; echo "$STATUS"; fi
      last_song_fetch=$now
    fi

    if (( now - last_media_fetch > 3000 )); then
      MEDIA=$(get_player_info)
      NEW_STATUS=$(emit_status)
      if [ "$NEW_STATUS" != "$STATUS" ]; then STATUS=$NEW_STATUS; echo "$STATUS"; fi
      VOL=$(get_volume)
      [ -n "$VOL" ] && eww update radio-vol="$VOL" 2>/dev/null
      last_media_fetch=$now
    fi

    sleep 0.5
  done
}

case "$1" in
  start)
    RADIO_ID="$2"
    echo "$RADIO_ID" > "$RADIO_ID_FILE"
    do_start
    ;;
  vol)
    do_vol "$2"
    ;;
  mute)
    update_state
    do_mute
    ;;
  toggle)
    update_state
    if [ "$PAUSED" = 1 ]; then
      [ "$RADIO_ID" -gt 0 ] && do_start
    else
      [ "$PID" -gt 0 ] && kill "$PID" 2>/dev/null
      rm -f "$MPV_PID_FILE"
    fi
    ;;
  *)
    status_loop
    ;;
esac
