-------------------------
-- AiB Co-Tank | My Private Auras
-- Zeigt eigene Private Auras als freiverschiebbaren Frame
-------------------------

local ns = AiB.CoTank.ns
ns.MyAuras = {}

local K          = ns.K
local DB_KEY     = "myPrivateAuras"
local FRAME_NAME = "AiB_MyPrivateAurasFrame"

-- Default-Einstellungen
local DEFAULTS = {
    enabled   = true,
    size      = 48,
    count     = 6,
    locked    = false,
    point     = "CENTER",
    relPoint  = "CENTER",
    x         = 0,
    y         = -200,
    spacing   = 4,
    growDir   = "RIGHT",
}

local function DB()
    local db = ns.DB()
    if not db[DB_KEY] then db[DB_KEY] = {} end
    return db[DB_KEY]
end

local function Get(key)
    local d = DB()
    if d[key] ~= nil then return d[key] end
    return DEFAULTS[key]
end

-- ── Frame ─────────────────────────────────────────────────────────────────
local frame      = nil
local anchorIDs  = {}
local scaleFrames = {}

local function CreateFrame_()
    if frame then return end

    frame = CreateFrame("Frame", FRAME_NAME, UIParent)
    frame:SetFrameStrata("MEDIUM")
    frame:SetClampedToScreen(true)
    frame:SetPoint(Get("point"), UIParent, Get("relPoint"), Get("x"), Get("y"))
    frame:SetSize(10, 10)  -- wird durch PositionIcons() korrekt gesetzt

    -- Drag
    frame:SetMovable(true)
    frame:EnableMouse(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetScript("OnDragStart", function(self)
        if not Get("locked") then self:StartMoving() end
    end)
    frame:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
        local p, _, rp, x, y = self:GetPoint()
        local d = DB()
        d.point = p; d.relPoint = rp; d.x = x; d.y = y
    end)

    -- Rechtsklick: Lock toggle
    frame:SetScript("OnMouseUp", function(self, btn)
        if btn == "RightButton" then
            local d = DB(); d.locked = not d.locked
            ns.MyAuras:Refresh()
        end
    end)

    ns.MyAuras.frame = frame
end

local function ClearAnchors()
    if InCombatLockdown() then return end
    for _, id in ipairs(anchorIDs) do
        pcall(C_UnitAuras.RemovePrivateAuraAnchor, id)
    end
    anchorIDs = {}
end

local function PositionIcons()
    local count   = Get("count")
    local size    = Get("size")
    local spacing = Get("spacing")
    local growDir = Get("growDir")

    local totalW = count * size + (count - 1) * spacing
    local totalH = size
    if growDir == "UP" or growDir == "DOWN" then
        totalW = size
        totalH = count * size + (count - 1) * spacing
    end
    frame:SetSize(math.max(totalW, 1), math.max(totalH, 1))

    for i = 1, count do
        if not scaleFrames[i] then
            local sf = CreateFrame("Frame", nil, frame)
            sf:SetSize(size, size)
            scaleFrames[i] = sf
        end
        local sf = scaleFrames[i]
        sf:SetSize(size, size)
        sf:ClearAllPoints()
        local ox, oy = 0, 0
        if     growDir == "RIGHT" then ox = (i-1) * (size + spacing)
        elseif growDir == "LEFT"  then ox = -(i-1) * (size + spacing)
        elseif growDir == "UP"    then oy = (i-1) * (size + spacing)
        elseif growDir == "DOWN"  then oy = -(i-1) * (size + spacing)
        end
        sf:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", ox, oy)
        sf:Show()
    end
    -- ueberschuessige scaleFrames verstecken
    for i = count + 1, #scaleFrames do
        scaleFrames[i]:Hide()
    end
end

local function AttachAnchors()
    if InCombatLockdown() then return end
    ClearAnchors()
    if not Get("enabled") then return end
    local count = Get("count")
    local size  = Get("size")
    PositionIcons()
    for i = 1, count do
        local sf = scaleFrames[i]
        if sf then
            local ok, id = pcall(C_UnitAuras.AddPrivateAuraAnchor, {
                unitToken            = "player",
                auraIndex            = i,
                parent               = sf,
                isContainer          = false,
                showCountdownFrame   = true,
                showCountdownNumbers = true,
                iconInfo = {
                    iconWidth   = size,
                    iconHeight  = size,
                    borderScale = 1,
                    iconAnchor  = {
                        point         = "CENTER",
                        relativeTo    = sf,
                        relativePoint = "CENTER",
                        offsetX = 0, offsetY = 0,
                    },
                },
            })
            if ok and id then
                table.insert(anchorIDs, id)
            end
        end
    end
end

-- ── Mock Icons fuer Preview ───────────────────────────────────────────────
local mockIcons = {}
local isPreview = false

-- Mock Icons: 1:1 wie Co-Tank ShowMockPrivateAuras
-- Textur auf container (anchorFrames), nicht auf scaleFrame
local MOCK_ICONS = ns.K.MOCK_PREVIEW_DEBUFF_ICONS

-- containers = anchorFrames (BackdropTemplate, volle Groesse, wie co-tank)
local containers = {}

