local addonName, ns = ...

-- ============================================================================
-- BrightQoL – Marker Display
-- ============================================================================

local Markers = {}
ns.Markers = Markers

-- WindTools TargetToWorld mapping (rid → wid)
local T2W = { 5, 6, 3, 2, 7, 1, 4, 8 }

-- Textures (exact paths from WindTools)
local TEX_RAID  = "Interface\\TargetingFrame\\UI-RaidTargetingIcon_%d"
local TEX_CLEAR = "Interface\\BUTTONS\\UI-GroupLoot-Pass-Up"
local TEX_READY = "Interface\\RaidFrame\\ReadyCheck-Ready"
local TEX_TIMER = "Interface\\Icons\\Spell_unused2"

local function DB() return BrightQoL.markers end

local function GetBorderColor(db)
    if not db then return 0, 207/255, 1.0 end
    if db.borderUseClassColor then
        local cc = RAID_CLASS_COLORS and RAID_CLASS_COLORS[select(2, UnitClass("player"))]
        if cc then return cc.r, cc.g, cc.b end
    end
    local r = db.borderColorR or 0
    local g = db.borderColorG or (207/255)
    local b = db.borderColorB or 1.0
    return r, g, b
end


local bar     = nil
local buttons = {}  -- buttons[1..11+]

-- ── Create the bar and all buttons (called once at PLAYER_LOGIN) ──────────────
local function BuildBar()
    if bar then return end
    local db = DB()

    -- ── Root frame ──────────────────────────────────────────────────────────
    bar = CreateFrame("Frame", "BrightQoL_MarkerBar", UIParent, "BackdropTemplate")
    bar:SetFrameStrata("MEDIUM")
    bar:SetMovable(true)
    bar:EnableMouse(true)
    bar:SetClampedToScreen(true)
    bar:RegisterForDrag("LeftButton")
    bar:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 2,
        insets   = { left = 2, right = 2, top = 2, bottom = 2 },
    })
    bar:SetBackdropColor(0.05, 0.05, 0.08, 0.90)
    do local _r,_g,_b = GetBorderColor(DB()); bar:SetBackdropBorderColor(_r,_g,_b, 0.75) end

    bar:SetScript("OnDragStart", function(self)
        if not DB().locked then self:StartMoving() end
    end)
    bar:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
        local pt, _, _, x, y = self:GetPoint()
        DB().pos = { pt, x, y }
    end)

    -- ── Textures ────────────────────────────────────────────────────────────
    local MK = "Interface\\AddOns\\BrightQoL\\Assets\\Markers\\"

    -- ── 14 buttons: 8 markers + clear + readyCheck + timer + mainTank + mainAssist + roleCheck
    for i = 1, 14 do
        local btn = CreateFrame("Button", "BrightQoL_MarkerBtn"..i, bar, "SecureActionButtonTemplate")
        btn:RegisterForClicks("AnyUp", "AnyDown")

        local tex = btn:CreateTexture(nil, "ARTWORK")
        tex:SetPoint("CENTER")
        btn.tex = tex

        local hl = btn:CreateTexture(nil, "HIGHLIGHT")
        hl:SetAllPoints()
        hl:SetColorTexture(1, 1, 1, 0.15)

        buttons[i] = btn
    end

    -- Set textures
    for i = 1, 8 do
        buttons[i].tex:SetTexture(TEX_RAID:format(i))
    end
    buttons[9].tex:SetTexture(TEX_CLEAR)
    buttons[10].tex:SetTexture(TEX_READY)
    buttons[11].tex:SetTexture(TEX_TIMER)
    buttons[11].tex:SetTexCoord(0.25, 0.8, 0.2, 0.75)
    buttons[12].tex:SetTexture(MK.."icon_mainTank.tga")
    buttons[13].tex:SetTexture(MK.."icon_mainAssist.tga")
    buttons[14].tex:SetTexture(MK.."icon_roleCheck.tga")

    -- Separator texture between markers and control buttons (purely visual)
    bar.sep = bar:CreateTexture(nil, "ARTWORK")
    bar.sep:SetColorTexture(0, 207/255, 1.0, 0.4)
