#!/bin/bash

set -u

readonly PANAMA_OSD_SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"

strict_delivery() {
    [[ ${PANAMA_OSD_STRICT:-false} == true || ${PANAMA_OSD_STRICT:-false} == 1 ]]
}

show_progress() {
    if ! qs ipc call osd progress "$1" "$2" 100 "$3" >/dev/null 2>&1; then
        strict_delivery && return 1
    fi
    return 0
}

show_message() {
    if ! qs ipc call osd message "$1" "$2" >/dev/null 2>&1; then
        strict_delivery && return 1
    fi
    return 0
}

volume_state() {
    local target="$1" output level percent muted=false
    output="$(wpctl get-volume "$target" 2>/dev/null)" || return 1
    if [[ $output =~ Volume:[[:space:]]*([0-9]+([.][0-9]+)?) ]]; then
        level="${BASH_REMATCH[1]}"
    else
        return 1
    fi
    [[ $output == *"[MUTED]"* ]] && muted=true
    percent="$(awk -v value="$level" 'BEGIN { printf "%d", value * 100 + 0.5 }')"
    printf '%s %s\n' "$percent" "$muted"
}

show_volume() {
    local target="$1" kind="$2" state percent muted label
    state="$(volume_state "$target")" || return 0
    read -r percent muted <<<"$state"
    if [[ $muted == true ]]; then
        show_progress "${kind}-muted" "$percent" "Muted"
    else
        label="${percent}%"
        show_progress "$kind" "$percent" "$label"
    fi
}

adjust_volume() {
    local action="${1:-}" step="${2:-6}" target="@DEFAULT_AUDIO_SINK@"
    case "$action" in
        up) wpctl set-volume -l 1 "$target" "${step}%+" || return ;;
        down) wpctl set-volume "$target" "${step}%-" || return ;;
        toggle) wpctl set-mute "$target" toggle || return ;;
        *) printf 'Usage: panama-osd volume up|down|toggle [step]\n' >&2; return 2 ;;
    esac
    show_volume "$target" volume
}

adjust_microphone() {
    local action="${1:-}" step="${2:-6}" target="@DEFAULT_AUDIO_SOURCE@"
    case "$action" in
        up) wpctl set-volume -l 1 "$target" "${step}%+" || return ;;
        down) wpctl set-volume "$target" "${step}%-" || return ;;
        toggle) wpctl set-mute "$target" toggle || return ;;
        *) printf 'Usage: panama-osd microphone up|down|toggle [step]\n' >&2; return 2 ;;
    esac
    show_volume "$target" microphone
}

brightness_percent() {
    local output="$1" percent
    percent="$(awk -F, 'NR == 1 { value=$4; gsub(/%/, "", value); print value }' <<<"$output")"
    [[ $percent =~ ^[0-9]+$ ]] || return 1
    printf '%s\n' "$percent"
}

brightness_error() {
    local detail="$1" label="External brightness unavailable"
    if [[ $detail == *udev* || $detail == *accessible* || $detail == *permission* ]]; then
        label="Brightness needs permission"
    fi

    show_message dialog-warning-symbolic "$label" || true
    if command -v notify-send >/dev/null 2>&1; then
        notify-send --app-name=Panama --icon=display-brightness-symbolic \
            "Brightness unavailable" "$detail" >/dev/null 2>&1 || true
    fi
}