local function EnsureContainers()
    local count = Get("count")
    local size  = Get("size")
    for i = 1, count do
        if not containers[i] then
            local c = CreateFrame("Frame", nil, frame, "BackdropTemplate")
            c:SetSize(size, size)
            containers[i] = c
        else
            containers[i]:SetSize(size, size)
        end
        containers[i]:Show()
    end
    for i = count+1, #containers do
        containers[i]:Hide()
    end
end

local function LayoutContainers()
    local count   = Get("count")
    local size    = Get("size")
    local spacing = Get("spacing")
    local growDir = Get("growDir")
    -- Frame-Groesse auf gesamte Icon-Reihe setzen
    local isHoriz = (growDir=="RIGHT" or growDir=="LEFT")
    local totalW  = isHoriz and (count*size + (count-1)*spacing) or size
    local totalH  = (not isHoriz) and (count*size + (count-1)*spacing) or size
    frame:SetSize(totalW, totalH)
    for i = 1, count do
        local c = containers[i]
        if c then
            c:ClearAllPoints()
            if i == 1 then
                c:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
            else
                local prev = containers[i-1]
                if growDir == "RIGHT" then
                    c:SetPoint("LEFT", prev, "RIGHT", spacing, 0)
                elseif growDir == "LEFT" then
                    c:SetPoint("RIGHT", prev, "LEFT", -spacing, 0)
                elseif growDir == "UP" then
                    c:SetPoint("BOTTOM", prev, "TOP", 0, spacing)
                else -- DOWN
                    c:SetPoint("TOP", prev, "BOTTOM", 0, -spacing)
                end
            end
        end
    end
end

local function ShowPreview()
    isPreview = true
    EnsureContainers()
    LayoutContainers()
    local count = Get("count")
    local max   = math.min(count, #MOCK_ICONS * 10)
    for i = 1, #containers do
        local c = containers[i]
        if c then
            if i <= max then
                if not c.mockIcon then
                    local tex = c:CreateTexture(nil, "OVERLAY")
                    tex:SetPoint("TOPLEFT",     c, "TOPLEFT",      1, -1)
                    tex:SetPoint("BOTTOMRIGHT", c, "BOTTOMRIGHT", -1,  1)
                    tex:SetTexCoord(0.08, 0.92, 0.08, 0.92)
                    c.mockIcon = tex
                end
                c.mockIcon:SetTexture(MOCK_ICONS[((i-1) % #MOCK_ICONS) + 1])
                c.mockIcon:SetAlpha(0.5)
                c:SetBackdropBorderColor(0, 0, 0, 0.7)
                if not c.mockStack then
                    local fs = c:CreateFontString(nil, "OVERLAY")
                    fs:SetFontObject(GameFontHighlightSmall)
                    fs:SetPoint("BOTTOMRIGHT", c, "BOTTOMRIGHT", 1, 1)
                    c.mockStack = fs
                end
                local stacks = ({3,1,5,2})[((i-1)%4)+1]
                c.mockStack:SetText(stacks > 1 and tostring(stacks) or "")
                c.mockStack:Show()
                c:Show()
            elseif c.mockIcon then
                c.mockIcon:SetAlpha(0)
                c:SetBackdropBorderColor(0,0,0,0)
                if c.mockStack then c.mockStack:Hide() end
                c:Hide()
            end
        end
    end
    frame:Show()
end

local function HidePreview()
    isPreview = false
    for _, c in ipairs(containers) do
        if c then
            if c.mockIcon then c.mockIcon:SetAlpha(0) end
            c:SetBackdropBorderColor(0,0,0,0)
            if c.mockStack then c.mockStack:Hide() end
            c:Hide()
        end
    end
    if not Get("enabled") then frame:Hide() end
end

-- ── Public API ─────────────────────────────────────────────────────────────
function ns.MyAuras:GetEnabled() return Get("enabled") end
function ns.MyAuras:IsPreview()  return isPreview end

function ns.MyAuras:TogglePreview()
    if isPreview then HidePreview()
    else ShowPreview() end
end

function ns.MyAuras:RefreshPreview()
    if isPreview then ShowPreview() end
end

function ns.MyAuras:Initialize()
    CreateFrame_()
    frame:Show()
    if Get("enabled") then
        C_Timer.After(0, function() AttachAnchors() end)
    else
        frame:Hide()
    end
end

function ns.MyAuras:Refresh()
    if not frame then CreateFrame_() end
    ClearAnchors()
    if Get("enabled") then
        AttachAnchors()
    end
end

function ns.MyAuras:SetEnabled(val)
    DB().enabled = val
    if val then
        if frame then frame:Show() end
        self:Refresh()
    else
        ClearAnchors()
        if frame then frame:Hide() end
    end
end

function ns.MyAuras:SetSize(val)
    DB().size = val
    if isPreview then ShowPreview() else self:Refresh() end
end

function ns.MyAuras:SetCount(val)
    DB().count = val
    if isPreview then ShowPreview() else self:Refresh() end
end

function ns.MyAuras:SetSpacing(val)
    DB().spacing = val
    if isPreview then ShowPreview() else self:Refresh() end
end

function ns.MyAuras:SetGrowDir(val)
    DB().growDir = val
    if isPreview then ShowPreview() else self:Refresh() end
end

function ns.MyAuras:GetLocked() return Get("locked") end