end

-- ── Update attributes (called after BuildBar and on settings change) ──────────
local function UpdateAttributes()
    local db  = DB()
    local mod = db.modifier or "shift"

    for i = 1, 8 do
        local btn = buttons[i]
        -- type* = applies to any mouse button. macrotext1 = left, macrotext2 = right.
        btn:SetAttribute("type*",      "macro")
        btn:SetAttribute("macrotext1", "/tm " .. i)
        btn:SetAttribute("macrotext2", "/tm 0")
        -- Modifier+click: world marker. shift-type* IS valid in SecureActionButtonTemplate.
        btn:SetAttribute(mod.."-type*",      "macro")
        btn:SetAttribute(mod.."-macrotext1", "/wm " .. T2W[i])
        btn:SetAttribute(mod.."-macrotext2", "/cwm " .. T2W[i])
        -- Clear stale attributes from previous modifier setting
        for _, m in ipairs({"shift","alt","ctrl"}) do
            if m ~= mod then
                btn:SetAttribute(m.."-type*",      nil)
                btn:SetAttribute(m.."-macrotext1", nil)
                btn:SetAttribute(m.."-macrotext2", nil)
            end
        end
    end

    -- Button 9: Clear all raid marks (left) + clear all world markers (modifier+left)
    local btn9 = buttons[9]
    btn9:SetAttribute("type*",             "raidtarget")
    btn9:SetAttribute("action",            "clear-all")
    btn9:SetAttribute(mod.."-type*",       "macro")
    btn9:SetAttribute(mod.."-macrotext1",  "/cwm all")

    -- Button 10: Ready Check (left) / Toggle Combat Log (right)
    local btn10 = buttons[10]
    btn10:SetAttribute("type*",      "macro")
    btn10:SetAttribute("macrotext1", "/readycheck")
    btn10:SetAttribute("macrotext2", "/combatlog")

    -- Button 11: Pull Countdown (left = start, right = cancel)
    local btn11 = buttons[11]
    local t = tostring(db.countdownTime or 5)
    btn11:SetAttribute("type*", "macro")
    if C_AddOns and C_AddOns.IsAddOnLoaded("BigWigs") then
        btn11:SetAttribute("macrotext1", "/pull " .. t)
        btn11:SetAttribute("macrotext2", "/pull 0")
    elseif C_AddOns and C_AddOns.IsAddOnLoaded("DBM-Core") then
        btn11:SetAttribute("macrotext1", "/dbm pull " .. t)
        btn11:SetAttribute("macrotext2", "/dbm pull 0")
    else
        local slash = SLASH_COUNTDOWN1 or "/countdown"
        btn11:SetAttribute("macrotext1", slash .. " " .. t)
        btn11:SetAttribute("macrotext2", slash .. " 0")
    end

    -- Button 12: Main Tank
    local btn12 = buttons[12]
    btn12:SetAttribute("type*",      "macro")
    btn12:SetAttribute("macrotext1", "/mt")
    btn12:SetAttribute("macrotext2", "/clearmt")

    -- Button 13: Main Assist
    local btn13 = buttons[13]
    btn13:SetAttribute("type*",      "macro")
    btn13:SetAttribute("macrotext1", "/ma")
    btn13:SetAttribute("macrotext2", "/clearma")

    -- Button 14: Role Check
    local btn14 = buttons[14]
    btn14:SetAttribute("type*",      "macro")
    btn14:SetAttribute("macrotext1", "/rolecheck")
end

