local beautiful = require("beautiful")
local gears = require("gears")
local naughty = require("naughty")
local wibox = require("wibox")

local config = require("config").widgets.system_resources

local inspect = require("simple/debug/inspect")

local bar = {
    {
        {
            max_value = 1,
            value = 0,
            widget = wibox.widget.progressbar,
            color = beautiful.system_resources_widget_bar_color,
            background_color = beautiful.system_resources_widget_bar_bg,
            shape = beautiful.system_resources_widget_bar_shape,
            border_color = beautiful.system_resources_widget_border_color,
            border_width = beautiful.system_resources_widget_border_width,
        },
        forced_width = beautiful.system_resources_widget_bar_width,
        direction = "east",
        layout = wibox.container.rotate,
    },
    margins = beautiful.system_resources_widget_bar_margin,
    widget = wibox.container.margin,
}

local bars = wibox.widget {
    bar,
    bar,
    bar,
    layout = wibox.layout.flex.horizontal
}

function readCommand(command)
    local handle = io.popen(command, "r")
    local r = handle:read("*a")
    handle:close()
    return r
end


local cpuBar = bars:get_children()[1]:get_children()[1]:get_children()[1]
function getCpuData()
    local raw = readCommand("cat /proc/stat | head -n 1")
    local data = {raw:match((raw:gsub("[^ ]* ", "([^ ]*) ")))}
    return {
        user = data[3],
        nice = data[4],
        system = data[5],
        idle = data[6],
        iowait = data[7],
        irq = data[8],
        softirq = data[9],
        steal = data[10],
    }
end

local lastCpuTime = -1
local lastCpuIdle = -1

gears.timer {
    timeout = config.bars.refresh_interval,
    call_now = true,
    autostart = true,
    callback = function()

        local data = getCpuData()

        local currentCpuTime = data.user + data.nice + data.system + data.idle + data.iowait + data.irq + data.softirq + data.steal
        local currentCpuIdle = data.idle + data.iowait

        if(lastCpuTime >= 0) then
            cpuBar.value = 1 - (currentCpuIdle - lastCpuIdle) / (currentCpuTime - lastCpuTime)
        end

        lastCpuTime = currentCpuTime
        lastCpuIdle = currentCpuIdle
    end
}


local memoryBar = bars:get_children()[2]:get_children()[1]:get_children()[1]
function getTotalMemory()
    return readCommand("cat /proc/meminfo | grep MemTotal | awk '{print $2}'")
end
function getAvailableMemory()
    return readCommand("cat /proc/meminfo | grep MemAvailable | awk '{print $2}'")
end
function getFreeMemory()
    return readCommand("cat /proc/meminfo | grep MemFree | awk '{print $2}'")
end

gears.timer {
    timeout = config.bars.refresh_interval,
    call_now = true,
    autostart = true,
    callback = function()
        memoryBar.value = 1 - getAvailableMemory() / getTotalMemory()
    end
}


local swapBar = bars:get_children()[3]:get_children()[1]:get_children()[1]
function getTotalSwap()
    return readCommand("cat /proc/meminfo | grep SwapTotal | awk '{print $2}'")
end
function getFreeSwap()
    return readCommand("cat /proc/meminfo | grep SwapFree | awk '{print $2}'")
end

gears.timer {
    timeout = config.bars.refresh_interval,
    call_now = true,
    autostart = true,
    callback = function()
        swapBar.value = 1 - getFreeSwap() / getTotalSwap()
    end
}




local battery = wibox.widget {
    {
        markup = "-- %",
        align = "center",
        valign = "center",
        widget = wibox.widget.textbox,
    },
    margins = beautiful.system_resources_widget_battery_margin,
    widget = wibox.container.margin,
}

local batteryText = battery:get_children()[1]

local rawBatteries = readCommand("ls -A1 /sys/class/power_supply")

function getBatteries()
    return rawBatteries:gmatch("([^\n]+)")
end

function hasBattery()
    return rawBatteries:len() > 0
end

function getBatteryCapacity()
    local charge = 0
    local capacity = 0
    for b in getBatteries() do
        if readCommand("cat /sys/class/power_supply/" .. b .. "/type"):match("Battery") then
            charge = charge + readCommand("cat /sys/class/power_supply/" .. b .. "/energy_now")
            capacity = capacity + readCommand("cat /sys/class/power_supply/" .. b .. "/energy_full")
        end
    end
    return charge / capacity
end

function isCharging()
    for b in getBatteries() do
        if readCommand("cat /sys/class/power_supply/" .. b .. "/type"):match("Battery") then
            return readCommand("cat /sys/class/power_supply/" .. b .. "/status") ~= "Discharging"
        end
    end
    return nil
end

if hasBattery() then
    gears.timer {
        timeout = config.battery.refresh_interval,
        call_now = true,
        autostart = true,
        callback = function()
            batteryText.markup = string.format("%." .. config.battery.precision .. "f", getBatteryCapacity() * 100) .. "%"
        end
    }
else
    battery = nil
end



return {
    bars = bars,
    battery = battery,
}