local MAJOR, MINOR = "DiesalStyle-2.0", 1
---@alias Diesal.Style DiesalStyle-2.0

---@class DiesalStyle-2.0
local DiesalStyle, oldminor = LibStub:NewLibrary(MAJOR, MINOR)

if not DiesalStyle then
    return
end -- No Upgrade needed.
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-2.0")
local LibSharedMedia = LibStub("LibSharedMedia-3.0")

-- ~~| Lib Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local GetIconCoords, HSL = DiesalTools.GetIconCoords, DiesalTools.HSL

-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber = type, select, pairs, tonumber
local next = next
local format, sub = string.format, string.sub
local min, max = math.min, math.max

-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local errorhandler = geterrorhandler()

-- ~~| DiesalStyle Values |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---@type { [string]: { [string]: string } }
DiesalStyle.Media = DiesalStyle.Media or {}
DiesalStyle.ReleasedTextures = DiesalStyle.ReleasedTextures or {}
DiesalStyle.TextureFrame = DiesalStyle.TextureFrame or CreateFrame("Frame")
DiesalStyle.TextureFrame:Hide()
DiesalStyle.Colors = DiesalStyle.Colors or {}
DiesalStyle.Formatters = DiesalStyle.Formatters or {}

-- ~~| DiesalStyle UpValues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local AddonName = ...
local ReleasedTextures = DiesalStyle.ReleasedTextures
local TextureFrame = DiesalStyle.TextureFrame
local Media = DiesalStyle.Media
local Colors = DiesalStyle.Colors
local Formatters = DiesalStyle.Formatters

-- ~~| Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local OUTLINES = { "_LEFT", "_RIGHT", "_TOP", "_BOTTOM" }
local MEDIA_PATH = MEDIA_PATH
    or type(AddonName) == "table" and string.format("Interface\\AddOns\\Media\\")
    or AddonName == "DiesalLibs" and string.format("Interface\\AddOns\\%s\\%s\\Media\\", AddonName, MAJOR)
    or string.format("Interface\\AddOns\\%s\\Libs\\%s\\Media\\", AddonName, MAJOR)
local DEFAULT_COLOR = "FFFFFF"
local DEFAULT_GRADIENT_ORIENTATION = "horizontal"
local DEFAULT_LAYER = "ARTWORK"

-- ~~| Local Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function addMedia(mediaType, name, mediaFile)
    Media[mediaType] = Media[mediaType] or {}
    -- update or create new media entry
    Media[mediaType][name] = MEDIA_PATH .. mediaFile
end

local function getMedia(mediaType, name)
    if not Media[mediaType] then
        error("media type: " .. mediaType .. " does not exist", 2)
        return
    end
    if not Media[mediaType][name] then
        error('media: "' .. name .. '" does not exist', 2)
        return
    end
    return Media[mediaType][name]
end

---@return Diesal.Style.Texture
local function newTexture()
    local newTexture = next(ReleasedTextures)
    if not newTexture then
        newTexture = TextureFrame:CreateTexture()
    else
        newTexture:Show()
        ReleasedTextures[newTexture] = nil
    end
    return newTexture
end

local function releaseTexture(texture)
    -- reset texture
    texture:ClearAllPoints()
    texture:SetDrawLayer("ARTWORK", 0)
    -- texture:SetTexCoord(0,1,0,1)
    -- specific order based on testing! for a close as possible full texture reset
    -- texture:SetGradientAlpha('HORIZONTAL',1,1,1,1,1,1,1,1)
    -- texture:SetColorTexture(0,0,0,0)
    -- texture:SetTexture()
    -- texture:SetVertexColor(1,1,1,1)

    texture:SetParent(TextureFrame)
    texture:Hide()
    texture.style = nil

    if ReleasedTextures[texture] then
        error("Attempt to Release a texture that is already released", 2)
    end
    ReleasedTextures[texture] = true
end

local function round(number, base)
    base = base or 1
    return floor((number + base / 2) / base) * base
end

local function GetBlizzColorValues(value)
    if not value then
        return
    end

    if type(value) == "table" and #value >= 3 then
        return value[1] / 255, value[2] / 255, value[3] / 255
    elseif type(value) == "string" then
        return tonumber(sub(value, 1, 2), 16) / 255, tonumber(sub(value, 3, 4), 16) / 255, tonumber(sub(value, 5, 6), 16) / 255
    end
end

local function formatCoords(coords)
    if type(coords) ~= "table" then
        return
    end

    if #coords == 5 then
        return { GetIconCoords(coords[1], coords[2], coords[3], coords[4], coords[5]) }
    else
        return coords
    end
end

local function formatFile(file)
    if type(file) ~= "string" and type(file) ~= "number" then
        return
    end

    return Media.texture[file] or file
end

local function formatPosition(position)
    if type(position) ~= "table" and type(position) ~= "number" then
        return
    end

    return type(position) == "number" and { position, position, position, position } or position
end

---@param orientation string
local function formatOrientation(orientation)
    if type(orientation) ~= "string" then
        return
    end

    return orientation:upper()
end

local function formatAlpha(alpha)
    if type(alpha) ~= "table" and type(alpha) ~= "number" then
        return
    end

    return type(alpha) == "number" and { alpha, alpha } or alpha
end

local function CreateColor(r, g, b, a)
    return {
        r = r or 0,
        g = g or 0,
        b = b or 0,
        a = a or 1,
    }
end

-- error handling
local function setColor(texture, r, g, b, a)
    local status, err = pcall(texture.SetColorTexture, texture, r, g, b, a)
    if not status then
        errorhandler('error in "' .. (texture.style.name or "texture") .. '" ' .. texture.style.mode .. " or alpha setting", r, g, b, a)
    end
end
local function setGradient(texture, orientation, r1, g1, b1, a1, r2, g2, b2, a2)
    local status, err = pcall(texture.SetGradient, texture, orientation, CreateColor(r1, g1, b1, a1), CreateColor(r2, g2, b2, a2))
    if not status then
        errorhandler('error in "' .. (texture.style.name or "texture") .. '" ' .. texture.style.mode .. " or alpha setting.")
    end