-- ── Update tooltips ───────────────────────────────────────────────────────────
local RAID_NAMES = {"Star","Circle","Diamond","Triangle","Moon","Square","Cross","Skull"}
local function UpdateTooltips()
    if not bar then return end
    local db  = DB()
    local mod = (db.modifier or "shift"):sub(1,1):upper() .. (db.modifier or "shift"):sub(2)

    local function tip(btn, title, lines)
        btn:SetScript("OnEnter", function(self)
            if db.tooltips then
                GameTooltip:SetOwner(self, "ANCHOR_BOTTOM", 0, -4)
                GameTooltip:ClearLines()
                GameTooltip:SetText(title, 0, 207/255, 1, 1)
                if lines then
                    for _, l in ipairs(lines) do GameTooltip:AddLine(l, 1,1,1) end
                end
                GameTooltip:Show()
            end
            if db.mouseOver then bar:SetAlpha(db.alpha or 0.9) end
        end)
        btn:SetScript("OnLeave", function()
            GameTooltip:Hide()
            if db.mouseOver then bar:SetAlpha(0) end
        end)
    end

    for i = 1, 8 do
        tip(buttons[i], RAID_NAMES[i], {
            "Left: Raid mark target",
            "Right: Remove raid mark",
            mod.."+Left: Place world marker",
            mod.."+Right: Clear world marker",
        })
    end
    tip(buttons[9],  "Clear All",       {"Left: Clear all raid marks", mod.."+Left: Clear all world markers"})
    tip(buttons[10], "Ready Check",     {"Left: Ready Check", "Right: Toggle Combat Log"})
    tip(buttons[11], "Pull Countdown",  {"Left: Start countdown", "Right: Cancel"})
    tip(buttons[12], "Main Tank",       {"Left: Set target as Main Tank", "Right: Clear Main Tank"})
    tip(buttons[13], "Main Assist",     {"Left: Set target as Main Assist", "Right: Clear Main Assist"})
    tip(buttons[14], "Role Check",      {"Left: Start Role Check"})
end

