--[[
    SuaviLura - Lu'Ra Memory Helper
    Cloned from LuraHelper — Snazzy design system
]]

local ADDON_NAME = ...
local PREFIX = "LURAHELP"

-------------------------------------------------
-- Snazzy Color Palette (from SuaviUI)
-------------------------------------------------

local C = {
    bg          = {0.157, 0.165, 0.212, 0.97},
    bgLight     = {0.188, 0.196, 0.247, 1},
    bgDark      = {0.133, 0.141, 0.188, 1},
    accent      = {1.0, 0.416, 0.757, 1},
    accentDark  = {0.878, 0.322, 0.659, 1},
    text        = {0.937, 0.941, 0.922, 1},
    textMuted   = {0.502, 0.502, 0.518, 1},
    border      = {0.220, 0.227, 0.275, 1},
    borderLight = {0.290, 0.298, 0.345, 1},
    success     = {0.353, 0.969, 0.557, 1},
    error       = {1.0, 0.361, 0.341, 1},
    cyan        = {0.604, 0.929, 0.996, 1},
    sliderTrack = {0.188, 0.196, 0.247, 1},
    sliderThumb = {0.937, 0.941, 0.922, 1},
}

local BACKDROP = {
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    edgeSize = 12,
    insets = { left = 3, right = 3, top = 3, bottom = 3 },
}

local CIRCLE_TEX = "Interface\\CHARACTERFRAME\\TempPortraitAlphaMask"

-------------------------------------------------
-- Utility
-------------------------------------------------

local function Print(msg)
    DEFAULT_CHAT_FRAME:AddMessage("|cffFF6AC1SuaviLura:|r " .. tostring(msg))
end

local MAX_SEND_RETRIES = 8
local RETRY_INTERVAL = 0.35

local function SendReliable(prefix, message, channel, retries)
    retries = retries or 0
    if C_ChatInfo.InChatMessagingLockdown() then
        if retries < MAX_SEND_RETRIES then
            C_Timer.After(RETRY_INTERVAL, function()
                SendReliable(prefix, message, channel, retries + 1)
            end)
        end
        return
    end
    local result = C_ChatInfo.SendAddonMessage(prefix, message, channel)
    if result ~= Enum.SendAddonMessageResult.Success then
        if retries < MAX_SEND_RETRIES then
            C_Timer.After(RETRY_INTERVAL, function()
                SendReliable(prefix, message, channel, retries + 1)
            end)
        else
            Print("Failed to send message (throttled).")
        end
    end
end

local function SerializeSequence(seq)
    return table.concat(seq, ",")
end

local function DeserializeSequence(str)
    local t = {}
    for token in string.gmatch(str or "", "([^,]+)") do
        table.insert(t, token)
    end
    return t
end

local function CreateStyledButton(parent, text, onClick)
    local btn = CreateFrame("Button", nil, parent, "BackdropTemplate")
    btn:SetBackdrop(BACKDROP)
    btn:SetBackdropColor(C.bgLight[1], C.bgLight[2], C.bgLight[3], 1)
    btn:SetBackdropBorderColor(C.border[1], C.border[2], C.border[3], 1)

    local label = btn:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    label:SetPoint("CENTER")
    label:SetTextColor(C.text[1], C.text[2], C.text[3], 1)
    label:SetText(text)
    btn.text = label

    btn:SetScript("OnEnter", function(self)
        self:SetBackdropBorderColor(C.accent[1], C.accent[2], C.accent[3], 1)
    end)
    btn:SetScript("OnLeave", function(self)
        self:SetBackdropBorderColor(C.border[1], C.border[2], C.border[3], 1)
    end)

    if onClick then btn:SetScript("OnClick", onClick) end
    return btn
end

-------------------------------------------------
-- State
-------------------------------------------------

local SuaviLura = {}
SuaviLura.sequence = {}
SuaviLura.isPlaying = false
SuaviLura.buttons = {}
SuaviLura.buttonOrder = {}
SuaviLura.displayIcons = {}
SuaviLura.playHighlightDuration = 0.4
SuaviLura.playStepDelay = 0.6
SuaviLura.iconSize = 80

-------------------------------------------------
-- Texture paths
-------------------------------------------------

local ICONS = {
    TRI = "Interface\\AddOns\\SuaviLura\\media\\triangle.tga",
    TEE = "Interface\\AddOns\\SuaviLura\\media\\t.tga",
    DIA = "Interface\\AddOns\\SuaviLura\\media\\diamond.tga",
    X   = "Interface\\AddOns\\SuaviLura\\media\\x.tga",
    CIR = "Interface\\AddOns\\SuaviLura\\media\\circle.tga",
}