end
-- ~~| Media |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
do -- | Set Colors |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    do -- google material colors
        Colors.red_50 = "fde0dc"
        Colors.red_100 = "f9bdbb"
        Colors.red_200 = "f69988"
        Colors.red_300 = "f36c60"
        Colors.red_400 = "e84e40"
        Colors.red_500 = "e51c23"
        Colors.red_600 = "dd191d"
        Colors.red_700 = "d01716"
        Colors.red_800 = "c41411"
        Colors.red_900 = "b0120a"
        Colors.red_A100 = "FF8A80"
        Colors.red_A200 = "FF5252"
        Colors.red_A400 = "FF1744"
        Colors.red_A700 = "D50000"
        Colors.pink_50 = "fce4ec"
        Colors.pink_100 = "f8bbd0"
        Colors.pink_200 = "f48fb1"
        Colors.pink_300 = "f06292"
        Colors.pink_400 = "ec407a"
        Colors.pink_500 = "e91e63"
        Colors.pink_600 = "d81b60"
        Colors.pink_700 = "c2185b"
        Colors.pink_800 = "ad1457"
        Colors.pink_900 = "880e4f"
        Colors.pink_A100 = "FF80AB"
        Colors.pink_A200 = "FF4081"
        Colors.pink_A400 = "F50057"
        Colors.pink_A700 = "C51162"
        Colors.purple_50 = "f3e5f5"
        Colors.purple_100 = "e1bee7"
        Colors.purple_200 = "ce93d8"
        Colors.purple_300 = "ba68c8"
        Colors.purple_400 = "ab47bc"
        Colors.purple_500 = "9c27b0"
        Colors.purple_600 = "8e24aa"
        Colors.purple_700 = "7b1fa2"
        Colors.purple_800 = "6a1b9a"
        Colors.purple_900 = "4a148c"
        Colors.purple_A100 = "EA80FC"
        Colors.purple_A200 = "E040FB"
        Colors.purple_A400 = "D500F9"
        Colors.purple_A700 = "AA00FF"
        Colors.dark_purple_50 = "ede7f6"
        Colors.dark_purple_100 = "d1c4e9"
        Colors.dark_purple_200 = "b39ddb"
        Colors.dark_purple_300 = "9575cd"
        Colors.dark_purple_400 = "7e57c2"
        Colors.dark_purple_500 = "673ab7"
        Colors.dark_purple_600 = "5e35b1"
        Colors.dark_purple_700 = "512da8"
        Colors.dark_purple_800 = "4527a0"
        Colors.dark_purple_900 = "311b92"
        Colors.dark_purple_A100 = "B388FF"
        Colors.dark_purple_A200 = "7C4DFF"
        Colors.dark_purple_A400 = "651FFF"
        Colors.dark_purple_A700 = "6200EA"
        Colors.indigo_50 = "e8eaf6"
        Colors.indigo_100 = "c5cae9"
        Colors.indigo_200 = "9fa8da"
        Colors.indigo_300 = "7986cb"
        Colors.indigo_400 = "5c6bc0"
        Colors.indigo_500 = "3f51b5"
        Colors.indigo_600 = "3949ab"
        Colors.indigo_700 = "303f9f"
        Colors.indigo_800 = "283593"
        Colors.indigo_900 = "1a237e"
        Colors.indigo_A100 = "8C9EFF"
        Colors.indigo_A200 = "536DFE"
        Colors.indigo_A400 = "3D5AFE"
        Colors.indigo_A700 = "304FFE"
        Colors.blue_50 = "e7e9fd"
        Colors.blue_100 = "d0d9ff"
        Colors.blue_200 = "afbfff"
        Colors.blue_300 = "91a7ff"
        Colors.blue_400 = "738ffe"
        Colors.blue_500 = "5677fc"
        Colors.blue_600 = "4e6cef"
        Colors.blue_700 = "455ede"
        Colors.blue_800 = "3b50ce"
        Colors.blue_900 = "2a36b1"
        Colors.blue_A100 = "82B1FF"
        Colors.blue_A200 = "448AFF"
        Colors.blue_A400 = "2979FF"
        Colors.blue_A700 = "2962FF"
        Colors.light_blue_50 = "e1f5fe"
        Colors.light_blue_100 = "b3e5fc"
        Colors.light_blue_200 = "81d4fa"
        Colors.light_blue_300 = "4fc3f7"
        Colors.light_blue_400 = "29b6f6"
        Colors.light_blue_500 = "03a9f4"
        Colors.light_blue_600 = "039be5"
        Colors.light_blue_700 = "0288d1"
        Colors.light_blue_800 = "0277bd"
        Colors.light_blue_900 = "01579b"
        Colors.light_blue_A100 = "80D8FF"
        Colors.light_blue_A200 = "40C4FF"
        Colors.light_blue_A400 = "00B0FF"
        Colors.light_blue_A700 = "0091EA"
        Colors.cyan_50 = "e0f7fa"
        Colors.cyan_100 = "b2ebf2"
        Colors.cyan_200 = "80deea"
        Colors.cyan_300 = "4dd0e1"
        Colors.cyan_400 = "26c6da"
        Colors.cyan_500 = "00bcd4"
        Colors.cyan_600 = "00acc1"
        Colors.cyan_700 = "0097a7"
        Colors.cyan_800 = "00838f"
        Colors.cyan_900 = "006064"
        Colors.cyan_A100 = "84FFFF"
        Colors.cyan_A200 = "18FFFF"
        Colors.cyan_A400 = "00E5FF"
        Colors.cyan_A700 = "00B8D4"
        Colors.teal_50 = "e0f2f1"
        Colors.teal_100 = "b2dfdb"
        Colors.teal_200 = "80cbc4"
        Colors.teal_300 = "4db6ac"
        Colors.teal_400 = "26a69a"
        Colors.teal_500 = "009688"
        Colors.teal_600 = "00897b"
        Colors.teal_700 = "00796b"
        Colors.teal_800 = "00695c"
        Colors.teal_900 = "004d40"
        Colors.teal_A100 = "A7FFEB"
        Colors.teal_A200 = "64FFDA"
        Colors.teal_A400 = "1DE9B6"
        Colors.teal_A700 = "00BFA5"
        Colors.green_50 = "d0f8ce"
        Colors.green_100 = "a3e9a4"
        Colors.green_200 = "72d572"
        Colors.green_300 = "42bd41"
        Colors.green_400 = "2baf2b"
        Colors.green_500 = "4CAF50"
        Colors.green_600 = "0a8f08"
        Colors.green_700 = "0a7e07"
        Colors.green_800 = "056f00"
        Colors.green_900 = "0d5302"
        Colors.green_A100 = "B9F6CA"
        Colors.green_A200 = "69F0AE"
        Colors.green_A400 = "00E676"
        Colors.green_A700 = "00C853"
        Colors.light_green_50 = "f1f8e9"
        Colors.light_green_100 = "dcedc8"
        Colors.light_green_200 = "c5e1a5"
        Colors.light_green_300 = "aed581"
        Colors.light_green_400 = "9ccc65"
        Colors.light_green_500 = "8bc34a"
        Colors.light_green_600 = "7cb342"
        Colors.light_green_700 = "689f38"
        Colors.light_green_800 = "558b2f"
        Colors.light_green_900 = "33691e"
        Colors.light_green_A100 = "CCFF90"
        Colors.light_green_A200 = "B2FF59"
        Colors.light_green_A400 = "76FF03"
        Colors.light_green_A700 = "64DD17"
        Colors.lime_50 = "f9fbe7"
        Colors.lime_100 = "f0f4c3"
        Colors.lime_200 = "e6ee9c"
        Colors.lime_300 = "dce775"
        Colors.lime_400 = "d4e157"
        Colors.lime_500 = "cddc39"
        Colors.lime_600 = "c0ca33"
        Colors.lime_700 = "afb42b"
        Colors.lime_800 = "9e9d24"
        Colors.lime_900 = "827717"
        Colors.lime_A100 = "F4FF81"
        Colors.lime_A200 = "EEFF41"
        Colors.lime_A400 = "C6FF00"
        Colors.lime_A700 = "AEEA00"
        Colors.yellow_50 = "fffde7"
        Colors.yellow_100 = "fff9c4"
        Colors.yellow_200 = "fff59d"
        Colors.yellow_300 = "fff176"
        Colors.yellow_400 = "ffee58"
        Colors.yellow_500 = "ffeb3b"
        Colors.yellow_600 = "fdd835"
        Colors.yellow_700 = "fbc02d"
        Colors.yellow_800 = "f9a825"
        Colors.yellow_900 = "f57f17"
        Colors.yellow_A100 = "FFFF8D"
        Colors.yellow_A200 = "FFFF00"
        Colors.yellow_A400 = "FFEA00"
        Colors.yellow_A700 = "FFD600"
        Colors.amber_50 = "fff8e1"
        Colors.amber_100 = "ffecb3"
        Colors.amber_200 = "ffe082"
        Colors.amber_300 = "ffd54f"
        Colors.amber_400 = "ffca28"
        Colors.amber_500 = "ffc107"
        Colors.amber_600 = "ffb300"
        Colors.amber_700 = "ffa000"
        Colors.amber_800 = "ff8f00"
        Colors.amber_900 = "ff6f00"
        Colors.amber_A100 = "FFE57F"
        Colors.amber_A200 = "FFD740"
        Colors.amber_A400 = "FFC400"
        Colors.amber_A700 = "FFAB00"
        Colors.orange_50 = "fff3e0"
        Colors.orange_100 = "ffe0b2"
        Colors.orange_200 = "ffcc80"
        Colors.orange_300 = "ffb74d"
        Colors.orange_400 = "ffa726"
        Colors.orange_500 = "ff9800"
        Colors.orange_600 = "fb8c00"
        Colors.orange_700 = "f57c00"
        Colors.orange_800 = "ef6c00"
        Colors.orange_900 = "e65100"
        Colors.orange_A100 = "FFD180"
        Colors.orange_A200 = "FFAB40"
        Colors.orange_A400 = "FF9100"
        Colors.orange_A700 = "FF6D00"
        Colors.deep_orange_50 = "fbe9e7"
        Colors.deep_orange_100 = "ffccbc"
        Colors.deep_orange_200 = "ffab91"
        Colors.deep_orange_300 = "ff8a65"
        Colors.deep_orange_400 = "ff7043"
        Colors.deep_orange_500 = "ff5722"
        Colors.deep_orange_600 = "f4511e"
        Colors.deep_orange_700 = "e64a19"
        Colors.deep_orange_800 = "d84315"
        Colors.deep_orange_900 = "bf360c"
        Colors.deep_orange_A100 = "FF9E80"
        Colors.deep_orange_A200 = "FF6E40"
        Colors.deep_orange_A400 = "FF3D00"
        Colors.deep_orange_A700 = "DD2C00"
        Colors.brown_50 = "efebe9"
        Colors.brown_100 = "d7ccc8"
        Colors.brown_200 = "bcaaa4"
        Colors.brown_300 = "a1887f"
        Colors.brown_400 = "8d6e63"
        Colors.brown_500 = "795548"
        Colors.brown_600 = "6d4c41"
        Colors.brown_700 = "5d4037"
        Colors.brown_800 = "4e342e"
        Colors.brown_900 = "3e2723"
        Colors.gray_50 = "fafafa"
        Colors.gray_100 = "f5f5f5"
        Colors.gray_200 = "eee"
        Colors.gray_300 = "e0e0e0"
        Colors.gray_400 = "bdbdbd"
        Colors.gray_500 = "9e9e9e"
        Colors.gray_600 = "757575"
        Colors.gray_700 = "616161"
        Colors.gray_800 = "424242"
        Colors.gray_900 = "212121"
        Colors.blue_gray_50 = "eceff1"
        Colors.blue_gray_100 = "cfd8dc"
        Colors.blue_gray_200 = "b0bec5"
        Colors.blue_gray_300 = "90a4ae"
        Colors.blue_gray_400 = "78909c"
        Colors.blue_gray_500 = "607d8b"
        Colors.blue_gray_600 = "546e7a"
        Colors.blue_gray_700 = "455a64"
        Colors.blue_gray_800 = "37474f"
        Colors.blue_gray_900 = "263238"
    end
    do -- Base UI Colors
        Colors.UI_Hue = 210
        Colors.UI_Saturation = 0.24

        Colors.UI_TEXT = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.9)

        -- level 1
        Colors.UI_100 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.03) -- BG
        Colors.UI_150 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.05)
        -- level 2
        Colors.UI_200 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.07)
        -- level 3
        Colors.UI_300 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.12)
        Colors.UI_300_GR = { HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.12), HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.11) }
        Colors.UI_350 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.15)
        Colors.UI_350_GR = { HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.17), HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.14) }
        -- level 4
        Colors.UI_400 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.20)
        Colors.UI_400_GR = { HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.20), HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.17) }
        Colors.UI_450_GR = { HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.24), HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.20) }
        -- level 5
        Colors.UI_500 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.29)
        Colors.UI_500_GR = { HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.29), HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.26) }

        Colors.UI_600_GR = { HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.35), HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.32) }

        -- font Colors -35
        Colors.UI_F450 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.75)
        Colors.UI_F350 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 0.60)

        Colors.UI_1000 = HSL(Colors.UI_Hue, Colors.UI_Saturation, 1)

        Colors.UI_A900 = HSL(Colors.UI_Hue, 1, 0.7)
        Colors.UI_A800 = HSL(Colors.UI_Hue, 1, 0.65)
        Colors.UI_A700 = HSL(Colors.UI_Hue, 1, 0.6)
        Colors.UI_A600 = HSL(Colors.UI_Hue, 1, 0.55)
        Colors.UI_A500 = HSL(Colors.UI_Hue, 1, 0.5)
        Colors.UI_A400 = HSL(Colors.UI_Hue, 1, 0.45)
        Colors.UI_A300 = HSL(Colors.UI_Hue, 1, 0.4)
        Colors.UI_A200 = HSL(Colors.UI_Hue, 1, 0.35)
        Colors.UI_A100 = HSL(Colors.UI_Hue, 1, 0.3)
    end
    -- Class Colors
    do
        Colors.WARRIOR = "c79c6e"
        Colors.PALADIN = "f58cba"
        Colors.HUNTER = "abd473"
        Colors.ROGUE = "fff569"
        Colors.PRIEST = "ffffff"
        Colors.DEATHKNIGHT = "c41f3b"
        Colors.SHAMAN = "0070de"
        Colors.MAGE = "69ccf0"
        Colors.WARLOCK = "9482c9"
        Colors.MONK = "00ff96"
        Colors.DRUID = "ff7d0a"
        Colors.DEMONHUNTER = "a330c9"
        Colors.EVOKER = "33937f"
    end
