---@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")

-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local sub, format, lower, upper, gsub = string.sub, string.format, string.lower, string.upper, string.gsub
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-- ~~| DropdownItem |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "DiesalDropDownItem"
local Version = 2
-- ~~| DropdownItem Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
    ["frame-hover"] = {
        type = "texture",
        layer = "HIGHLIGHT",
        color = "b3d9ff",
        alpha = 0.1,
    },
}
-- ~~| DropdownItem Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---@class Diesal.GUI.DropDownItem.Methods
local methods = {
    ---@param self Diesal.GUI.Object.DropDown.Item
    ["OnAcquire"] = function(self)
        self:ApplySettings()
        self:SetStylesheet(Stylesheet)
        -- self:SetStylesheet(wireFrameSheet)
        self:Show()
    end,
    ---@param self Diesal.GUI.Object.DropDown.Item
    ["OnRelease"] = function(self)
        self.check:Hide()
    end,
    ---@param self Diesal.GUI.Object.DropDown.Item
    ["ApplySettings"] = function(self)
        if not self.settings.key then
            return
        end

        local settings = self.settings
        local dropdownSettings = settings.parentObject.settings
        local text = self.text
        if settings.position == 1 then
            self:SetPoint("TOPLEFT")
        else
            self:SetPoint("TOPLEFT", settings.parentObject.children[settings.position - 1].frame, "BOTTOMLEFT", 0, 0)
        end
        self:SetPoint("RIGHT")

        self:SetHeight(dropdownSettings.itemHeight)

        self:SetText(settings.value)

        if settings.clickable == false then
            self:UpdateStyle("frame-hover", {
                type = "texture",
                alpha = 0.0,
            })
        end
    end,
    ---@param self Diesal.GUI.Object.DropDown.Item
    ["SetText"] = function(self, text)
        local indentText = (self.settings.indent == 0 and "" or ((" "):rep(self.settings.indent + 3))) .. text
        self.text:SetText(text)
    end,
    ---@param self Diesal.GUI.Object.DropDown.Item
    ["OnClick"] = function(self)
        local settings = self.settings
        local dropdown = settings.parentObject
        if dropdown then
            ---@cast dropdown Diesal.GUI.Object.DropDown
            local dropdownSettings = dropdown.settings
            local dropdownItems = dropdown.children
            local selectedCount = 0

            local selectionTable = {}
            local dropdownText
            if not settings.clickable then
                return
            end
            if settings.key ~= "CLEAR" then
                if dropdownSettings.multiSelect then
                    self:SetSelected(not settings.selected)
                    for i = 1, #dropdownItems do
                        if dropdownItems[i].settings.selected then
                            selectedCount = selectedCount + 1
                            dropdownText = dropdownText and format("%s, %s", dropdownText, dropdownItems[i].settings.value) or dropdownItems[i].settings.value
                            selectionTable[#selectionTable + 1] = dropdownItems[i].settings.key
                        end
                    end
                else
                    for i = 1, #dropdownItems do
                        if dropdownItems[i].SetSelected then
                            dropdownItems[i]:SetSelected(false)
                        end
                    end
                    self:SetSelected(true)
                    dropdownText = settings.value
                    selectionTable = { settings.key }
                    dropdown.dropdown:Hide()
                end
            else
                dropdown.dropdown:Hide()
                dropdown:ClearSelection()
            end
            if dropdownSettings.multiSelect then
                dropdownText = string.format("+%d", selectedCount)
            end
            dropdown:SetText(dropdownText)
            dropdown:FireEvent("OnValueChanged", settings.key, settings.value, selectionTable)
            dropdown:FireEvent("OnValueSelected", settings.key, settings.value, selectionTable)
        end
    end,
    ---@param self Diesal.GUI.Object.DropDown.Item
    ["SetSelected"] = function(self, selected)
        self.settings.selected = selected and true or false
        self.check[selected and "Show" or "Hide"](self.check)
    end,
}

---@class Diesal.GUI.DropDownItem.Settings : Diesal.GUI.ObjectBase.Settings
---@field last boolean
---@field key string
---@field value string
---@field position number
---@field selected boolean
---@field clickable boolean
---@field indent number
---@field header boolean
---@field parentObject Diesal.GUI.Object.DropDown

---@class DiesalDropDownItem : Diesal.GUI.Object.DropDown.Item

-- ~~| DropdownItem Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
    ---@class Diesal.GUI.Object.DropDown.Item : Diesal.GUI.ObjectBase, Diesal.GUI.DropDownItem.Methods
    ---@field check Texture
    ---@field text FontString
    ---@field settings Diesal.GUI.DropDownItem.Settings
    local self = DiesalGUI:Create(Type, true)
    local frame = CreateFrame("Button", nil, UIParent)
    frame:SetToplevel(true)
    frame:SetFrameLevel(999)
    frame:SetFrameStrata("TOOLTIP")
    frame:SetFixedFrameStrata(true)
    self.frame = frame
    self.defaults = {}
    -- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    frame:SetScript("OnClick", function(this, button)
        self:OnClick()
    end)
    frame:SetScript("OnEnter", function(this) end)
    frame:SetScript("OnLeave", function(this) end)

    local text = self:CreateRegion("FontString", "text", frame)
    text:SetPoint("TOPLEFT", 12, -2)
    text:SetPoint("BOTTOMRIGHT", 0, 0)
    text:SetJustifyH("TOP")
    text:SetJustifyH("LEFT")
    text:SetWordWrap(false)

    local check = self:CreateRegion("Texture", "check", frame)
    DiesalStyle:StyleTexture(check, {
        type = "texture",
        position = { 2, nil, 0, nil },
        height = 16,
        width = 16,
        image = { "DiesalGUIcons", { 10, 5, 16, 256, 128 }, "FFFF00" },
    })
    check:Hide()
    -- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    self:SetMethods(methods)
    --[[ for method, func in pairs(methods) do
        self[method] = func
    end ]]
    -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    return self
end
DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)
