---@type Diesal.GUI
local DiesalGUI = LibStub("DiesalGUI-2.0")
---@type Diesal.Tools
local DiesalTools = LibStub("DiesalTools-2.0")
---@type Diesal.Style
local DiesalStyle = LibStub("DiesalStyle-2.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, tonumber, select = type, tonumber, select
local pairs, ipairs, next = pairs, ipairs, next
local min, max = math.min, math.max
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent, GetCursorPosition = CreateFrame, UIParent, GetCursorPosition
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
local GetSpellInfo, GetBonusBarOffset, GetDodgeChance = GetSpellInfo, GetBonusBarOffset, GetDodgeChance
local GetCombatRatingBonus = GetCombatRatingBonus
-- ~~| Button |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "DiesalCheckBox"
local Version = 1
-- ~~| Button Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
    ["frame-background"] = {
        type = "texture",
        layer = "BACKGROUND",
        color = "000000",
        alpha = 0.60,
        position = -2,
    },
    ["frame-inline"] = {
        type = "outline",
        layer = "BORDER",
        color = "000000",
        alpha = 0.6,
        position = -2,
    },
    ["frame-outline"] = {
        type = "outline",
        layer = "BORDER",
        color = "FFFFFF",
        alpha = 0.02,
        position = -1,
    },
}
local checkBoxStyle = {
    base = {
        type = "texture",
        layer = "ARTWORK",
        color = Colors.UI_A400,
        position = -3,
    },
    disabled = {
        type = "texture",
        color = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.35),
    },
    enabled = {
        type = "texture",
        color = Colors.UI_A400,
    },
}

local wireFrame = {
    ["frame-white"] = {
        type = "outline",
        layer = "OVERLAY",
        color = "ffffff",
    },
}
-- ~~| Button Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---@class Diesal.GUI.CheckBox.Settings
---@field height number
---@field width number
---@field checked boolean
---@field disabled boolean

---@class Diesal.GUI.CheckBox.Methods
local methods = {
    ---@param self Diesal.GUI.Object.CheckBox
    ["OnAcquire"] = function(self)
        self:ApplySettings()
        self:SetStylesheet(Stylesheet)
        self:Enable()
        -- self:SetStylesheet(wireFrameSheet)
        self:Show()
    end,

    ---@param self Diesal.GUI.Object.CheckBox
    ["OnRelease"] = function(self) end,

    ---@param self Diesal.GUI.Object.CheckBox
    ["ApplySettings"] = function(self)
        local settings = self.settings
        local frame = self.frame

        self:SetWidth(settings.width)
        self:SetHeight(settings.height)
    end,

    ---@param self Diesal.GUI.Object.CheckBox
    ---@param value boolean
    ["SetChecked"] = function(self, value)
        self.settings.checked = value
        self.frame:SetChecked(value)
        self.value = self.settings.checked

        self[self.settings.disabled and "Disable" or "Enable"](self)
    end,
    ["GetChecked"] = function(self)
        return self.settings.checked
    end,
    ["Disable"] = function(self)
        self.settings.disabled = true
        DiesalStyle:StyleTexture(self.check, checkBoxStyle.disabled)
        self.frame:Disable()
    end,
    ["Enable"] = function(self)
        self.settings.disabled = false
        DiesalStyle:StyleTexture(self.check, checkBoxStyle.enabled)
        self.frame:Enable()
    end,
    ["RegisterForClicks"] = function(self, ...)
        self.frame:RegisterForClicks(...)
    end,
}

---@class DiesalCheckBox : Diesal.GUI.Object.CheckBox

-- ~~| Button Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
    ---@class Diesal.GUI.Object.CheckBox : Diesal.GUI.ObjectBase, Diesal.GUI.CheckBox.Methods
    ---@field check Texture
    ---@field settings Diesal.GUI.CheckBox.Settings
    ---@field value boolean
    local self = DiesalGUI:Create(Type, true)
    local frame = CreateFrame("CheckButton", nil, UIParent)
    self.frame = frame

    -- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    self.defaults = {
        height = 11,
        width = 11,
    }
    -- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
    -- OnValueChanged, OnEnter, OnLeave, OnDisable, OnEnable
    -- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    local check = self:CreateRegion("Texture", "check", frame)
    DiesalStyle:StyleTexture(check, checkBoxStyle.base)
    frame:SetCheckedTexture(check)
    frame:SetScript("OnClick", function(this, button, ...)
        DiesalGUI:OnMouse(this, button)

        if not self.settings.disabled then
            self:SetChecked(not self.settings.checked)

            if self.settings.checked then
                PlaySound(856)
            else
                PlaySound(857)
            end

            self:FireEvent("OnValueChanged", self.settings.checked)
        end
    end)
    frame:SetScript("OnEnter", function(this)
        self:FireEvent("OnEnter")
    end)
    frame:SetScript("OnLeave", function(this)
        self:FireEvent("OnLeave")
    end)
    frame:SetScript("OnDisable", function(this)
        self:FireEvent("OnDisable")
    end)
    frame:SetScript("OnEnable", function(this)
        self:FireEvent("OnEnable")
    end)

    -- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    self:SetMethods(methods)
    --[[ for method, func in pairs(methods) do
        self[method] = func
    end ]]
    -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    return self
end

DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)