-------------------------------------------------
-- Events
-------------------------------------------------

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:RegisterEvent("PLAYER_LOGIN")
eventFrame:RegisterEvent("CHAT_MSG_ADDON")

C_ChatInfo.RegisterAddonMessagePrefix(PREFIX)

eventFrame:SetScript("OnEvent", function(self, event, ...)
    if event == "ADDON_LOADED" then
        local addon = ...
        if addon == ADDON_NAME then
            Print("Loaded.")
        end

    elseif event == "PLAYER_LOGIN" then

        SLASH_SUAVILURA1 = "/slura"
        SLASH_SUAVILURA2 = "/sl"
        SlashCmdList["SUAVILURA"] = function()
            if SuaviLura.mainFrame:IsShown() then
                SuaviLura.mainFrame:Hide()
            else
                SuaviLura.mainFrame:Show()
                SuaviLura:UpdateSendState()
            end
        end

    elseif event == "CHAT_MSG_ADDON" then
        local prefix, message, channel, sender = ...
        if prefix == PREFIX then
            SuaviLura:OnSequenceReceived(message, sender)
        end
    end
end)

-------------------------------------------------
-- UI: Main Frame
-------------------------------------------------

local function CreateMainFrame()
    local f = CreateFrame("Frame", "SuaviLuraMainFrame", UIParent, "BackdropTemplate")
    f:SetSize(280, 165)
    f:SetPoint("CENTER")
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)

    f:SetBackdrop(BACKDROP)
    f:SetBackdropColor(C.bg[1], C.bg[2], C.bg[3], C.bg[4])
    f:SetBackdropBorderColor(C.border[1], C.border[2], C.border[3], 1)

    -- Header bar
    local header = CreateFrame("Frame", nil, f, "BackdropTemplate")
    header:SetHeight(30)
    header:SetPoint("TOPLEFT", 4, -4)
    header:SetPoint("TOPRIGHT", -4, -4)
    header:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8",
    })
    header:SetBackdropColor(C.bgDark[1], C.bgDark[2], C.bgDark[3], 1)

    local title = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    title:SetPoint("LEFT", 10, 0)
    title:SetTextColor(C.cyan[1], C.cyan[2], C.cyan[3], 1)
    title:SetText("SuaviLura")

    SuaviLura.header = header
    SuaviLura.mainFrame = f
end

-------------------------------------------------
-- UI: Shape Buttons
-------------------------------------------------

local BUTTON_LAYOUT = {
    { row = 1, col = 1 },
    { row = 1, col = 2 },
    { row = 1, col = 3 },
    { row = 2, col = 1 },
    { row = 2, col = 2 },
}

local FRAME_PADDING = 20

local function RefreshButtonLayout()
    local size = SuaviLura.iconSize
    local gap = size * 0.25
    local stride = size + gap
    local f = SuaviLura.mainFrame

    -- Capture current top-center before resizing
    local topX = f:GetLeft() + f:GetWidth() / 2
    local topY = f:GetTop()

    -- Frame width based on row 1 (widest: 3 icons)
    local row1Width = 3 * size + 2 * gap
    local frameW = row1Width + FRAME_PADDING * 2
    f:SetWidth(frameW)

    for i, btn in ipairs(SuaviLura.buttonOrder) do
        local layout = BUTTON_LAYOUT[i]
        local cols = layout.row == 1 and 3 or 2
        local rowWidth = cols * size + (cols - 1) * gap
        local startX = (frameW - rowWidth) / 2
        local headerH = 38
        local y = layout.row == 1 and -headerH or (-headerH - stride)

        btn:ClearAllPoints()
        btn:SetSize(size, size)
        btn:SetPoint("TOPLEFT", startX + (layout.col - 1) * stride, y)
    end

    -- Frame height
    local headerH = 38
    local row2Bottom = headerH + stride + size
    local controlHeight = 52
    local totalH = row2Bottom + controlHeight + 10
    f:SetHeight(totalH)

    -- Re-anchor from top-center so drag bar stays put
    if topX and topY then
        f:ClearAllPoints()
        f:SetPoint("TOP", UIParent, "BOTTOMLEFT", topX, topY)
    end

    -- Resize control buttons to 50% each
    local inset = 8
    local halfWidth = (frameW - inset * 2) / 2
    if SuaviLura.sendBtn then
        SuaviLura.sendBtn:SetSize(halfWidth, 44)
        SuaviLura.clearBtn:SetSize(halfWidth, 44)
    end