-- ── Layout (size bar, position buttons) ──────────────────────────────────────
local function Layout()
    if not bar then return end
    local db  = DB()
    local sz  = db.iconSize or 26
    local sp  = 3
    local pad = 5

    -- Build the ordered list of visible buttons
    local allBtns = {}
    for i = 1, 8 do allBtns[#allBtns+1] = buttons[i] end  -- 8 raid markers always shown
    allBtns[#allBtns+1] = buttons[9]                        -- clear always present

    -- Control buttons (optional)
    local controlBtns = {}
    if db.readyCheckEnabled then controlBtns[#controlBtns+1] = buttons[10] else buttons[10]:Hide() end
    if db.timerEnabled      then controlBtns[#controlBtns+1] = buttons[11] else buttons[11]:Hide() end
    if db.mainTankEnabled   then controlBtns[#controlBtns+1] = buttons[12] else buttons[12]:Hide() end
    if db.mainAssistEnabled then controlBtns[#controlBtns+1] = buttons[13] else buttons[13]:Hide() end
    if db.roleCheckEnabled  then controlBtns[#controlBtns+1] = buttons[14] else buttons[14]:Hide() end

    local hasControls = #controlBtns > 0

    -- Size all visible buttons
    for _, btn in ipairs(allBtns) do
        btn:SetSize(sz, sz); btn.tex:SetSize(sz, sz); btn:Show()
    end
    for _, btn in ipairs(controlBtns) do
        btn:SetSize(sz, sz); btn.tex:SetSize(sz, sz); btn:Show()
    end

    -- Position: chain markers+clear, then gap+separator, then controls
    local prev = nil
    for _, btn in ipairs(allBtns) do
        btn:ClearAllPoints()
        if not prev then
            btn:SetPoint("LEFT", bar, "LEFT", pad, 0)
        else
            btn:SetPoint("LEFT", prev, "RIGHT", sp, 0)
        end
        prev = btn
    end

    local sepGap = hasControls and (sp + 8) or 0
    for _, btn in ipairs(controlBtns) do
        btn:ClearAllPoints()
        if not prev then
            btn:SetPoint("LEFT", bar, "LEFT", pad, 0)
        elseif sepGap > 0 then
            btn:SetPoint("LEFT", prev, "RIGHT", sepGap, 0)
            sepGap = sp  -- only first control gets the extra gap
        else
            btn:SetPoint("LEFT", prev, "RIGHT", sp, 0)
        end
        prev = btn
    end

    -- Separator between markers/clear and controls
    if bar.sep then
        if hasControls then
            local sepX = pad + 9*(sz+sp) + 3
            bar.sep:SetSize(2, sz - 8)
            bar.sep:ClearAllPoints()
            bar.sep:SetPoint("LEFT", bar, "LEFT", sepX, 0)
            bar.sep:Show()
        else
            bar.sep:Hide()
        end
    end

    -- Bar total size
    local numBase    = 9  -- 8 markers + clear
    local numControl = #controlBtns
    local numTotal   = numBase + numControl
    local sepBonus   = hasControls and 8 or 0
    local totalW = pad*2 + numTotal*sz + (numTotal-1)*sp + sepBonus
    local totalH = sz + pad*2
    bar:SetSize(totalW, totalH)
end

-- ── Position restore ─────────────────────────────────────────────────────────
local function RestorePosition()
    if not bar then return end
    local p = DB().pos
    bar:ClearAllPoints()
    if p and p[1] and p[2] and p[3] then
        bar:SetPoint(p[1], UIParent, p[1], p[2], p[3])
    else
        bar:SetPoint("CENTER", UIParent, "CENTER", 0, 150)
    end
end

-- ── Mouseover fade ────────────────────────────────────────────────────────────
local function UpdateFade()
    if not bar then return end
    local db = DB()
    if db.mouseOver then
        bar:SetAlpha(0)
        bar:SetScript("OnEnter", function() bar:SetAlpha(db.alpha or 0.9) end)
        bar:SetScript("OnLeave", function() bar:SetAlpha(0) end)
    else
        bar:SetAlpha(db.alpha or 0.9)
        bar:SetScript("OnEnter", nil)
        bar:SetScript("OnLeave", nil)
    end
end

-- ── Public API ────────────────────────────────────────────────────────────────
function Markers:ApplySettings()
    if not bar then return end
    if InCombatLockdown() then return end
    UpdateAttributes()
    Layout()
    RestorePosition()
    UpdateFade()
    UpdateTooltips()
    -- Backdrop / border visibility
    local db = DB()
    bar:SetBackdropColor(0.05, 0.05, 0.08, db.showBackdrop and 0.90 or 0.0)
    do local _r,_g,_b = GetBorderColor(db); bar:SetBackdropBorderColor(_r,_g,_b, db.showBorder and 0.75 or 0.0) end
    if bar.sep then local _r,_g,_b = GetBorderColor(db); bar.sep:SetColorTexture(_r,_g,_b, 0.5) end
end

function Markers:UpdateVisibility()
    if not bar then return end
    -- Always unregister any stale state driver from old saved vars
    UnregisterStateDriver(bar, "visibility")
    if DB().enabled then
        bar:Show()
    else
        bar:Hide()
    end
end

function Markers:Refresh()
    if InCombatLockdown() then return end
    Markers:ApplySettings()
    Markers:UpdateVisibility()
end

-- ── Init at PLAYER_LOGIN ──────────────────────────────────────────────────────
local initFrame = CreateFrame("Frame")
initFrame:RegisterEvent("PLAYER_LOGIN")
initFrame:SetScript("OnEvent", function(self, event)
    self:UnregisterEvent("PLAYER_LOGIN")
    BuildBar()
    -- Short delay to ensure all saved vars are processed and taint is settled
    C_Timer.After(0.1, function()
        Markers:ApplySettings()
        Markers:UpdateVisibility()
    end)
end)