end
do -- | Text Formatters |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Formatters.tooltip = "|cff" .. Colors.gray_50 .. "%s\n|cff" .. Colors.yellow_500 .. "%s"
end
do -- | Set Media |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    addMedia("font", "calibrib", "Fonts\\calibrib.ttf")
    -- monospaced
    addMedia("font", "DejaVuSansMono", "Fonts\\DejaVuSansMono.ttf")
    addMedia("font", "DejaVuSansMonoBold", "Fonts\\DejaVuSansMono-Bold.ttf")

    addMedia("font", "FiraMonoMedium", "Fonts\\FiraMono-Medium.ttf")
    addMedia("font", "FiraMonoRegular", "Fonts\\FiraMono-Regular.ttf")
    addMedia("font", "FiraMonoBold", "Fonts\\FiraMono-Bold.ttf")

    addMedia("font", "HackRegular", "Fonts\\Hack-Regular.ttf")
    addMedia("font", "HackBold", "Fonts\\Hack-Bold.ttf")

    addMedia("font", "InconsolataRegular", "Fonts\\Inconsolata-Regular.ttf")
    addMedia("font", "InconsolataBold", "Fonts\\Inconsolata-Bold.ttf")

    addMedia("font", "LucidiaMono", "Fonts\\LUCON.ttf")

    addMedia("font", "MonoFur", "Fonts\\monof55.ttf")
    addMedia("font", "MonoFurItalic", "Fonts\\monof56.ttf")

    addMedia("font", "OfficeCodeProRegular", "Fonts\\OfficeCodePro-Regular.ttf")
    addMedia("font", "OfficeCodeProMedium", "Fonts\\OfficeCodePro-Medium.ttf")
    addMedia("font", "OfficeCodeProBold", "Fonts\\OfficeCodePro-Bold.ttf")

    addMedia("font", "RobotoMonoRegular", "Fonts\\RobotoMono-Regular.ttf")
    addMedia("font", "RobotoMonoMedium", "Fonts\\RobotoMono-Medium.ttf")
    addMedia("font", "RobotoMonoBold", "Fonts\\RobotoMono-Bold.ttf")

    addMedia("font", "SourceCodeProRegular", "Fonts\\SourceCodePro-Regular.ttf")
    addMedia("font", "SourceCodeProMedium", "Fonts\\SourceCodePro-Medium.ttf")
    addMedia("font", "SourceCodeProSemibold", "Fonts\\SourceCodePro-Semibold.ttf")
    addMedia("font", "SourceCodeProBold", "Fonts\\SourceCodePro-Bold.ttf")
    addMedia("font", "SourceCodeProBlack", "Fonts\\SourceCodePro-Black.ttf")

    addMedia("font", "UbuntuMonoBold", "Fonts\\UbuntuMono-B.ttf")
    addMedia("font", "UbuntuMonoRegular", "Fonts\\UbuntuMono-R.ttf")

    -- pixel fonts
    addMedia("font", "FiraSans", "Fonts\\FiraSans-Regular.ttf")
    addMedia("font", "Standard0755", "Fonts\\Standard0755.ttf")
    addMedia("font", "FFF Intelligent Thin Condensed", "Fonts\\FFF Intelligent Thin Condensed.ttf")

    -- Icons
    addMedia("texture", "DiesalGUIcons", "Textures\\DiesalGUIcons16x256x128.tga")
    addMedia("texture", "DiesalGUIcons64", "Textures\\DiesalGUIcons64x256x256.tga")
    addMedia("texture", "DiesalGUIcons32", "Textures\\DiesalGUIcons32x256x256.tga")
    addMedia("texture", "DiesalButtonIcons32", "Textures\\DiesalButtonIcons32x128x512.tga")

    -- Shadows
    addMedia("border", "shadow", "Textures\\shadow.tga")
    addMedia("border", "shadowNoDist", "Textures\\shadowNoDist.tga")
end

do -- | Add LibSharedMedia |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    local font = getMedia("font", "calibrib")
    if font then
        LibSharedMedia:Register("font", "Calibri Bold", font)
    end
    font = getMedia("font", "FiraSans")
    if font then
        LibSharedMedia:Register("font", "Fira Sans", font)
    end
    -- monospaced
    -- LibSharedMedia:Register("font","DejaVuSansMono",getMedia('font','DejaVuSansMono'))
    -- LibSharedMedia:Register("font","Hack",getMedia('font','Hack'))
    -- LibSharedMedia:Register("font","Inconsolata",getMedia('font','Inconsolata'))
    -- LibSharedMedia:Register("font","Fira Sans",getMedia('font','FiraSans'))
    -- LibSharedMedia:Register("font","Source Code Pro",getMedia('font','SourceCodePro'))
    -- pixel fonts
    font = getMedia("font", "Standard0755")
    if font then
        LibSharedMedia:Register("font", "Standard0755", font)
    end
    font = getMedia("font", "FFF Intelligent Thin Condensed")
    if font then
        LibSharedMedia:Register("font", "FFF Intelligent", font)
    end