end

local function CreateShapeButton(parent, id, texturePath, index)
    local size = SuaviLura.iconSize
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(size, size)

    local tex = btn:CreateTexture(nil, "ARTWORK")
    tex:SetAllPoints()
    tex:SetTexture(texturePath)

    btn.shapeID = id

    btn:SetScript("OnClick", function(self)
        if SuaviLura.isPlaying then return end
        local id = self.shapeID
        -- Check if already selected — if so, unselect
        for i, seqId in ipairs(SuaviLura.sequence) do
            if seqId == id then
                table.remove(SuaviLura.sequence, i)
                SuaviLura:EnableButton(id)
                SuaviLura:ShowSequenceVisual(SuaviLura.sequence)
                return
            end
        end
        table.insert(SuaviLura.sequence, id)
        SuaviLura:DisableButton(id)
        SuaviLura:ShowSequenceVisual(SuaviLura.sequence)
    end)

    local hl = btn:CreateTexture(nil, "OVERLAY")
    hl:SetAllPoints()
    hl:SetColorTexture(C.accent[1], C.accent[2], C.accent[3], 0.3)
    hl:Hide()
    btn.highlight = hl

    SuaviLura.buttons[id] = btn
    table.insert(SuaviLura.buttonOrder, btn)
    return btn
end

function SuaviLura:DisableButton(id)
    local btn = self.buttons[id]
    if not btn then return end
    btn:SetAlpha(0.35)
end

function SuaviLura:EnableButton(id)
    local btn = self.buttons[id]
    if not btn then return end
    btn:SetAlpha(1)
end

function SuaviLura:ResetAllButtons()
    for _, btn in pairs(self.buttons) do
        btn:SetAlpha(1)
    end
end

function SuaviLura:CanSendToRaid()
    return not IsInRaid() or UnitIsGroupLeader("player") or UnitIsGroupAssistant("player")
end

function SuaviLura:UpdateSendState()
    local canSend = self:CanSendToRaid()
    if canSend then
        self.sendBtn:SetAlpha(1)
        self.sendBtn:EnableMouse(true)
    else
        self.sendBtn:SetAlpha(0.4)
        self.sendBtn:EnableMouse(false)
    end
end

-------------------------------------------------
-- UI: Icon Size Slider (Snazzy styled)
-------------------------------------------------

local function CreateIconSizeSlider()
    local header = SuaviLura.header

    -- Track background
    local track = CreateFrame("Frame", nil, header, "BackdropTemplate")
    track:SetHeight(6)
    track:SetPoint("LEFT", header, "CENTER", 0, 0)
    track:SetPoint("RIGHT", -12, 0)
    track:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })
    track:SetBackdropColor(C.sliderTrack[1], C.sliderTrack[2], C.sliderTrack[3], 1)
    track:SetBackdropBorderColor(C.border[1], C.border[2], C.border[3], 1)

    -- Accent fill (left portion of track)
    local fill = track:CreateTexture(nil, "ARTWORK")
    fill:SetHeight(4)
    fill:SetPoint("LEFT", 1, 0)
    fill:SetColorTexture(C.accent[1], C.accent[2], C.accent[3], 1)

    -- Visible circle thumb
    local thumbFrame = CreateFrame("Frame", nil, header)
    thumbFrame:SetSize(14, 14)
    thumbFrame:SetFrameLevel(track:GetFrameLevel() + 2)
    local thumbCircle = thumbFrame:CreateTexture(nil, "ARTWORK")
    thumbCircle:SetAllPoints()
    thumbCircle:SetTexture(CIRCLE_TEX)
    thumbCircle:SetVertexColor(C.sliderThumb[1], C.sliderThumb[2], C.sliderThumb[3], 1)

    -- Hidden native slider for drag mechanics
    local slider = CreateFrame("Slider", "SuaviLuraIconSlider", header)
    slider:SetOrientation("HORIZONTAL")
    slider:SetPoint("LEFT", track, "LEFT", 0, 0)
    slider:SetPoint("RIGHT", track, "RIGHT", 0, 0)
    slider:SetHeight(16)
    slider:SetMinMaxValues(30, 120)
    slider:SetValueStep(5)
    slider:SetObeyStepOnDrag(true)
    slider:SetValue(SuaviLura.iconSize)

    -- Hidden thumb for native slider mechanics
    slider:SetThumbTexture("Interface\\Buttons\\WHITE8x8")
    local nativeThumb = slider:GetThumbTexture()
    nativeThumb:SetSize(14, 14)
    nativeThumb:SetAlpha(0)

    local function UpdateThumbPosition(value)
        local trackWidth = track:GetWidth()
        if trackWidth < 1 then return end
        local pct = (value - 30) / (120 - 30)
        pct = math.max(0, math.min(1, pct))
        local thumbX = pct * (trackWidth - 14) + 7
        thumbFrame:ClearAllPoints()
        thumbFrame:SetPoint("CENTER", track, "LEFT", thumbX, 0)
        fill:SetWidth(math.max(1, thumbX))
    end

    local isDragging = false

    slider:SetScript("OnValueChanged", function(self, value)
        value = math.floor(value + 0.5)
        UpdateThumbPosition(value)
    end)

    slider:SetScript("OnMouseDown", function()
        isDragging = true
    end)

    slider:SetScript("OnMouseUp", function(self)
        isDragging = false
        local value = math.floor(self:GetValue() + 0.5)
        SuaviLura.iconSize = value
        RefreshButtonLayout()
        -- Reposition thumb after track width has settled
        C_Timer.After(0, function() UpdateThumbPosition(value) end)
    end)

    slider:SetScript("OnEnter", function()
        thumbCircle:SetVertexColor(C.accent[1], C.accent[2], C.accent[3], 1)
    end)
    slider:SetScript("OnLeave", function()
        thumbCircle:SetVertexColor(C.sliderThumb[1], C.sliderThumb[2], C.sliderThumb[3], 1)
    end)

    -- Initial position after track has geometry
    C_Timer.After(0, function() UpdateThumbPosition(SuaviLura.iconSize) end)
