local addonName = ...

local ARM = CreateFrame("Frame")
local ICON_TEXTURE = "Interface\\TargetingFrame\\UI-RaidTargetingIcons"
local ICON_COORDS = {
    { 0.00, 0.25, 0.00, 0.25 }, -- star
    { 0.25, 0.50, 0.00, 0.25 }, -- circle
    { 0.50, 0.75, 0.00, 0.25 }, -- diamond
    { 0.75, 1.00, 0.00, 0.25 }, -- triangle
    { 0.00, 0.25, 0.25, 0.50 }, -- moon
    { 0.25, 0.50, 0.25, 0.50 }, -- square
    { 0.50, 0.75, 0.25, 0.50 }, -- cross
    { 0.75, 1.00, 0.25, 0.50 }, -- skull
}

local DEFAULTS = {
    point = "CENTER",
    relativePoint = "CENTER",
    x = 0,
    y = 180,
    locked = false,
    visible = true,
    maxIcons = 8,
}

local function Print(message)
    DEFAULT_CHAT_FRAME:AddMessage("|cff00d8ffAzta'rec Memory:|r " .. message)
end

local function CopyDefaults(source, target)
    for key, value in pairs(source) do
        if target[key] == nil then target[key] = value end
    end
end

local function CreateDisplay()
    local frame = CreateFrame("Frame", "AztaRecMemoryDisplay", UIParent, "BackdropTemplate")
    frame:SetSize(350, 54)
    frame:SetClampedToScreen(true)
    frame:SetMovable(true)
    frame:EnableMouse(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8X8",
        edgeFile = "Interface\\Buttons\\WHITE8X8",
        edgeSize = 1,
    })
    frame:SetBackdropColor(0.025, 0.035, 0.055, 0.92)
    frame:SetBackdropBorderColor(0.15, 0.75, 1, 0.9)

    frame.icons = {}
    for index = 1, 8 do
        local texture = frame:CreateTexture(nil, "ARTWORK")
        texture:SetSize(38, 38)
        texture:SetPoint("LEFT", 7 + (index - 1) * 43, 0)
        texture:SetTexture(ICON_TEXTURE)
        texture:Hide()
        frame.icons[index] = texture
    end

    frame:SetScript("OnDragStart", function(self)
        if not AztaRecMemoryDB.locked then self:StartMoving() end
    end)
    frame:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
        local point, _, relativePoint, x, y = self:GetPoint(1)
        AztaRecMemoryDB.point = point
        AztaRecMemoryDB.relativePoint = relativePoint
        AztaRecMemoryDB.x = x
        AztaRecMemoryDB.y = y
    end)

    ARM.display = frame
end

local function Render()
    for index = 1, 8 do
        local texture = ARM.display.icons[index]
        local marker = tonumber(AztaRecMemoryDB.sequence[index])
        if marker and ICON_COORDS[marker] then
            texture:SetTexCoord(unpack(ICON_COORDS[marker]))
            texture:Show()
        else
            texture:Hide()
        end
    end
end

local markerNames = {
    star = 1, circle = 2, diamond = 3, triangle = 4,
    moon = 5, square = 6, cross = 7, skull = 8,
}

local function ParseMarker(text)
    text = strtrim((text or ""):lower())
    local number = text:match("^%d$") or text:match("^rt(%d)$") or text:match("^{rt(%d)}$")
    number = tonumber(number)
    if number and number >= 1 and number <= 8 then return number end
    text = text:gsub("[{}]", "")
    return markerNames[text]
end