end
do -- | Set Fonts |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    local font = getMedia("font", "calibrib")
    if font then
        DiesalFontNormal = CreateFont("DiesalFontNormal")
        DiesalFontNormal:SetFont(font, 11, "")
    end

    font = getMedia("font", "Standard0755")
    if font then
        DiesalFontPixel = CreateFont("DiesalFontPixel")
        DiesalFontPixel:SetFont(font, 8, "")
    end

    font = getMedia("font", "Standard0755")
    if font then
        DiesalFontPixelOutLine = CreateFont("DiesalFontPixelOutLine")
        DiesalFontPixelOutLine:SetFont(font, 8, "OUTLINE, MONOCHROME")
        DiesalFontPixelOutLine:SetSpacing(2)
    end

    font = getMedia("font", "FFF Intelligent Thin Condensed")
    if font then
        DiesalFontPixel2 = CreateFont("DiesalFontPixel2")
        DiesalFontPixel2:SetFont(font, 8, "OUTLINE, MONOCHROME")
    end
end

do -- Set Icons
    ---@class DiesalStyle.Icon.Coords
    ---@field column integer
    ---@field row integer

    ---@class DiesalStyle.Icon.File
    ---@field prefix { [1]: string, [2]: string, [3]: string }
    ---@field size { width: integer, height: integer, icon: integer }

    ---@class DiesalStyle.Icon
    ---@field name string
    ---@field file DiesalStyle.Icon.File
    ---@field coords DiesalStyle.Icon.Coords

    ---@class DiesalStyle.Icons : { [string]: table<string, table<string, table<integer,table<string, table<integer, table<integer, DiesalStyle.Icon>>>>>> }
    DiesalStyle.Icons = DiesalStyle.Icons or {}

    local Icons = DiesalStyle.Icons

    ---@class DiesalStyle.IconsByFileColumnRow : { [string]: DiesalStyle.Icon }
    local IconsByFileColumnRow = {}

    ---@class DiesalStyle.IconsByName : { [string]: DiesalStyle.Icon }
    local IconsByName = {}

    function DiesalStyle.AddIcons(iconsToAdd)
        assert(type(iconsToAdd) == "table", "iconsToAdd parameter (1) should be a table")

        local prefixInfo = {
            [1] = { prefix = "prefix1", count = 1, file = 1, iconSize = 1 },
            [2] = { prefix = "prefix2", count = 1, file = 1, iconSize = 1 },
            [3] = { prefix = "prefix3", count = 1, file = 1, iconSize = 1 },
        }

        ---@param prefix integer
        ---@param key string
        ---@param table table
        local function checkType(prefix, key, table)
            assert(type(key) == "string", string.format("key %d for %s not a string.", prefixInfo[prefix].count, prefixInfo[prefix].prefix))
            assert(type(table) == "table", string.format("value %d for %s is not a table.", prefixInfo[prefix].count, prefixInfo[prefix].prefix))
        end

        for p1, p1Table in pairs(iconsToAdd) do
            checkType(1, p1, p1Table)
            Icons[p1] = Icons[p1] or {}
            for p2, p2Table in pairs(p1Table) do
                checkType(2, p2, p2Table)
                Icons[p1][p2] = Icons[p1][p2] or {}
                for p3, p3Table in pairs(p2Table) do
                    checkType(3, p3, p3Table)
                    local filePrefixes = string.format("%s%s%s", p1, p2, p3)
                    Icons[p1][p2][p3] = Icons[p1][p2][p3] or {}
                    for iconSize, fileDimTable in pairs(p3Table) do
                        assert(type(iconSize) == "number", string.format("icon size key %d for %s is not a number.", prefixInfo[3].iconSize, filePrefixes))
                        filePrefixes = string.format("%s[%d]", filePrefixes, iconSize)
                        Icons[p1][p2][p3][iconSize] = Icons[p1][p2][p3][iconSize] or {}
                        for fileDimKey, iconColumns in pairs(fileDimTable) do
                            assert(type(fileDimKey == "string"), string.format("file dimensions key for file %d in %s is not a string.", prefixInfo[3].file, filePrefixes))
                            local fileDims = strsplittable("x", fileDimKey, 2)

                            assert(type(tonumber(fileDims[1])) == "number", string.format("could not obtain width from %s in %s", fileDimKey, filePrefixes))
                            assert(type(tonumber(fileDims[2])) == "number", string.format("could not obtain height from %s in %s", fileDimKey, filePrefixes))
                            Icons[p1][p2][p3][iconSize][fileDimKey] = Icons[p1][p2][p3][iconSize][fileDimKey] or {}

                            filePrefixes = string.format("%s[%s]", filePrefixes, fileDimKey)

                            local fileWidth = tonumber(fileDims[1]) or 0
                            local fileHeight = tonumber(fileDims[2]) or 0
                            local maxColumns = math.floor(fileWidth / iconSize)
                            local maxRows = math.floor(fileHeight / iconSize)

                            local iconsFileTable = Icons[p1][p2][p3][iconSize][fileDimKey]

                            local columnCount = 0
                            local rowCount = 0
                            for column, rows in pairs(iconColumns) do
                                columnCount = columnCount + 1
                                assert(type(column) == "number", string.format("column %d key in %s is not a number.", columnCount, filePrefixes))
                                assert(type(rows) == "table", string.format("column %d value in %s is not a table.", columnCount, filePrefixes))
                                local filePrefixesColumn = string.format("%s[%d]", filePrefixes, column)
                                iconsFileTable[column] = iconsFileTable[column] or {}
                                for row, icon in pairs(rows) do
                                    rowCount = rowCount + 1
                                    assert(type(row) == "number", string.format("row %d key in %s is not a number.", rowCount, filePrefixesColumn))
                                    assert(type(icon) == "string", string.format("row %d value in %s is not a string.", rowCount, filePrefixesColumn))

                                    local filePrefixesColumnRow = string.format("%s[%d]", filePrefixesColumn, row)
                                    local iconName = icon

                                    iconsFileTable[column][row] = {
                                        name = iconName,
                                        file = {
                                            prefix = {
                                                [1] = p1,
                                                [2] = p2,
                                                [3] = p3,
                                            },
                                            size = {
                                                width = fileWidth,
                                                height = fileHeight,
                                                icon = iconSize,
                                            },
                                        },
                                        coords = {
                                            column = column,
                                            row = row,
                                        },
                                    }
                                    IconsByName[iconName] = IconsByName[iconName] or iconsFileTable[column][row]
                                    IconsByFileColumnRow[filePrefixesColumnRow] = iconsFileTable[column][row]
                                end
                                rowCount = 1
                            end
                            prefixInfo[3].file = prefixInfo[3].file + 1
                        end
                        prefixInfo[3].iconSize = prefixInfo[3].iconSize + 1
                    end
                    prefixInfo[3].count = prefixInfo[3].count + 1
                end
                prefixInfo[2].count = prefixInfo[2].count + 1
            end
            prefixInfo[1].count = prefixInfo[1].count + 1
        end
    end

    ---@param iconTable DiesalStyle.Icon
    local function CreateIconStyle(iconTable)
        local fileName = string.format("%s%s%s", iconTable.file.prefix[1], iconTable.file.prefix[2], iconTable.file.prefix[3])
        local iconSize = iconTable.file.size.icon

        fileName = fileName .. (iconSize ~= 16 and iconSize or "")
        local fileWidth = iconTable.file.size.width
        local fileHeight = iconTable.file.size.height
        local column = iconTable.coords.column
        local row = iconTable.coords.row
        return {
            fileName,
            {
                column,
                row,
                iconSize,
                fileWidth,
                fileHeight,
            },
        }
    end

    ---@param iconName string
    function DiesalStyle.GetIconStyleByName(iconName)
        return IconsByName[iconName] and CreateIconStyle(IconsByName[iconName]) or {}
    end

    -- [prefix1][prefix2][prefix3][iconSize][fileWidthxfileHeight][column][row]
    -- DiesalGUIcons16x256x128.tga, Column 3, Row 4
    -- [Diesal][GUI][cons][16][256x128][3][4]
    ---@param iconFile string
    function DiesalStyle.GetIconByFileColumnRow(iconFile)
        return IconsByFileColumnRow[iconFile] and CreateIconStyle(IconsByFileColumnRow[iconFile]) or {}
    end

    -- Camel Case File Name
    local DefaultDiesalIcons = {
        -- Prefix 1
        Diesal = {
            -- Prefix 2
            Button = {
                -- Prefix 3
                Icons = {
                    -- Icon Size
                    [32] = {
                        -- WidthxHeight
                        ["128x512"] = {
                            [1] = {
                                [1] = "background-horseshoe",
                                [2] = "hover-horseshoe",
                                [3] = "normal-horseshoe",
                            },
                            [2] = {
                                [1] = "background-crosshair",
                                [2] = "hover-crosshair",
                                [3] = "normal-crosshair",
                            },
                            [3] = {
                                [1] = "background-crossbones",
                                [2] = "hover-crossbones",
                                [3] = "normal-crossbones",
                            },
                            [4] = {
                                [1] = "background-tag",
                                [2] = "hover-tag",
                                [3] = "normal-tag",
                            },
                            [5] = {
                                [1] = "background-crossed-swords",
                                [2] = "hover-crossed-swords",
                                [3] = "normal-crossed-swords",
                            },
                            [6] = {
                                [1] = "background-oc",
                                [2] = "hover-oc",
                                [3] = "normal-oc",
                            },
                        },
                    },
                },
            },
            -- Prefix 2
            GU = {
                -- Prefix 3
                Icons = {
                    -- Icon Size
                    [16] = {
                        -- WidthxHeight
                        ["256x128"] = {
                            -- Column 1
                            [1] = {
                                -- Row 1
                                [1] = "solid-white-arrow-up",
                                [4] = "outline-textured-rewind",
                                [5] = "outline-textured-question-mark",
                                [6] = "outline-textured-cirle-plus",
                                [7] = "outline-textured-file",
                                [8] = "outline-blue-folder-closed",
                            },
                            [2] = {
                                [1] = "solid-white-arrow-down",
                                [4] = "outline-textured-pause",
                                [5] = "outline-textured-cog",
                                [6] = "outline-textured-cirle-minus",
                                [7] = "outline-textured-folder",
                                [8] = "outline-blue-folder-opened",
                            },
                            [3] = {
                                [1] = "solid-white-arrow-right",
                                [4] = "outline-textured-play",
                                [5] = "outline-textured-reload",
                                [6] = "outline-textured-square-minus",
                                [7] = "outline-textured-folder-plus",
                                [8] = "outline-white-file",
                            },
                            [4] = {
                                [1] = "solid-white-arrow-left",
                                [4] = "outline-textured-fast-forward",
                                [5] = "outline-textured-home",
                                [6] = "outline-textured-square-plus",
                                [7] = "outline-textured-folder-minus",
                                [8] = "outline-multi-cluster",
                            },
                            [5] = {
                                [1] = "solid-white-circl",
                                [4] = "outline-textured-back",
                                [5] = "outline-textured-arrow-down",
                                [8] = "outline-multi-diskette",
                            },
                            [6] = {
                                [4] = "outline-textured-forward",
                                [5] = "outline-textured-arrow-up",
                            },
                            [7] = {
                                [5] = "outline-textured-arrow-right",
                            },
                            [8] = {
                                [5] = "outline-textured-arrow-left",
                            },
                            [9] = {
                                [5] = "outline-textured-arrow-close",
                            },
                            [10] = {
                                [5] = "outline-textured-check",
                            },
                            [11] = {
                                [5] = "outline-textured-lock-unclocked",
                            },
                            [12] = {
                                [5] = "outline-textured-lock-locked",
                            },
                            [13] = {
                                [5] = "outline-textured-lock-delete",
                            },
                            [14] = {
                                [4] = "outline-textured-circle",
                                [5] = "outline-textured-power",
                            },
                            [15] = {
                                [4] = "outline-textured-dropplet-down",
                                [5] = "outline-textured-ellipse",
                            },
                            [16] = {
                                [4] = "outline-textured-dropplet-square",
                            },
                        },
                    },
                    [32] = {
                        ["256x256"] = {
                            [1] = {
                                [1] = "white-horseshoe",
                                [2] = "black-horseshoe",
                            },
                            [2] = {
                                [1] = "white-crosshair",
                                [2] = "black-crosshair",
                            },
                            [3] = {
                                [1] = "white-crossbones",
                                [2] = "black-crossbones",
                            },
                            [4] = {
                                [1] = "white-tag",
                                [2] = "black-tag",
                            },
                            [5] = {
                                [1] = "white-crossed-swords",
                                [2] = "black-crossed-swords",
                            },
                            [6] = {
                                [1] = "white-oc",
                                [2] = "black-oc",
                            },
                        },
                    },
                    [64] = {
                        ["256x256"] = {
                            [1] = {
                                [1] = "marker-droplette-yellow-diamond",
                            },
                            [2] = {
                                [1] = "marker-droplette-green-leaf",
                            },
                            [3] = {
                                [1] = "marker-droplette-teal-star",
                            },
                        },
                    },
                },
            },
        },
    }

    DiesalStyle.AddIcons(DefaultDiesalIcons)