end

-------------------------------------------------
-- UI: Control Buttons
-------------------------------------------------

local function CreateControlButtons(parent)
    local sendBtn = CreateStyledButton(parent, "Send", function()
        if SuaviLura.isPlaying then return end
        if not SuaviLura:CanSendToRaid() then return end
        if #SuaviLura.sequence == 0 then
            Print("No sequence to send.")
            return
        end
        local msg = SerializeSequence(SuaviLura.sequence)
        SendReliable(PREFIX, msg, "RAID")
        Print("Sequence sent to raid.")
        -- Flash accent state
        SuaviLura.sendBtn:SetBackdropColor(C.accent[1], C.accent[2], C.accent[3], 0.4)
        SuaviLura.sendBtn.text:SetTextColor(C.accent[1], C.accent[2], C.accent[3], 1)
        C_Timer.After(0.8, function()
            SuaviLura.sendBtn:SetBackdropColor(C.bgLight[1], C.bgLight[2], C.bgLight[3], 1)
            SuaviLura.sendBtn.text:SetTextColor(C.text[1], C.text[2], C.text[3], 1)
        end)
    end)
    sendBtn:SetSize(100, 44)
    sendBtn:SetPoint("BOTTOMLEFT", 8, 8)

    local clearBtn = CreateStyledButton(parent, "Clear", function()
        if SuaviLura.isPlaying then return end
        wipe(SuaviLura.sequence)
        SuaviLura:ResetAllButtons()
        SuaviLura:ShowSequenceVisual(SuaviLura.sequence)
        if SuaviLura:CanSendToRaid() then
            SendReliable(PREFIX, "CLEAR", "RAID")
        end
    end)
    clearBtn:SetSize(100, 44)
    clearBtn:SetPoint("BOTTOMRIGHT", -8, 8)

    SuaviLura.sendBtn = sendBtn
    SuaviLura.clearBtn = clearBtn
end

-------------------------------------------------
-- UI: Circular Display Frame
-------------------------------------------------

local function CreateDisplayFrame()
    local f = CreateFrame("Frame", "SuaviLuraDisplayFrame", UIParent, "BackdropTemplate")
    f:SetSize(200, 200)
    f:SetPoint("CENTER", 0, 150)
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)

    f:SetClipsChildren(false)

    -- Circular background
    local bgCircle = f:CreateTexture(nil, "BACKGROUND")
    bgCircle:SetPoint("TOPLEFT", -6, 6)
    bgCircle:SetPoint("BOTTOMRIGHT", 6, -6)
    bgCircle:SetTexture(CIRCLE_TEX)
    bgCircle:SetVertexColor(C.bg[1], C.bg[2], C.bg[3], 0.85)

    SuaviLura.displayFrame = f
end

