#!/usr/bin/env lua

-- Wireplumber doesn't expose much of the 'os' table so here is a wrapper script

local argv = table.pack(...)
local wireplumber_script = os.getenv('HOME') .. '/.local/libexec/volume.lua'
local icon_dir = os.getenv('HOME') .. '/.config/{{ notification }}'
local volume_step = 0.05

local function print_help()
    io.stdout:write(string.format([[
Usage: volumecontrol [--help|--increase|--decrease|--toggle-source|--toggle]
    --increase     : Increase volume of default sink by %s
    --decrease     : Decrease volume of default sink by %s
    --toggle       : Toggle mute state of default sink
    --toggle-source: Toggle mute state of default source
]], volume_step, volume_step))
end

if #argv == 0 then
    print_help()
    return
end

local action = argv[1]:match('%-%-(.+)')
local options = { 'toggle', 'toggle-source', 'increase', 'decrease' }

local function findValue(tbl, value)
    for _, v in pairs(tbl) do
        if v == value then
            return true
        end
    end
    return false
end

if not findValue(options, action) then
    print_help()
    return
end

local function read_output(command)
    -- No buffering to get all output at once
    io.stdout:setvbuf('no')

    local file = assert(io.popen(command, 'r'))
    file:flush() -- receive all the output immediately (in case the output is big)
    local output = file:read('a')
    file:close()

    return output
end

if action == 'toggle-source' then
    os.execute('wpexec ' .. wireplumber_script .. ' action=toggle_source')

    local status = read_output('wpexec ' .. wireplumber_script .. ' action=print_source')
    local volume = tonumber(status:match('Volume:%s+([^%a]+)')) * 100
    local mute = status:match('Mute:%s+(%a+)')

    if mute == 'true' then
        local icon = icon_dir .. '/microphone_mute.png'
        os.execute('notify-send -i ' .. icon .. ' "Microphone muted" "Volume: ' .. tostring(volume) .. '%"')
    else
        local icon = icon_dir .. '/microphone.png'
        os.execute('notify-send -i ' .. icon .. ' "Microphone unmuted" "Volume: ' .. tostring(volume) .. '%"')
    end
elseif action == 'toggle' then
    os.execute('wpexec ' .. wireplumber_script .. ' action=toggle_sink')

    local status = read_output('wpexec ' .. wireplumber_script .. ' action=print_sink')
    local volume = tonumber(status:match('Volume:%s+([^%a]+)')) * 100
    local mute = status:match('Mute:%s+(%a+)')

    if mute == 'true' then
        local icon = icon_dir .. '/mute.png'
        os.execute('notify-send -i ' .. icon .. ' "Sound muted" "Volume: ' .. tostring(volume) .. '%"')
    else
        local icon = icon_dir .. '/speaker.png'
        os.execute('notify-send -i ' .. icon .. ' "Sound unmuted" "Volume: ' .. tostring(volume) .. '%"')
    end
else
    os.execute('wpexec ' .. wireplumber_script .. ' action=' .. action .. ' step=' .. volume_step)

    local status = read_output('wpexec ' .. wireplumber_script .. ' action=print_sink')
    local volume = tonumber(status:match('Volume:%s+([^%a]+)')) * 100
    local icon = icon_dir .. '/speaker.png'

    os.execute(string.format([[
    notify-send -h string:x-canonical-private-synchronous:audio -h int:value:%s -i %s "Volume: %s%%"
    ]], tostring(volume), icon, tostring(volume)))
end