end
-- ~~| DiesalStyle API |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[[
  Texture style table format
  style.layer BACKGROUND | BORDER | ARTWORK | OVERLAY | HIGHLIGHT (texture in this layer is automatically shown when the mouse is over the containing Frame)
  **FontStrings always appear on top of all textures in a given draw layer. avoid using sublayer
  -- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  style.alpha alpha [0 - 1]
  style.alphaEnd alpha [0 - 1]
  style.color hexColor | {Red, Green, Blue} [0-255]
  style.colorEnd hexColor | {Red, Green, Blue} [0-255]
  style.gradient VERTICAL | HORIZONTAL
  -- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  style.texFile texture fileName
  style.texTile true | false
  style.texCoord {left, right, top, bottom} [0-1] | {column,row,size,textureWidth,TextureHeight}
  style.texColor hexColor | {Red,Green,Blue} [0-255]
  style.texColorAlpha alpha [0 - 1]
  -- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  style.offset offset | {Left, Right, Top, Bottom}
  style.width width
  style.height height
]]

-- type                 = 'fill',
-- layer                = 'BACKGROUND',
--
-- gradient             = {'VERTICAL','744d00','996600'}
-- gradient_orientation = 'VERTICAL'|'HORIZONTAL ',
-- gradient_color       = {colorStart,colorEnd},
--
-- image                = {'texture-file', {left,right,top,bottom}, color, tiling_h, tiling_v}
-- image_file           = 'texture-file'
-- image_coords         = {left,right,top,bottom} | {row, coloumn, size, image width, image height }
-- image_color          = "FFFFFF"
-- image_tiling         = {'HORIZNONTAL','VERTICAL'}
--
-- color                = 'FFFFFF',
-- alpha                = 1 | {1,1}
--
-- position             = 0 | {0,0,0,0}

---@alias r number
---@alias g number
---@alias b number

---@class Diesal.Style.RGB : { [1]: r, [2]: g, [3]: b }

---@alias left number
---@alias right number
---@alias top number
---@alias bottom number
---@alias column number
---@alias row number
---@alias textureWidth number
---@alias textureHeight number

---@alias hexString string
---@alias Diesal.Style.Color hexString | Diesal.Style.RGB

---@class Diesal.Style.TexCoord : { [1]: left, [2]: right, [3]: top, [4]: bottom }
---@class Diesal.Style.TexCoord2 : { [1]: column, [2]: row, [3]: size, [4]: textureWidth, [5]: textureHeight }

--[[
  Missing required fields in type `Diesal.Style.Style`:
  `layer`, `alpha`, `alphaEnd`, `color`, `colorEnd`, `gradient`, `gradient_alpha`, `gradient_orientation`, `gradient_color`, `name`, `debug`, `texFile`, `texTile`, `texCoord`, `texColor`, `texColorAlpha`, `type`, `offset`
]]

---@class Diesal.Style.Style
---@field layer? 'BACKGROUND' | 'BORDER' | 'ARTWORK' | 'OVERLAY' | 'HIGHLIGHT'
---@field alpha? number
---@field alphaEnd? number
---@field color? Diesal.Style.Color
---@field colorEnd? Diesal.Style.Color
---@field gradient? { [1]: 'VERTICAL' | 'HORIZONTAL', [2]: string, [3]: string }
---@field gradient_alpha? number
---@field gradient_orientation? 'VERTICAL' | 'HORIZONTAL'
---@field gradient_color? {[1]: Diesal.Style.Color, [2]: Diesal.Style.Color }
---@field image? { [1]: string, [2]: Diesal.Style.TexCoord, [3]: Diesal.Style.Color, [4]: WrapMode, [5]: WrapMode }
---@field image_file? string
---@field image_coords? Diesal.Style.TexCoord | Diesal.Style.TexCoord2
---@field image_color? hexString
---@field image_tiling? { [1]: WrapMode, [2]: WrapMode }
---@field name? string
---@field debug? boolean
---@field texFile? string
---@field texTile? boolean
---@field texCoord? Diesal.Style.TexCoord | Diesal.Style.TexCoord2
---@field texColor? Diesal.Style.Color
---@field texColorAlpha? number
---@field type "texture" | "outline" | "shadow" | "font"
---@field offset? number | { [1]: left, [2]: right, [3]: top, [4]: bottom }
---@field width? number
---@field height? number
---@field position? Diesal.Style.TexCoord
---@field clear? boolean