discover_ddc_bus() {
    local helper="$1" cache_file="$2" list_json focused selected error bus connector

    command -v jq >/dev/null 2>&1 || {
        brightness_error "jq is required to discover DDC/CI displays."
        return 1
    }

    list_json="$("$helper" list 2>/dev/null)" || {
        brightness_error "The external brightness helper could not inspect connected displays."
        return 1
    }
    if ! jq -e 'type == "object" and (.displays | type == "array")' >/dev/null 2>&1 <<<"$list_json"; then
        brightness_error "The external brightness helper returned invalid display information."
        return 1
    fi

    error="$(jq -r '.error // empty' <<<"$list_json")"
    if [[ -n $error ]]; then
        brightness_error "$error"
        return 1
    fi

    focused="$(hyprctl -j monitors 2>/dev/null \
        | jq -r '.[] | select(.focused == true) | .name' 2>/dev/null \
        | head -n1)"
    selected="$(jq -r --arg connector "$focused" '
        ([.displays[] | select(.connector == $connector)][0] // .displays[0] // empty)
        | [.bus, .connector]
        | @tsv
    ' <<<"$list_json")"
    IFS=$'\t' read -r bus connector <<<"$selected"
    if [[ ! $bus =~ ^[0-9]+$ ]]; then
        brightness_error "No connected monitor exposes DDC/CI brightness control."
        return 1
    fi

    umask 077
    printf '%s\t%s\n' "$bus" "$connector" >"$cache_file"
    printf '%s\n' "$bus"
}

adjust_ddc_brightness() {
    local action="$1" step="$2"
    local helper="${PANAMA_OSD_BRIGHTNESS_HELPER:-$PANAMA_OSD_SCRIPT_DIR/panama-brightness}"
    local runtime_dir="${PANAMA_OSD_RUNTIME_DIR:-${XDG_RUNTIME_DIR:-/tmp}/panama-osd-${UID}}"
    local cache_file="$runtime_dir/brightness-bus" lock_file="$runtime_dir/brightness.lock"
    local bus="" connector="" current target lock_fd

    [[ -x $helper ]] || {
        brightness_error "The external brightness helper is not installed."
        return 0
    }
    mkdir -p "$runtime_dir" || return 0
    chmod 700 "$runtime_dir" 2>/dev/null || true

    exec {lock_fd}>"$lock_file" || return 0
    # DDC transactions on one I2C bus cannot safely overlap. A short wait also
    # sheds an excessive key-repeat backlog instead of replaying it seconds later.
    flock -w 2 "$lock_fd" || return 0

    if [[ -r $cache_file ]]; then
        IFS=$'\t' read -r bus connector <"$cache_file" || true
        [[ $bus =~ ^[0-9]+$ ]] || bus=""
    fi

    if [[ -n $bus ]]; then
        current="$("$helper" get "$bus" 2>/dev/null)" || current=""
        if [[ ! $current =~ ^[0-9]+$ ]]; then
            : >"$cache_file"
            bus=""
        fi
    fi

    if [[ -z $bus ]]; then
        bus="$(discover_ddc_bus "$helper" "$cache_file")" || return 0
        current="$("$helper" get "$bus" 2>/dev/null)" || current=""
    fi
    if [[ ! $current =~ ^[0-9]+$ ]]; then
        brightness_error "The selected monitor stopped responding over DDC/CI."
        return 0
    fi

    if [[ $action == up ]]; then
        target=$(( current + step ))
    else
        target=$(( current - step ))
    fi
    (( target > 100 )) && target=100
    (( target < 0 )) && target=0

    if ! "$helper" set "$bus" "$target" >/dev/null 2>&1; then
        brightness_error "The selected monitor did not accept the brightness change."
        return 0
    fi
    show_progress brightness "$target" "${target}%"
}

adjust_brightness() {
    local action="${1:-}" step="${2:-5}" output percent
    [[ $step =~ ^[0-9]+$ ]] || {
        printf 'Usage: panama-osd brightness up|down [step]\n' >&2
        return 2
    }
    case "$action" in
        up|down) ;;
        *) printf 'Usage: panama-osd brightness up|down [step]\n' >&2; return 2 ;;
    esac

    # Laptop panels expose a kernel backlight class and remain the fastest,
    # most reliable path. Desktops fall through to DDC/CI monitor control.
    output="$(brightnessctl -m -c backlight 2>/dev/null)" || output=""
    if percent="$(brightness_percent "$output")"; then
        if [[ $action == up ]]; then
            brightnessctl -e4 -n2 -c backlight set "${step}%+" >/dev/null || return 0
        else
            brightnessctl -e4 -n2 -c backlight set "${step}%-" >/dev/null || return 0
        fi
        output="$(brightnessctl -m -c backlight 2>/dev/null)" || return 0
        percent="$(brightness_percent "$output")" || return 0
        show_progress brightness "$percent" "${percent}%"
        return
    fi

    adjust_ddc_brightness "$action" "$step"
}

media_action() {
    local action="${1:-}" kind label fallback
    case "$action" in
        play-pause)
            playerctl play-pause || return
            if [[ $(playerctl status 2>/dev/null) == "Playing" ]]; then
                kind="media-play"
                fallback="Playing"
            else
                kind="media-pause"
                fallback="Paused"
            fi
            ;;
        next) playerctl next || return; kind="media-next"; fallback="Next track" ;;
        previous) playerctl previous || return; kind="media-previous"; fallback="Previous track" ;;
        stop) playerctl stop || return; kind="media-stop"; fallback="Stopped" ;;
        *) printf 'Usage: panama-osd media play-pause|next|previous|stop\n' >&2; return 2 ;;
    esac

    label="$(playerctl metadata --format '{{ title }} — {{ artist }}' 2>/dev/null)"
    [[ -n $label ]] || label="$fallback"
    show_message "$kind" "$label"
}

# Airplane mode: one rfkill state for every radio, with an OSD saying which
# way it went. "Any radio unblocked" reads as radios-on, so toggle means
# "block everything" from a mixed state -- the direction a person reaching
# for airplane mode wants.
airplane_action() {
    case "${1:-toggle}" in
        toggle)
            if rfkill list 2>/dev/null | grep -q 'Soft blocked: no'; then
                rfkill block all 2>/dev/null \
                    && show_message "airplane-mode-symbolic" "Airplane mode on"
            else
                rfkill unblock all 2>/dev/null \
                    && show_message "network-wireless-symbolic" "Airplane mode off"
            fi
            ;;
        *)
            printf 'Usage: panama-osd airplane toggle\n' >&2
            return 2
            ;;
    esac
}

case "${1:-}" in
    volume) shift; adjust_volume "$@" ;;
    microphone) shift; adjust_microphone "$@" ;;
    brightness) shift; adjust_brightness "$@" ;;
    media) shift; media_action "$@" ;;
    airplane) shift; airplane_action "$@" ;;
    message)
        shift
        kind="${1:-}"
        [[ -n $kind && $# -ge 2 ]] || {
            printf 'Usage: panama-osd message ICON LABEL\n' >&2
            exit 2
        }
        shift
        show_message "$kind" "$*"
        ;;
    *)
        printf 'Usage: panama-osd volume|microphone|brightness|media|airplane|message ACTION [value]\n' >&2
        exit 2
        ;;
esac