local function AddMarker(marker)
    if #AztaRecMemoryDB.sequence >= AztaRecMemoryDB.maxIcons then
        Print("The sequence is full. Use /aztarec clear to empty it.")
        return
    end
    AztaRecMemoryDB.sequence[#AztaRecMemoryDB.sequence + 1] = marker
    AztaRecMemoryDB.visible = true
    ARM.display:Show()
    Render()
end

local macroDefinitions = {
    { "Azta Star",     "Interface\\TargetingFrame\\UI-RaidTargetingIcon_1", "/aztarec 1" },
    { "Azta Circle",   "Interface\\TargetingFrame\\UI-RaidTargetingIcon_2", "/aztarec 2" },
    { "Azta Diamond",  "Interface\\TargetingFrame\\UI-RaidTargetingIcon_3", "/aztarec 3" },
    { "Azta Triangle", "Interface\\TargetingFrame\\UI-RaidTargetingIcon_4", "/aztarec 4" },
    { "Azta Moon",     "Interface\\TargetingFrame\\UI-RaidTargetingIcon_5", "/aztarec 5" },
    { "Azta Square",   "Interface\\TargetingFrame\\UI-RaidTargetingIcon_6", "/aztarec 6" },
    { "Azta Cross",    "Interface\\TargetingFrame\\UI-RaidTargetingIcon_7", "/aztarec 7" },
    { "Azta Skull",    "Interface\\TargetingFrame\\UI-RaidTargetingIcon_8", "/aztarec 8" },
    { "Azta Clear",    655994, "/aztarec clear" },
    { "Azta Undo",     236372, "/aztarec undo" },
}

local function GetMacroIconFileID(texturePath)
    if type(texturePath) == "number" then return texturePath end
    if type(GetFileIDFromPath) ~= "function" then return 134400 end
    local normalizedPath = texturePath:gsub("\\", "/")
    if not normalizedPath:lower():match("%.blp$") then
        normalizedPath = normalizedPath .. ".blp"
    end
    local fileID = GetFileIDFromPath(normalizedPath)
    return (fileID and fileID > 0) and fileID or 134400
end

local function CreateMarkerMacros()
    if InCombatLockdown() then
        Print("Macros cannot be created during combat. Try again out of combat.")
        return
    end

    local created = 0
    local updated = 0
    for _, definition in ipairs(macroDefinitions) do
        local name, icon, body = unpack(definition)
        local macroIcon = GetMacroIconFileID(icon)
        local existingIndex = GetMacroIndexByName(name)
        if existingIndex > 0 then
            local success = pcall(EditMacro, existingIndex, name, macroIcon, body)
            if success then updated = updated + 1 end
        else
            local success, macroIndex = pcall(CreateMacro, name, macroIcon, body, true)
            if success and macroIndex then created = created + 1 end
        end
    end

    Print(created .. " macros created, " .. updated .. " macros updated.")
    if created + updated < #macroDefinitions then
        Print("There are not enough free character-specific macro slots.")
    else
        Print("The macros are available under Macros > Character Specific Macros.")
    end
end

local function ShowHelp()
    Print("Commands:")
    Print("/aztarec 1 ... /aztarec 8 - append a raid marker to the sequence.")
    Print("/aztarec star, circle, diamond, triangle, moon, square, cross, skull - named marker commands.")
    Print("/aztarec clear - clear the sequence; /aztarec undo - remove the last marker.")
    Print("/aztarec macros - create or update all character-specific Azta macros.")
    Print("/aztarec lock, unlock, show, hide, reset - control the display bar.")
    Print("Short command: /azta")
end

local function HandleSlash(message)
    local command = strtrim((message or ""):lower())
    local marker = ParseMarker(command)

    if marker then
        AddMarker(marker)
    elseif command == "macros" then
        CreateMarkerMacros()
    elseif command == "help" or command == "" then
        ShowHelp()
    elseif command == "clear" then
        wipe(AztaRecMemoryDB.sequence)
        Render()
    elseif command == "undo" then
        table.remove(AztaRecMemoryDB.sequence)
        Render()
    elseif command == "show" then
        AztaRecMemoryDB.visible = true
        ARM.display:Show()
    elseif command == "hide" then
        AztaRecMemoryDB.visible = false
        ARM.display:Hide()
    elseif command == "lock" then
        AztaRecMemoryDB.locked = true
        Print("The display bar is locked.")
    elseif command == "unlock" then
        AztaRecMemoryDB.locked = false
        AztaRecMemoryDB.visible = true
        ARM.display:Show()
        Print("The display bar is unlocked. Drag it with the left mouse button.")
    elseif command == "reset" then
        wipe(AztaRecMemoryDB.sequence)
        AztaRecMemoryDB.point = "CENTER"
        AztaRecMemoryDB.relativePoint = "CENTER"
        AztaRecMemoryDB.x = 0
        AztaRecMemoryDB.y = 180
        ARM.display:ClearAllPoints()
        ARM.display:SetPoint("CENTER", UIParent, "CENTER", 0, 180)
        Render()
    else
        ShowHelp()
    end
end

ARM:RegisterEvent("ADDON_LOADED")
ARM:SetScript("OnEvent", function(_, _, loadedAddon)
    if loadedAddon ~= addonName then return end

    AztaRecMemoryDB = AztaRecMemoryDB or {}
    CopyDefaults(DEFAULTS, AztaRecMemoryDB)
    if type(AztaRecMemoryDB.sequence) ~= "table" then AztaRecMemoryDB.sequence = {} end

    CreateDisplay()
    ARM.display:SetPoint(
        AztaRecMemoryDB.point,
        UIParent,
        AztaRecMemoryDB.relativePoint,
        AztaRecMemoryDB.x,
        AztaRecMemoryDB.y
    )
    if not AztaRecMemoryDB.visible then ARM.display:Hide() end
    Render()

    SLASH_AZTARECMEMORY1 = "/aztarec"
    SLASH_AZTARECMEMORY2 = "/azta"
    SlashCmdList.AZTARECMEMORY = HandleSlash
    Print("Loaded. Macro example: /aztarec 1 - Help: /aztarec help")
    ARM:UnregisterEvent("ADDON_LOADED")
end)