---@class Diesal.Style.Texture.Style : Diesal.Style.Style
---@field alpha { [1]: number, [2]: number }
---@field image { file: string, coords: Diesal.Style.TexCoord, color: Diesal.Style.Color, tiling: { [1]: WrapMode, [2]: WrapMode } }
---@field gradient { orientation: 'VERTICAL' | 'HORIZONTAL', color: { [1]: Diesal.Style.Color, [2]: Diesal.Style.Color } }
---@field mode string

---@class Diesal.Style.Texture : Texture
---@field style Diesal.Style.Texture.Style?

---@class Diesal.Style.Stylesheet : {[string]: Diesal.Style.Style | Diesal.Style.Texture.Style}

---@param texture Texture
---@param style Diesal.Style.Style
function DiesalStyle:StyleTexture(texture, style)
    -- | Setup Texture.style |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if not texture.style or style.clear then
        ---@diagnostic disable-next-line: missing-fields, inject-field
        texture.style = {}
    end
    -- debugging
    texture.style.name = style.name or texture.style.name
    texture.style.debug = style.debug or texture.style.debug
    -- | Format Settings |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -- Gradient ~~~~~~~~~~~~~~~~~~~~~~~~~
    if style.gradient and type(style.gradient) == "table" then
        local orientation = formatOrientation(style.gradient[1])
        if orientation then
            texture.style.gradient = {
                orientation = orientation,
                color = style.gradient[2] and style.gradient[3] and { style.gradient[2], style.gradient[3] },
            }
        end
    end

    local orientation = formatOrientation(style.gradient_orientation)
    if orientation then
        style.gradient_orientation = orientation -- fuck you
    end

    if not texture.style.gradient and (style.gradient_orientation or style.gradient_alpha or style.gradient_color) then
        texture.style.gradient = {}
    end
    -- Image ~~~~~~~~~~~~~~~~~~~~~~~~~
    if style.image and type(style.image) == "table" then
        local file = formatFile(style.image[1])
        local coords = formatCoords(style.image[2])
        if file and coords then
            texture.style.image = {
                file = file,
                coords = coords,
                color = style.image[3],
                tiling = { style.image[4], style.image[5] },
            }
        end
    end
    if not texture.style.image and style.image_file then
        texture.style.image = {}
    end
    -- | Update Settings |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    texture.style.layer = style.layer or texture.style.layer or DEFAULT_LAYER
    texture.style.position = formatPosition(style.position) or texture.style.position or { 0, 0, 0, 0 }
    texture.style.width = style.width or texture.style.width
    texture.style.height = style.height or texture.style.height
    texture.style.color = style.color or texture.style.color
    texture.style.alpha = formatAlpha(style.alpha) or texture.style.alpha or { 1, 1 }
    -- gradient
    if texture.style.gradient then
        texture.style.gradient.orientation = style.gradient_orientation or texture.style.gradient.orientation or DEFAULT_GRADIENT_ORIENTATION
        texture.style.gradient.color = style.gradient_color or texture.style.gradient.color or { DEFAULT_COLOR, DEFAULT_COLOR }
    end
    -- image
    if texture.style.image then
        texture.style.image.file = formatFile(style.image_file) or texture.style.image.file
        texture.style.image.coords = formatCoords(style.image_coords) or texture.style.image.coords or { 0, 1, 0, 1 }
        texture.style.image.color = style.image_color or texture.style.image.color
        texture.style.image.tiling = style.image_tiling or texture.style.image.tiling
    end
    -- | Apply Settings |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    -- layer
    texture:SetDrawLayer(texture.style.layer, 0)
    -- position
    texture:ClearAllPoints() -- clear offsets
    if texture.style.position[1] then
        texture:SetPoint("LEFT", -texture.style.position[1], 0)
    end
    if texture.style.position[2] then
        texture:SetPoint("RIGHT", texture.style.position[2], 0)
    end
    if texture.style.position[3] then
        texture:SetPoint("TOP", 0, texture.style.position[3])
    end
    if texture.style.position[4] then
        texture:SetPoint("BOTTOM", 0, -texture.style.position[4])
    end
    -- size
    if texture.style.width then
        texture:SetWidth(texture.style.width)
    end
    if texture.style.height then
        texture:SetHeight(texture.style.height)
    end

    if style.debug then
        print(texture:GetHeight(), texture.style.position[1], texture.style.position[2], texture.style.position[3], texture.style.position[4])
    end
    -- [1] Texture > [2] gradient > [3] color
    if texture.style.image then -- [1] Texture
        -- set mode
        texture.style.mode = "image"
        -- clear any old settings
        setGradient(texture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1) -- clear gradient
        texture:SetColorTexture(1, 1, 1, 1) -- clear color
        -- apply settings
        texture:SetTexCoord(texture.style.image.coords[1], texture.style.image.coords[2], texture.style.image.coords[3], texture.style.image.coords[4])
        texture:SetTexture(texture.style.image.file, texture.style.image.tiling and texture.style.image.tiling[1], texture.style.image.tiling and texture.style.image.tiling[2])
        texture:SetHorizTile(texture.style.image.tiling[1] and true)
        texture:SetVertTile(texture.style.image.tiling[2] and true)
        local r, g, b = GetBlizzColorValues(texture.style.image.color)
        texture:SetVertexColor(r or 1, g or 1, b or 1, texture.style.alpha[1])
    elseif texture.style.gradient then -- [2] gradient
        -- set mode
        texture.style.mode = "gradient"
        -- clear any old  settings
        texture:SetTexture() -- clear image
        texture:SetColorTexture(1, 1, 1, 1) -- clear color
        -- apply settings
        local r1, g1, b1 = GetBlizzColorValues(texture.style.gradient.color[texture.style.gradient.orientation == "HORIZONTAL" and 1 or 2])
        local r2, g2, b2 = GetBlizzColorValues(texture.style.gradient.color[texture.style.gradient.orientation == "HORIZONTAL" and 2 or 1])
        local a1, a2 =
            texture.style.alpha[texture.style.gradient.orientation == "HORIZONTAL" and 1 or 2], texture.style.alpha[texture.style.gradient.orientation == "HORIZONTAL" and 2 or 1]
        setGradient(texture, texture.style.gradient.orientation, r1, g1, b1, a1, r2, g2, b2, a2)
    elseif texture.style.color then -- [3] color
        -- set mode
        texture.style.mode = "color"
        -- clear any old settings
        texture:SetTexture() -- clear image
        setGradient(texture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1) -- clear gradient
        -- apply settings
        local r, g, b = GetBlizzColorValues(texture.style.color)
        setColor(texture, r, g, b, texture.style.alpha[1])
    else
        -- set mode
        texture.style.mode = "none!"
        -- clear the texture
        texture:SetTexture() -- clear image
        setGradient(texture, "HORIZONTAL", 0, 0, 0, 0, 0, 0, 0, 0) -- clear gradient
        texture:SetColorTexture(0, 0, 0, 0) -- clear color
    end
end

