------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------

local love       = require 'love'
local make_class = require 'src.utils.classes'
local collisions = require 'src.utils.colls'
local UIElement  = require 'src.ui.element'
local Color      = require 'src.utils.color'


------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------

local Bar = make_class(UIElement)


------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------

function Bar:_init(callback, val_fn, min, max, w, h, color, sel_color, press_col, float, x, y)
    UIElement._init(self, x, y, float)
    self.callback  = callback
    self.val_fn    = val_fn
    self.min       = min
    self.max       = max
    self.w         = w
    self.h         = h
    self.base_col  = color  ~= nil and color  or Color(255, 255, 255)
    self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
    self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
    self.disbl_col = Color(95, 63, 75)
end


function Bar:set_dimensions()
    self.w = self.w
    self.h = self.h
end


function Bar:draw()
    local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))

    local v = (self.val_fn() + math.abs(self.min)) / (self.max + math.abs(self.min))

    love.graphics.setColor(color.r, color.g, color.b)
    love.graphics.rectangle('line', self.x, self.y, self.w, self.h)
    love.graphics.rectangle('fill', self.x, self.y, self.w * v, self.h)
    love.graphics.setColor()
end


function Bar:_mouse2bar(x)
    local v = math.max(math.min(((x - self.x) / self.w), 1.0), 0.0)
    return (v * (self.max + math.abs(self.min))) - self.min
end


function Bar:mousemoved(x, y)
    -- Select if the pointer is inside the button's bounding rect.
    self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)

    -- If the button was pressed then check if the pointer is no longer inside the button.
    if self.pressed then
        -- If it's not, then mark the button as "was pressed".
        self.pressed     = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
        self.was_pressed = true
        self.callback(self:_mouse2bar(x))
    end

    -- If the button was pressed and the pointer is inside the button right now.
    if self.was_pressed and collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) then
        -- Then mark the button as pressed again.
        self.pressed     = true
        self.was_pressed = false
        self.callback(self:_mouse2bar(x))
    end
end


function Bar:mousepressed(x, y, btn)
    -- If the pointer was inside the button when it was pressed then mark the button as pressed.
    if btn == 0 then
        self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
    end
end


function Bar:mousereleased(x, _, btn)
    if btn == 0 then
        if self.pressed then
            -- If the button was pressed then execute the callback if any and unmark as pressed.
            if self.callback ~= nil then
                self.callback(self:_mouse2bar(x))
            end

            self.pressed = false
        end

        -- The button no longer was pressed.
        self.was_pressed = false
    end
end


------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------

return Bar
