local awful = require("awful")
local gears = require("gears")
local wibox = require("wibox")
local awmtk = require("awmtk")

local get_pactl_data = function()
    -- Get pactl process data and convert it into a list
    local pactl_processes = {}
    local pactl_process = io.popen("pactl list sink-inputs", "r")
    local pactl_data = pactl_process:read("*a")
    pactl_process:close()
    while pactl_data:match("^(%w.-\n)%w") do
        local test = pactl_data:match("^(%w.-\n)%w")
        table.insert(pactl_processes,test)
        pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1")
    end
    table.insert(pactl_processes,pactl_data)
    return pactl_processes
end

local get_app_volume = function(pid)
    for key,process in pairs(get_pactl_data()) do
        -- Match app by pid
        if process:match("application.process.id = \""..tostring(pid).."\"") then
            return tonumber(process:match("Volume: .-(%d?%d?%d)%%"))
        end
    end
    -- Return nil and an error if not found matching process
    return nil, "Process doesn't play audio"
end

local set_app_volume = function(pid,percentage)
    for key,process in pairs(get_pactl_data()) do
        if process:match("application.process.id = \""..tostring(pid).."\"") then
            local sink_input_id = process:match("Sink Input #(%d*)")
            os.execute("pactl set-sink-input-volume "..sink_input_id.." "..tostring(percentage).."%")
        end
    end
end

return function(args)
    local style = awmtk.style(awmtk.defaults, args.style or {},"client_volume_")
    local device = args.device or "default"
    local icons = args.icons or {
        high = style.volume_icon_high,
        medium = style.volume_icon_medium,
        low = style.volume_icon_low,
        muted = style.volume_icon_muted,
        warn = style.warning_icon
    }
    local function get_icon(percent)
        if percent >= 66 then
            return icons.high
        elseif percent >= 33 then
            return icons.medium
        elseif percent > 0 then
            return icons.low
        else
            return icons.muted
        end
    end
    local slider = wibox.widget {
        widget = wibox.widget.slider,
        id = "widget_slider",
        handle_width = style.client_volume_handle_width or 6,
        bar_height = style.client_volumer_bar_width or 5,
        bar_color = style.client_volume_bar_color or "#55CC60",
        bar_shape = style.bar_shape,
        handler_shape = style.handle_shape,
        forced_height = 20,
        forced_width = 100,
        value = 100,
    }
    local warning_text = wibox.widget {
        markup = "An unknown error has occured",
        widget = wibox.widget.textbox
    }
    local widget = wibox.widget { 
        {
            image = icons.warn,
            resize = true,
            widget = wibox.widget.imagebox,
            forced_height = 20,
            forced_width = 20
        },
        warning_text,
        spacing = style.client_volume_container_spacing_horizontal,
        layout = wibox.layout.fixed.horizontal
    }
    if os.execute("pactl --version") then
        client.connect_signal("focus",function(c)
            local value,err = get_app_volume(c.pid)
            if value then
                slider.value = value
                widget.children[2] = slider
                widget.children[1].image = get_icon(value)
            else
                warning_text.markup = err
                widget.children[2] = warning_text
                widget.children[1].image = icons.warn
            end
        end)
        slider:connect_signal("widget::redraw_needed",function()
            set_app_volume(client.focus.pid,slider.value)
            widget.children[1].image = get_icon(slider.value)
        end)
    else
        warning_text.markup = "pactl is not available"
        widget.children[2] = warning_text
        widget.children[1].image = icons.warn
    end
    return widget
end
