local addonTable = select(2, ...)
local core = addonTable

core.MeetingStoneButtonArt = core.MeetingStoneButtonArt or {}
local ButtonArt = core.MeetingStoneButtonArt

local BUTTON_ART_PATH = "Interface\\AddOns\\MythicKeystoneAssistant\\Art\\Buttons\\RedStyle\\"
local BUTTON_ART_INSETS = { left = 9, right = 9, top = 8, bottom = 7 }
local BUTTON_TEXT_COLOR = { 1, 0.82, 0, 1 }
local BUTTON_DISABLED_TEXT_COLOR = { 0.5, 0.5, 0.5, 1 }
local BUTTON_ART_PIECES = {
    "top-left", "top", "top-right",
    "left", "center", "right",
    "bottom-left", "bottom", "bottom-right",
}

local function HideRegion(region)
    if not region or not region.Hide then
        return
    end

    region:Hide()
    if region.SetAlpha then
        region:SetAlpha(0)
    end
end

local function HideChrome(button)
    if not button then
        return
    end

    local fontString = button.Text or (button.GetFontString and button:GetFontString())
    if button.GetRegions then
        for _, region in ipairs({ button:GetRegions() }) do
            if region ~= fontString and region.GetObjectType and region:GetObjectType() == "Texture" then
                HideRegion(region)
            end
        end
    end

    if button.GetNormalTexture then HideRegion(button:GetNormalTexture()) end
    if button.GetPushedTexture then HideRegion(button:GetPushedTexture()) end
    if button.GetDisabledTexture then HideRegion(button:GetDisabledTexture()) end
    if button.GetHighlightTexture then HideRegion(button:GetHighlightTexture()) end

    HideRegion(button.NineSlice)
    HideRegion(button.Left)
    HideRegion(button.Middle)
    HideRegion(button.Right)
    HideRegion(button.LeftTexture)
    HideRegion(button.MiddleTexture)
    HideRegion(button.RightTexture)
end

local function GetFile(state, piece)
    return BUTTON_ART_PATH .. "button-" .. state .. "-" .. piece .. ".png"
end

local function AnchorSlice(texture, button, piece)
    local insets = BUTTON_ART_INSETS
    if piece == "top-left" then
        texture:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
        texture:SetSize(insets.left, insets.top)
    elseif piece == "top" then
        texture:SetPoint("TOPLEFT", button, "TOPLEFT", insets.left, 0)
        texture:SetPoint("TOPRIGHT", button, "TOPRIGHT", -insets.right, 0)
        texture:SetHeight(insets.top)
    elseif piece == "top-right" then
        texture:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0)
        texture:SetSize(insets.right, insets.top)
    elseif piece == "left" then
        texture:SetPoint("TOPLEFT", button, "TOPLEFT", 0, -insets.top)
        texture:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 0, insets.bottom)
        texture:SetWidth(insets.left)
    elseif piece == "center" then
        texture:SetPoint("TOPLEFT", button, "TOPLEFT", insets.left, -insets.top)
        texture:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -insets.right, insets.bottom)
    elseif piece == "right" then
        texture:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, -insets.top)
        texture:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, insets.bottom)
        texture:SetWidth(insets.right)
    elseif piece == "bottom-left" then
        texture:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 0, 0)
        texture:SetSize(insets.left, insets.bottom)
    elseif piece == "bottom" then
        texture:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", insets.left, 0)
        texture:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -insets.right, 0)
        texture:SetHeight(insets.bottom)
    elseif piece == "bottom-right" then
        texture:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, 0)
        texture:SetSize(insets.right, insets.bottom)
    end
end

local function SetArtState(button, state, enabled)
    local art = button and button.mkaMeetingStoneButtonArt
    if not art then
        return
    end

    if art.state ~= state then
        for _, texture in ipairs(art.textures) do
            texture:SetTexture(GetFile(state, texture.mkaMeetingStoneButtonPiece))
            texture:Show()
        end
        art.state = state
    end

    local dim = enabled and 1 or 0.5
    local alpha = enabled and 1 or 0.65
    for _, texture in ipairs(art.textures) do
        texture:SetVertexColor(dim, dim, dim, alpha)
    end
end

function ButtonArt.Update(button)
    if not button or not button.mkaMeetingStoneButtonArt then
        return
    end

    local enabled = not (button.IsEnabled and not button:IsEnabled())
    local pressed = enabled and button.mkaMeetingStoneButtonPressed == true
    local hovered = enabled and button.IsMouseOver and button:IsMouseOver()
    local state = pressed and "pressed" or (hovered and "hover" or "default")
    SetArtState(button, state, enabled)

    local fontString = button.Text or (button.GetFontString and button:GetFontString())
    if fontString and fontString.SetTextColor then
        local color = enabled and BUTTON_TEXT_COLOR or BUTTON_DISABLED_TEXT_COLOR
        fontString:SetTextColor(color[1], color[2], color[3], color[4])
    end
end

function ButtonArt.Apply(button)
    if not button or button.mkaMeetingStoneButtonArtApplied then
        return
    end

    HideChrome(button)
    local textures = {}
    for _, piece in ipairs(BUTTON_ART_PIECES) do
        local texture = button:CreateTexture(nil, "BACKGROUND")
        texture.mkaMeetingStoneButtonPiece = piece
        texture:SetTexCoord(0, 1, 0, 1)
        AnchorSlice(texture, button, piece)
        textures[#textures + 1] = texture
    end

    button.mkaMeetingStoneButtonArt = { textures = textures }
    button.mkaMeetingStoneButtonArtApplied = true
    button:HookScript("OnEnter", ButtonArt.Update)
    button:HookScript("OnLeave", function(self)
        self.mkaMeetingStoneButtonPressed = nil
        ButtonArt.Update(self)
    end)
    button:HookScript("OnMouseDown", function(self, mouseButton)
        if mouseButton == "LeftButton" then
            self.mkaMeetingStoneButtonPressed = true
            ButtonArt.Update(self)
        end
    end)
    button:HookScript("OnMouseUp", function(self)
        self.mkaMeetingStoneButtonPressed = nil
        ButtonArt.Update(self)
    end)
    button:HookScript("OnEnable", ButtonArt.Update)
    button:HookScript("OnDisable", ButtonArt.Update)
    button:HookScript("OnShow", ButtonArt.Update)

    ButtonArt.Update(button)
end
