-- {{{ Grab environment
local setmetatable = setmetatable
local tonumber = tonumber
local string = { format = string.format, gmatch = string.gmatch }
local io = { popen = io.popen }
local math = { floor = math.floor, modf = math.modf }
-- }}}

local bat_openbsd = {}

local function worker(format, warg)
    local battery = warg or "bat0"
    local filter = string.format("hw.sensors.acpi%s", battery)
    local cmd = string.format("sysctl -a | grep '^%s'", filter)
    local proc = io.popen(cmd)

    local bat_info = {}
    for line in proc:lines("*l") do
        for key, value in string.gmatch(line, "(%S+)=(%S+)") do
	    key = key:gsub(filter .. ".", "")
	    bat_info[key] = value
        end
    end

    -- current state
    local states = {[0] = "↯", -- not charging
                    [1] = "-", -- discharging
                    [2] = "!", -- critical
                    [3] = "+", -- charging
                    [4] = "N/A", -- unknown status
                    [255] = "N/A"} -- unimplemented by the driver
    local state = states[tonumber(bat_info.raw0)]

    -- battery capacity in percent
    local percent = tonumber(bat_info.watthour3 / bat_info.watthour0 * 100)

    local time
    if tonumber(bat_info.power0) < 1 then
        time = "∞"
    else
        local raw_time = bat_info.watthour3 / bat_info.power0
        local hours, hour_fraction = math.modf(raw_time)
        local minutes = math.floor(60 * hour_fraction)
        time = string.format("%d:%0.2d", hours, minutes)
    end

    -- calculate wear level from (last full / design) capacity
    local wear = "N/A"
    if bat_info.watthour0 and bat_info.watthour4 then
        local l_full = tonumber(bat_info.watthour0)
        local design = tonumber(bat_info.watthour4)
        wear = math.floor(l_full / design * 100)
    end

    -- dis-/charging rate as presented by battery
    local rate = bat_info.power0

    -- returns
    --  * state (high "↯", discharging "-", charging "+", N/A "⌁" }
    --  * remaining_capacity (percent)
    --  * remaining_time, by battery
    --  * wear level (percent)
    --  * present_rate (W)
    return {state, percent, time, wear, rate}
end

return setmetatable(bat_openbsd, { __call = function(_, ...) return worker(...) end })
