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

local awmtk = {}

-- {{{ Utils
awmtk.create_delta = function(name,instance_delta,class_delta,parent_delta) 
    -- To save memory, we create proxies for lower layers called "deltas"
    -- This function creates that proxy layer using metatables
    return setmetatable(instance_delta,{
        __index = function(self,k)
            -- Per-instance overrides are top priority
            if rawget(self,k) then
                return rawget(self,k)
            -- Class-wide overrides are second in priority
            elseif type(class_delta[name]) == "table" 
                and rawget(class_delta[name],k) then
                return rawget(class_delta[name],k)
            -- Parent is fallback
            elseif parent_delta[k] then
                return parent_delta[k]
            end
        end
    })
end

awmtk.create_style = function(name,parent,overrides)
    -- A style is essentially a layer of deltas upon the previous (parent) style
    local new_style = {}
    for name,parent_class in pairs(parent) do 
        new_style[name] = awmtk.create_delta(
            name,
            (overrides and overrides[name]) or {},
            (beautiful.widgets and beautiful.widgets[style_name]) or {},
            parent_class
        )
    end
    return new_style
end 

awmtk.create_template_lib = function(name,parent,overrides)
    -- same thing but beautiful.templates 
    return awmtk.create_delta(
        name,
        overrides or {},
        beautiful.templates or {},
        parent
    )
end

awmtk.build_templates = function(templates,style)
    local new_templates = {}
    for name,template in pairs(awmtk.templates) do
        new_templates[name] = templates[name](style)
    end
    return new_templates
end

awmtk.merge = function(base,overrides)
    for k,v in pairs(overrides) do
        base[k] = v
    end
    return base
end
-- }}}


-- {{{ Default style

-- Default style
awmtk.default = {
    base = setmetatable({
        -- { Backgrounds
        -- custom background color for highlighting elements
        bg_highlight = beautiful.bg_highlight or beautiful.bg_focus,
        -- }
        -- { Borders
        -- Borders for popups
        shape_border_width = beautiful.shape_border_width or 0,
        shape_border_color = beautiful.shape_border_color or beautiful.bg_normal,
        -- }
        -- { Shapes
        margins = 5,
        spacing = 5,
        shape = function(cr, width, height)
            return require("gears").shape.rounded_rect(cr,width,height,5)
        end,
        -- }
    },{__index = beautiful})
}

-- Subclasses
awmtk.default.container = awmtk.create_delta("container",{
},awmtk.default,awmtk.default.base)

awmtk.default.button = awmtk.create_delta("button",{
    margins = 3
},awmtk.default,awmtk.default.base)

awmtk.default.icon = awmtk.create_delta("icon",{
    margins = 1
},awmtk.default,awmtk.default.base)

awmtk.default.textbox = awmtk.create_delta("textbox",{
    font = beautiful.font or "sans 8"
}, awmtk.default,awmtk.default.base)

awmtk.default.separator = awmtk.create_delta("separator",{
    thickness = 1,
    color = beautiful.bg_focus,
    border_width = 0
}, awmtk.default,awmtk.default.base)

awmtk.default.article = awmtk.create_delta("article", {
    icon_size = 16,
    small_font = beautiful.font or "sans 8",
    font_align = "left",
    small_font_align = "left"
}, awmtk.default,awmtk.default.base)

awmtk.default.popup = awmtk.create_delta("popup", {
}, awmtk.default,awmtk.default.base)
-- }}}

-- {{{ Generic templates 
awmtk.templates = {
    -- Templates are built first using the given style, then applied to contents
    -- through returned function
    container = function(style)
        return function(layout,options)
            return awmtk.merge({
                {
                    layout,
                    margins = (options and options.margins) or style.container.margins,
                    widget = wibox.container.margin
                },
                bg = style.container.bg_normal,
                shape = style.container.shape,
                widget = wibox.container.background
            },options or {})
        end
    end,
   
    button = function(style)
        return function(layout,options)
            return awmtk.merge({
                {
                    layout,
                    margins = (options and options.margins) or style.button.margins,
                    widget = wibox.container.margin
                },
                bg = style.button.bg_normal,
                shape = style.button.shape,
                widget = wibox.container.background
            },options or {})
        end
    end,


    textbox = function(style)
        return function(options)
            return awmtk.merge({
                font = style.textbox.font,
                widget = wibox.widget.textbox
            },options or {})
        end
    end,

    hseparator = function(style)
        return function(options)
            awmtk.merge({
                widget = wibox.widget.separator,
                orientation = "horizontal",
                thickness = style.separator.thickness,
                color = style.separator.color,
                border_width = style.separator.border_width
            },options or {})
        end
    end,
    
    vseparator = function(style)
        return function(options)
            awmtk.merge({
                widget = wibox.widget.separator,
                orientation = "vertical",
                thickness = style.separator.thickness,
                color = style.separator.color,
                border_width = style.separator.border_width
            },options or {})
        end
    end,

    -- Article is a template that contains an icon, a headline and a 
    -- short description, side by side. Useful for menus and notifications.
    article = function(style)
        return function(options)
            return awmtk.merge({
                (options.icon and {
                    {
                        {
                            image = options.icon,
                            resize = options.resize,
                            widget = wibox.widget.imagebox
                        },
                        strategy = "exact",
                        height = options.icon_size or
                            style.article.icon_size,
                        width = options.icon_size or 
                            style.article.icon_size,
                        widget = wibox.container.constraint 
                    },
                    widget = wibox.container.place,
                    valign = "center",
                    halign = "center"
                }),
                {
                    {
                        markup = options.title or "",
                        widget = wibox.widget.textbox,
                        font = options.font or style.article.font,
                        align = options.font_align or
                            style.article.font_align,
                        valign = "center"
                    },
                    (options.description and {
                        markup = options.description,
                        widget = wibox.widget.textbox,
                        font = options.small_font or style.article.small_font,
                        align = options.small_font_align or
                            style.article.small_font_align,
                        valign = "center"
                    }),
                    spacing = style.article.spacing,
                    layout = wibox.layout.flex.vertical
                },
                spacing = style.article.spacing,
                layout = wibox.layout.fixed.horizontal,
                bg = style.article.bg_normal,
                widget = wibox.container.background
            }, options or {})
        end
    end,

    popup = function(style)
        return function(widget,options)
            return awmtk.merge({
                widget = {
                    {
                        widget,
                        margins = (options and options.margins) or style.popup.margins,
                        widget = wibox.container.margin
                    },
                    bg = style.popup.bg_normal,
                    widget = wibox.container.background
                },
                shape = style.popup.shape,
                visible = false,
                ontop = true
            },options or {})
        end
    end
}
-- }}}
return awmtk