---@param leftTexture Diesal.Style.Texture
---@param rightTexture Diesal.Style.Texture
---@param topTexture Diesal.Style.Texture
---@param bottomTexture Diesal.Style.Texture
---@param style Diesal.Style.Style
function DiesalStyle:StyleOutline(leftTexture, rightTexture, topTexture, bottomTexture, style)
    -- | Setup Texture.style |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if not leftTexture.style or style.clear then
        ---@diagnostic disable-next-line: missing-fields
        leftTexture.style = {}
        rightTexture.style = leftTexture.style
        topTexture.style = leftTexture.style
        bottomTexture.style = leftTexture.style
    end
    local texture = leftTexture
    -- debugging
    texture.style.name = style.name or texture.style.name
    texture.style.debug = style.debug or texture.style.debug
    -- | Format Settings |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if style.gradient and type(style.gradient) == "table" then
        texture.style.gradient = {
            orientation = style.gradient[1]:upper(),
            color = style.gradient[2] and style.gradient[3] and { style.gradient[2], style.gradient[3] },
        }
    end
    style.gradient_orientation = style.gradient_orientation and style.gradient_orientation:upper() --formatOrientation(style.gradient_orientation) -- fuck you
    if not texture.style.gradient and (style.gradient_orientation or style.gradient_alpha or style.gradient_color) then
        texture.style.gradient = {}
    end
    -- | Update Settings |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    texture.style.layer = style.layer or texture.style.layer or DEFAULT_LAYER
    texture.style.position = formatPosition(style.position) or texture.style.position or { 0, 0, 0, 0 }
    texture.style.width = style.width or texture.style.width
    texture.style.height = style.height or texture.style.height
    texture.style.color = style.color or texture.style.color
    texture.style.alpha = formatAlpha(style.alpha) or texture.style.alpha or { 1, 1 }
    -- gradient
    if texture.style.gradient then
        texture.style.gradient.orientation = style.gradient_orientation or texture.style.gradient.orientation or DEFAULT_GRADIENT_ORIENTATION
        texture.style.gradient.color = style.gradient_color or texture.style.gradient.color or { DEFAULT_COLOR, DEFAULT_COLOR }
    end
    -- | Apply Settings |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    -- layer
    leftTexture:SetDrawLayer(texture.style.layer, 0)
    rightTexture:SetDrawLayer(texture.style.layer, 0)
    topTexture:SetDrawLayer(texture.style.layer, 0)
    bottomTexture:SetDrawLayer(texture.style.layer, 0)
    -- position
    leftTexture:ClearAllPoints()
    rightTexture:ClearAllPoints()
    topTexture:ClearAllPoints()
    bottomTexture:ClearAllPoints()

    if texture.style.position[1] then
        leftTexture:SetPoint("LEFT", -texture.style.position[1], 0)
    else
        leftTexture:SetPoint("RIGHT", -texture.style.width, 0)
    end
    if texture.style.position[3] then
        leftTexture:SetPoint("TOP", 0, texture.style.position[3])
    end
    if texture.style.position[4] then
        leftTexture:SetPoint("BOTTOM", 0, -texture.style.position[4])
    end
    if texture.style.position[2] then
        rightTexture:SetPoint("RIGHT", texture.style.position[2], 0)
    else
        rightTexture:SetPoint("LEFT", texture.style.width - (texture.style.position[1] + 1), 0)
    end
    if texture.style.position[3] then
        rightTexture:SetPoint("TOP", 0, texture.style.position[3])
    end
    if texture.style.position[4] then
        rightTexture:SetPoint("BOTTOM", 0, -texture.style.position[4])
    end
    if texture.style.position[1] then
        topTexture:SetPoint("LEFT", -texture.style.position[1] + 1, 0)
    end
    if texture.style.position[2] then
        topTexture:SetPoint("RIGHT", texture.style.position[2] - 1, 0)
    end
    if texture.style.position[3] then
        topTexture:SetPoint("TOP", 0, texture.style.position[3])
    else
        topTexture:SetPoint("BOTTOM", 0, texture.style.height - 1)
    end
    if texture.style.position[1] then
        bottomTexture:SetPoint("LEFT", -texture.style.position[1] + 1, 0)
    end
    if texture.style.position[2] then
        bottomTexture:SetPoint("RIGHT", texture.style.position[2] - 1, 0)
    end
    if texture.style.position[4] then
        bottomTexture:SetPoint("BOTTOM", 0, -texture.style.position[4])
    else
        bottomTexture:SetPoint("TOP", 0, -(texture.style.height + 1) + (texture.style.position[3] + 2))
    end
    -- size
    leftTexture:SetWidth(1)
    if texture.style.height then
        leftTexture:SetHeight(texture.style.height)
    end
    rightTexture:SetWidth(1)
    if texture.style.height then
        rightTexture:SetHeight(texture.style.height)
    end
    topTexture:SetHeight(1)
    if texture.style.width then
        topTexture:SetWidth(texture.style.width - 2)
    end
    bottomTexture:SetHeight(1)
    if texture.style.width then
        bottomTexture:SetWidth(texture.style.width - 2)
    end
    -- texture
    if texture.style.gradient then
        -- set mode
        texture.style.mode = "gradient"
        -- clear any old  settings
        leftTexture:SetTexture() -- clear image
        -- leftTexture:SetAlpha(1) -- reset alpha
        rightTexture:SetTexture() -- clear image
        -- rightTexture:SetAlpha(1) -- reset alpha
        topTexture:SetTexture() -- clear image
        -- topTexture:SetAlpha(1) -- reset alpha
        bottomTexture:SetTexture() -- clear image
        -- bottomTexture:SetAlpha(1) -- reset alpha

        local r1, g1, b1, r2, g2, b2, a1, a2

        if texture.style.gradient.orientation == "HORIZONTAL" then
            -- clear settings
            setGradient(leftTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
            setGradient(rightTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
            topTexture:SetColorTexture(1, 1, 1, 1) -- clear color
            bottomTexture:SetColorTexture(1, 1, 1, 1) -- clear color

            -- aply settings
            r1, g1, b1 = GetBlizzColorValues(texture.style.gradient.color[1])
            r2, g2, b2 = GetBlizzColorValues(texture.style.gradient.color[2])
            a1, a2 = texture.style.alpha[1], texture.style.alpha[2]

            setColor(leftTexture, r1, g1, b1, a1)
            setColor(rightTexture, r2, g2, b2, a2)
            setGradient(topTexture, "HORIZONTAL", r1, g1, b1, a1, r2, g2, b2, a2)
            setGradient(bottomTexture, "HORIZONTAL", r1, g1, b1, a1, r2, g2, b2, a2)
        elseif texture.style.gradient.orientation == "VERTICAL" then
            -- clear settings
            leftTexture:SetColorTexture(1, 1, 1, 1) -- clear color
            rightTexture:SetColorTexture(1, 1, 1, 1) -- clear color
            setGradient(topTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
            setGradient(bottomTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)

            -- aply settings
            r1, g1, b1 = GetBlizzColorValues(texture.style.gradient.color[2])
            r2, g2, b2 = GetBlizzColorValues(texture.style.gradient.color[1])
            a1, a2 = texture.style.alpha[2], texture.style.alpha[1]

            setColor(topTexture, r2, g2, b2, a2)
            setColor(bottomTexture, r1, g1, b1, a1)
            setGradient(leftTexture, "VERTICAL", r1, g1, b1, a1, r2, g2, b2, a2)
            setGradient(rightTexture, "VERTICAL", r1, g1, b1, a1, r2, g2, b2, a2)
        else
            texture.style.mode = "gradient: no orientation!"
            -- should never be here
        end
    elseif texture.style.color then
        -- set mode
        texture.style.mode = "color"
        -- clear any old settings
        setGradient(leftTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
        setGradient(rightTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
        setGradient(topTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
        setGradient(bottomTexture, "HORIZONTAL", 1, 1, 1, 1, 1, 1, 1, 1)
        -- apply settings
        local r, g, b = GetBlizzColorValues(texture.style.color)

        setColor(leftTexture, r, g, b, texture.style.alpha[1])
        setColor(rightTexture, r, g, b, texture.style.alpha[1])
        setColor(topTexture, r, g, b, texture.style.alpha[1])
        setColor(bottomTexture, r, g, b, texture.style.alpha[1])
    else
        -- set mode
        texture.style.mode = "none!"
        -- clear the texture
        leftTexture:SetTexture() -- clear image
        setGradient(leftTexture, "HORIZONTAL", 0, 0, 0, 0, 0, 0, 0, 0) -- clear gradient
        leftTexture:SetColorTexture(0, 0, 0, 0) -- clear color
        rightTexture:SetTexture() -- clear image
        setGradient(rightTexture, "HORIZONTAL", 0, 0, 0, 0, 0, 0, 0, 0) -- clear gradient
        rightTexture:SetColorTexture(0, 0, 0, 0) -- clear color
        topTexture:SetTexture() -- clear image
        setGradient(topTexture, "HORIZONTAL", 0, 0, 0, 0, 0, 0, 0, 0) -- clear gradient
        topTexture:SetColorTexture(0, 0, 0, 0) -- clear color
        bottomTexture:SetTexture() -- clear image
        setGradient(bottomTexture, "HORIZONTAL", 0, 0, 0, 0, 0, 0, 0, 0) -- clear gradient
        bottomTexture:SetColorTexture(0, 0, 0, 0) -- clear color
    end
end

---@class Diesal.Style.ShadowStyle : Diesal.Style.Style
---@field edgeFile? string
---@field edgeSize? number
---@field red? number
---@field green? number
---@field blue? number

---@class Diesal.Style.Shadow : Frame, BackdropTemplate
---@field style Diesal.Style.ShadowStyle

---@class Diesal.Style.ShadowObject : Diesal.GUI.ObjectBase
---@field shadow Diesal.Style.Shadow

---@param object Diesal.Style.ShadowObject
---@param frame Frame
---@param style Diesal.Style.ShadowStyle
function DiesalStyle:StyleShadow(object, frame, style)
    object.shadow = object.shadow or CreateFrame("Frame", nil, frame, BackdropTemplateMixin and "BackdropTemplate") --CreateFrame("Frame",nil,frame)
    object.shadow:Show()
    if not object.shadow.style or style.clear then
        object.shadow.style = {}
    end
    local shadowStyle = object.shadow.style
    -- ~~ Format New Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    local red, green, blue = DiesalTools.GetColor(style.color)
    local offset = style.offset and type(style.offset) == "number" and { style.offset, style.offset, style.offset, style.offset } or style.offset
    -- Setting ~~~~~~~~~~~~~~~~~~~~~~~ New Setting ~~~~~~~~~~~~~~~ Old Setting ~~~~~~~~~~~~~~~~~ Default ~~~~~~~~~~~~~~~~~~
    shadowStyle.edgeFile = style.edgeFile or shadowStyle.edgeFile or getMedia("border", "shadow")
    shadowStyle.edgeSize = style.edgeSize or shadowStyle.edgeSize or 28

    shadowStyle.red = red or shadowStyle.red or 0
    shadowStyle.green = green or shadowStyle.green or 0
    shadowStyle.blue = blue or shadowStyle.blue or 0
    shadowStyle.alpha = style.alpha or shadowStyle.alpha or 0.45

    shadowStyle.offset = offset or shadowStyle.offset or { 20, 20, 20, 20 }
    -- ~~ Apply Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    if shadowStyle.offset[1] then
        object.shadow:SetPoint("LEFT", -shadowStyle.offset[1], 0)
    end
    if shadowStyle.offset[2] then
        object.shadow:SetPoint("RIGHT", shadowStyle.offset[2], 0)
    end
    if shadowStyle.offset[3] then
        object.shadow:SetPoint("TOP", 0, shadowStyle.offset[3])
    end
    if shadowStyle.offset[4] then
        object.shadow:SetPoint("BOTTOM", 0, -shadowStyle.offset[4])
    end

    object.shadow:SetBackdrop({ edgeFile = shadowStyle.edgeFile, edgeSize = shadowStyle.edgeSize })
    object.shadow:SetBackdropBorderColor(shadowStyle.red, shadowStyle.green, shadowStyle.blue, shadowStyle.alpha)
end

--[[ Font style table format
TODO style.offset ( offset|{ Left, Right, Top, Bottom })
TODO style.width ( width )
TODO style.height ( height )

style.font ( Path to a font file )
style.fontSize ( Size (point size) of the font to be displayed (in pixels) )
style.flags ( Additional properties specified by one or more of the following tokens: MONOCHROME, OUTLINE | THICKOUTLINE ) (comma delimitered string)
style.alpha ( alpha )
style.color ( hexColor|{ Red, Green, Blue } [0-255])
style.lineSpacing ( number - Sets the font instance's amount of spacing between lines)
]]

---@class Diesal.Style.FontStyle
---@field font string
---@field filename string
---@field fontSize number
---@field flags string
---@field alpha number
---@field color Diesal.Style.Color
---@field lineSpacing number
---@field red number
---@field green number
---@field blue number

---@class Diesal.Style.FontString : FontString
---@field style Diesal.Style.FontStyle

---@param fontInstance Diesal.Style.FontString
---@param name string
---@param style Diesal.Style.FontStyle
function DiesalStyle:StyleFont(fontInstance, name, style)
    local filename, fontSize, flags = fontInstance:GetFont()
    local red, green, blue, alpha = fontInstance:GetTextColor()
    local lineSpacing = fontInstance:GetSpacing()
    -- Fallback to DiesalFontNormal for Patch 8.1
    if not filename then
        filename, fontSize, flags = DiesalFontNormal:GetFont()
        red, green, blue, alpha = DiesalFontNormal:GetTextColor()
        lineSpacing = DiesalFontNormal:GetSpacing()
    end
    ---@diagnostic disable-next-line: assign-type-mismatch
    style.red, style.green, style.blue = DiesalTools.GetColor(style.color)
    -- ~~ Set Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    style.filename = style.filename or filename
    style.fontSize = style.fontSize or fontSize
    style.flags = style.flags or flags

    style.red = style.red or red
    style.green = style.green or green
    style.blue = style.blue or blue
    style.alpha = style.alpha or alpha
    style.lineSpacing = style.lineSpacing or lineSpacing
    -- ~~ Apply Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    fontInstance:SetFont(style.filename, style.fontSize, style.flags)
    fontInstance:SetTextColor(style.red, style.green, style.blue, style.alpha)
    fontInstance:SetSpacing(style.lineSpacing)

    fontInstance.style = style
end

---@param object Diesal.GUI.ObjectBase
---@param name string
---@param style Diesal.Style.Style
function DiesalStyle:UpdateObjectStyle(object, name, style)
    if not style or type(style) ~= "table" then
        return
    end
    if type(name) ~= "string" then
        return
    end
    -- ~~ Clear Texture ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if style.clear then
        -- clear texture
        if object.textures[name] then
            DiesalStyle:ReleaseTexture(object, name)
        end
        -- clear OUTLINE
        for i = 1, #OUTLINES do
            if object.textures[name .. OUTLINES[i]] then
                DiesalStyle:ReleaseTexture(object, name .. OUTLINES[i])
            end
        end
    end
    -- add texture name to style for better debugging
    style.name = name
    -- ~~ Get styleType ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if not style.type then
        return
    end
    local styleType = DiesalTools.Capitalize(style.type)
    if not DiesalStyle["Style" .. styleType] then
        geterrorhandler()(style.type .. " is not a valid style type")
        return
    end
    -- ~~ Get Frame ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    local framename = name:match("^[ \t]*([%w%d%_]*)")
    local frame = object[framename]
    if not frame then
        return
    end
    -- ~~ Style ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if styleType == "Texture" then
        local texture = object.textures[name]
        if not texture then
            texture = newTexture()
            object.textures[name] = texture
        end
        texture:SetParent(frame)
        DiesalStyle:StyleTexture(texture, style)
        return
    end
    if styleType == "Outline" then
        local textures = {}
        for i = 1, #OUTLINES do
            local texture = object.textures[name .. OUTLINES[i]]
            if not texture then
                texture = newTexture()
                object.textures[name .. OUTLINES[i]] = texture
            end
            texture:SetParent(frame)
            textures[i] = texture
        end
        DiesalStyle:StyleOutline(textures[1], textures[2], textures[3], textures[4], style)
        return
    end
    if styleType == "Shadow" then
        DiesalStyle:StyleShadow(
            ---@cast object Diesal.Style.ShadowObject
            object,
            frame,
            style --[[ @as Diesal.Style.ShadowStyle ]]
        )
        return
    end
    if styleType == "Font" then
        DiesalStyle:StyleFont(frame, name, style --[[ @as Diesal.Style.FontStyle ]])
    end
end

---@param object Diesal.GUI.ObjectBase
---@param name string
---@param style Diesal.Style.Style
function DiesalStyle:SetObjectStyle(object, name, style)
    if not style or type(style) ~= "table" then
        return
    end
    if type(name) ~= "string" then
        return
    end
    -- clear texture
    if object.textures[name] then
        DiesalStyle:ReleaseTexture(object, name)
    end
    -- clear OUTLINE
    for i = 1, #OUTLINES do
        if object.textures[name .. OUTLINES[i]] then
            DiesalStyle:ReleaseTexture(object, name .. OUTLINES[i])
        end
    end
    -- Set object style
    DiesalStyle:UpdateObjectStyle(object, name, style)
end

---@param object Diesal.GUI.ObjectBase
---@param Stylesheet Diesal.Style.Stylesheet
function DiesalStyle:UpdateObjectStylesheet(object, Stylesheet)
    if not Stylesheet or type(Stylesheet) ~= "table" then
        return
    end
    if not object.textures then
        object.textures = {}
    end

    for name, style in pairs(Stylesheet) do
        self:UpdateObjectStyle(object, name, style)
    end
end

---@param object Diesal.GUI.ObjectBase
---@param Stylesheet Diesal.Style.Stylesheet
function DiesalStyle:SetObjectStylesheet(object, Stylesheet)
    if not object.textures then
        object.textures = {}
    end

    DiesalStyle:ReleaseTextures(object)

    for name, style in pairs(Stylesheet) do
        self:UpdateObjectStyle(object, name, style)
    end
end

---@param object Diesal.GUI.ObjectBase
---@param name string
function DiesalStyle:ReleaseTexture(object, name)
    if not object or not object.textures or not object.textures[name] then
        error("No such texture on ojbect", 2)
        return
    end
    releaseTexture(object.textures[name])
    object.textures[name] = nil
end

---@param object Diesal.GUI.ObjectBase
function DiesalStyle:ReleaseTextures(object)
    for name, texture in pairs(object.textures) do
        releaseTexture(texture)
        object.textures[name] = nil
    end
end

---@param mediaType string
---@param name string
function DiesalStyle:GetMedia(mediaType, name)
    return getMedia(mediaType, name)
end

---@param mediaType string
---@param name string
---@param mediaFile string
function DiesalStyle:AddMedia(mediaType, name, mediaFile)
    addMedia(mediaType, name, mediaFile)
end
