#!/bin/bash

# Define some icons
SPEAKER_ICONS=("" "" "")
SPEAKER_MUTED_ICON=""
MIC_ICON=""
MIC_MUTED_ICON=""

# Define some helper functions for getting/setting audio data using wireplumber (wpctl)

# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
get_vol() {
  wpctl get-volume "@DEFAULT_AUDIO_${1}@" | awk '{print int($2*100)}'
}

# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
# #2 is the voulme (as percentage) to set the volume to
# $3 is optional, if set, it can be '+' or '-', which then adds/decreases volume, instead of setting
set_vol() {
  wpctl set-volume "@DEFAULT_AUDIO_${1}@" "$(awk -v n="$2" 'BEGIN{print (n / 100)}')$3"
}

# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
check_mute() {
  wpctl get-volume "@DEFAULT_AUDIO_${1}@" | grep -i muted >/dev/null
  echo $?
}

# $1 can either be "SINK" (speaker) or "SOURCE" (microphone)
toggle_mute() {
  wpctl set-mute "@DEFAULT_AUDIO_${1}@" toggle
}

get_report() {
    spkr_vol="$(get_vol "SINK")"
    mic_vol="$(get_vol "SOURCE")"

    if [ "$(check_mute "SINK")" == "0" ]; then
      spkr_mute="true"
      spkr_icon="$SPEAKER_MUTED_ICON"
    else
      spkr_mute="false"
      index="$(awk -v n="$spkr_vol" -v m="${#SPEAKER_ICONS[@]}" 'BEGIN{print int(n/(100/m))}')"

      # We might end up with an higher than the length of icons, if the volume is over 100%
      # in this case, set the index to last icon
      if [ "$index" -ge "${#SPEAKER_ICONS[@]}" ]; then
        spkr_icon="${SPEAKER_ICONS[-1]}"
      else
        spkr_icon="${SPEAKER_ICONS[$index]}"
      fi
    fi

    if [ "$(check_mute "SOURCE")" = "0" ]; then
      mic_mute="true" 
      mic_icon="$MIC_MUTED_ICON"
    else
      mic_mute="false"
      mic_icon="$MIC_ICON"
    fi

    echo "{ \"speaker_vol\": \"$spkr_vol\", \"speaker_mute\": $spkr_mute, \"speaker_icon\": \"$spkr_icon\", \"microphone_mute\": $mic_mute, \"microphone_vol\": \"$mic_vol\", \"microphone_icon\": \"$mic_icon\" }"
}

# Continually run and report every volume change (into stdout)
loop() {
  pactl subscribe | grep --line-buffered "change" | while read -r _; do
    get_report
  done
}

case "$1" in
  "loop") 
    get_report
    loop 
    ;;

  "once") get_report ;;

  "togglemute")
    if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
      >&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'"
      exit 1
    fi
    toggle_mute "$2"
    ;;

  "setvol")
    if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
      >&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'"
      exit 1
    fi

    if [[ "$3" =~ ^[+-]?[0-9]*\.?[0-9]+$ ]]; then
        case "$4" in
          "") set_vol "$2" "$3" ;;
          up|+) set_vol "$2" "$3" "+" ;;
          down|-) set_vol "$2" "$3" "-" ;;
          *)
            >&2 echo "Invalid usage, expected fourth argument to be up/down or +/-, got '$4'"
            exit 1
            ;;
        esac
    else
      >&2 echo "Invalid usage, exepcted third argument to be a number, got '$3'"
      exit 1
    fi
    ;;

  *)
    >&2 echo "Invalid usage, argument '$1' not recognized."
    exit 1
    ;;
esac