-------------------------------------------------
-- Sequence Visuals
-------------------------------------------------

function SuaviLura:ShowSequenceVisual(seq)
    if not self.displayFrame then return end

    for _, obj in ipairs(self.displayIcons) do
        obj:Hide()
    end
    wipe(self.displayIcons)

    -- Shield Icon
    local shield = self.displayFrame:CreateTexture(nil, "OVERLAY")
    shield:SetSize(24, 24)
    shield:SetDrawLayer("OVERLAY", 7)
    shield:SetPoint("CENTER", 0, 52)
    shield:SetTexture("Interface\\Icons\\INV_Shield_04")
    table.insert(self.displayIcons, shield)

    -- BOSS Text
    local bossText = self.displayFrame:CreateFontString(nil, "OVERLAY")
    bossText:SetFont("Fonts\\FRIZQT__.TTF", 19, "OUTLINE")
    bossText:SetDrawLayer("OVERLAY", 7)
    bossText:SetPoint("CENTER", 0, 0)
    bossText:SetTextColor(C.error[1], C.error[2], C.error[3], 1)
    bossText:SetText("BOSS")
    table.insert(self.displayIcons, bossText)

    if #seq == 0 then
        self.displayFrame:Hide()
        return
    end

    local positions = {
        { angle = 30 },
        { angle = 330 },
        { angle = 270 },
        { angle = 210 },
        { angle = 150 },
    }

    local radius = 70
    local numberRadius = 90

    for i, id in ipairs(seq) do
        local pos = positions[i]
        if not pos then break end

        local rad = math.rad(pos.angle)
        local x = radius * math.cos(rad)
        local y = radius * math.sin(rad)

        local tex = self.displayFrame:CreateTexture(nil, "ARTWORK")
        tex:SetSize(40, 40)
        tex:SetPoint("CENTER", x, y)
        tex:SetTexture(ICONS[id])
        table.insert(self.displayIcons, tex)

        local nx = numberRadius * math.cos(rad)
        local ny = numberRadius * math.sin(rad)

        local num = self.displayFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
        num:SetPoint("CENTER", nx, ny)
        num:SetTextColor(C.accent[1], C.accent[2], C.accent[3], 1)
        num:SetText(i)
        table.insert(self.displayIcons, num)
    end

    self.displayFrame:Show()
end

-------------------------------------------------
-- Playback
-------------------------------------------------

function SuaviLura:HighlightButtonOnce(id, delay)
    local btn = self.buttons[id]
    if not btn then return end

    C_Timer.After(delay, function()
        btn.highlight:Show()
        C_Timer.After(self.playHighlightDuration, function()
            btn.highlight:Hide()
        end)
    end)
end

function SuaviLura:PlaySequence(seq)
    if self.isPlaying then return end
    self.isPlaying = true

    local totalTime = 0
    for i, id in ipairs(seq) do
        local delay = (i - 1) * self.playStepDelay
        self:HighlightButtonOnce(id, delay)
        totalTime = delay
    end

    C_Timer.After(totalTime + self.playHighlightDuration + 0.1, function()
        self.isPlaying = false
    end)
end

-------------------------------------------------
-- Receiving
-------------------------------------------------

function SuaviLura:OnSequenceReceived(message, sender)
    if message == "CLEAR" then
        wipe(self.sequence)
        self:ResetAllButtons()
        self:ShowSequenceVisual(self.sequence)
        return
    end

    local seq = DeserializeSequence(message)
    if #seq == 0 then return end

    wipe(self.sequence)
    for _, id in ipairs(seq) do
        table.insert(self.sequence, id)
    end

    self:ShowSequenceVisual(self.sequence)
    self:PlaySequence(self.sequence)
end

-------------------------------------------------
-- Init
-------------------------------------------------

CreateMainFrame()

CreateShapeButton(SuaviLura.mainFrame, "TRI", ICONS.TRI, 1)
CreateShapeButton(SuaviLura.mainFrame, "TEE", ICONS.TEE, 2)
CreateShapeButton(SuaviLura.mainFrame, "DIA", ICONS.DIA, 3)
CreateShapeButton(SuaviLura.mainFrame, "X",   ICONS.X,   4)
CreateShapeButton(SuaviLura.mainFrame, "CIR", ICONS.CIR, 5)

CreateIconSizeSlider()
CreateControlButtons(SuaviLura.mainFrame)
RefreshButtonLayout()
SuaviLura.mainFrame:Hide()

CreateDisplayFrame()
SuaviLura.displayFrame:Hide()
