#!/usr/bin/env bash

select_audio_sink() {
    sinks="$(pactl list sinks)"

    IFS=$(echo -en "\n\b")
    devices=($(echo "${sinks}" | grep -ioP "(?<=name: ).*$"))
    names=($(echo "${sinks}" | grep -ioP "(?<=description: ).*$"))
    unset IFS

    if [[ "${#devices[@]}" != "${#names[@]}" ]]; then
        echo "ERROR: #devices (${#devices[@]}) != #names (${#names[@]})"
        return 1
    fi

    unset number
    for n in ${!devices[@]}; do
        if [[ "${devices[$n]}" == "$(pactl get-default-sink)" ]]; then
            number=$n
            break
        fi
    done
    if [[ -z "${number}" ]]; then
        return 1
    fi

    if ((${#devices[@]} > 16)); then
        lines=16
    else
        lines=${#devices[@]}
    fi

    if $(which rofi &>/dev/null); then
        selection="$(printf "%s\n" "${names[@]//\"/}" | rofi -dmenu -theme-str "#listview { lines: ${lines}; }" -selected-row ${number} -case-smart)"
    elif $(which fuzzel &>/dev/null); then
        selection="$(printf "%s\n" "${names[@]//\"/}" | fuzzel --lines ${lines} --dmenu --select-index ${number})"
    else
        notify-send "sink-switcher" "requires either [rofi] or [fuzzel]"
        return 1
    fi

    if [[ -z "${selection}" ]]; then
        return 1
    fi

    unset number
    for n in ${!names[@]}; do
        if [[ "${names[$n]}" == *"${selection}"* ]]; then
            number=$n
            break
        fi
    done

    if [[ -z "${number}" ]]; then
        notify-send "sink-switcher" "something went wrong.."
        return 1
    fi

    pactl set-default-sink ${devices[$number]//\"/}
}

select_audio_sink
