local _, addon = ...

addon.Indicator = addon.Indicator or {}
local Indicator = addon.Indicator

local BASE_SIZE = 36

local function getActionKey(actionRef)
    if not actionRef then
        return "none"
    end
    return tostring(actionRef.type or "") .. ":" .. tostring(actionRef.id or "")
end

function Indicator:GetGlobalConfig()
    addon.globalDB.indicator = addon.globalDB.indicator or {
        enabled = false,
        scale = 1.0,
        locked = false,
    }
    return addon.globalDB.indicator
end

function Indicator:GetCharConfig()
    addon.charDB.indicator = addon.charDB.indicator or {
        point = "CENTER",
        relativePoint = "CENTER",
        x = 0,
        y = -140,
    }
    return addon.charDB.indicator
end

function Indicator:ApplyPosition()
    if not self.frame then
        return
    end
    local c = self:GetCharConfig()
    self.frame:ClearAllPoints()
    self.frame:SetPoint(c.point or "CENTER", UIParent, c.relativePoint or "CENTER", c.x or 0, c.y or 0)
end

function Indicator:SavePosition()
    if not self.frame then
        return
    end
    local point, _, relativePoint, x, y = self.frame:GetPoint(1)
    local c = self:GetCharConfig()
    c.point = point or "CENTER"
    c.relativePoint = relativePoint or "CENTER"
    c.x = math.floor((x or 0) + 0.5)
    c.y = math.floor((y or 0) + 0.5)
end

function Indicator:ApplyConfig()
    if not self.frame then
        return
    end
    local g = self:GetGlobalConfig()
    self.frame:SetScale(tonumber(g.scale) or 1.0)
    self.frame:EnableMouse(g.enabled == true)
    self.frame:SetMovable(g.enabled == true and g.locked ~= true)
    if g.enabled then
        self.frame:Show()
    else
        self.frame:Hide()
    end
end

function Indicator:SetEnabled(enabled)
    local g = self:GetGlobalConfig()
    g.enabled = enabled == true
    self:ApplyConfig()
end

function Indicator:SetLocked(locked)
    local g = self:GetGlobalConfig()
    g.locked = locked == true
    self:ApplyConfig()
end

function Indicator:SetScale(scale)
    local g = self:GetGlobalConfig()
    g.scale = math.max(0.5, math.min(2.0, tonumber(scale) or 1.0))
    self:ApplyConfig()
end

function Indicator:ResetPosition()
    local c = self:GetCharConfig()
    c.point = "CENTER"
    c.relativePoint = "CENTER"
    c.x = 0
    c.y = -140
    self:ApplyPosition()
end

function Indicator:RefreshDisplay()
    if not self.frame then
        return
    end
    local g = self:GetGlobalConfig()
    if not g.enabled then
        return
    end

    local slotKey = addon.Actions:GetModifierSlotKey()
    local actionRef = addon:GetBindingSlotAction(slotKey)
    local actionKey = slotKey .. "|" .. getActionKey(actionRef)
    if actionKey == self.lastActionKey then
        return
    end
    self.lastActionKey = actionKey

    if actionRef and actionRef.icon then
        self.frame.icon:SetTexture(actionRef.icon)
    else
        self.frame.icon:SetTexture(134400)
    end

    self.frame.slotLabel:SetText(addon.Bindings.SLOT_LABELS[slotKey] or slotKey)
end

function Indicator:CreateFrame()
    if self.frame then
        return
    end

    local f = CreateFrame("Button", "MountBinderFloatingIndicator", UIParent, "BackdropTemplate")
    f:SetSize(BASE_SIZE, BASE_SIZE)
    f:SetFrameStrata("MEDIUM")
    f:SetClampedToScreen(true)
    f:RegisterForDrag("LeftButton")
    f:SetBackdrop({
        bgFile = "Interface/Buttons/WHITE8x8",
        edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
        edgeSize = 10,
        insets = { left = 1, right = 1, top = 1, bottom = 1 },
    })
    f:SetBackdropColor(0.05, 0.05, 0.05, 0.9)

    f.icon = f:CreateTexture(nil, "ARTWORK")
    f.icon:SetPoint("TOPLEFT", 3, -3)
    f.icon:SetPoint("BOTTOMRIGHT", -3, 3)
    f.icon:SetTexture(134400)

    f.slotLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.slotLabel:SetPoint("BOTTOM", f, "TOP", 0, 2)
    f.slotLabel:SetText("No Mod")

    f:SetScript("OnDragStart", function(frame)
        local g = self:GetGlobalConfig()
        if g.enabled and g.locked ~= true then
            frame:StartMoving()
        end
    end)
    f:SetScript("OnDragStop", function(frame)
        frame:StopMovingOrSizing()
        self:SavePosition()
    end)
    f:SetScript("OnEnter", function(frame)
        GameTooltip:SetOwner(frame, "ANCHOR_RIGHT")
        GameTooltip:SetText("MountBinder Indicator")
        local g = self:GetGlobalConfig()
        if g.locked then
            GameTooltip:AddLine("Locked", 0.8, 0.8, 0.8)
        else
            GameTooltip:AddLine("Drag to reposition", 0.8, 0.8, 0.8)
        end
        GameTooltip:Show()
    end)
    f:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    local elapsed = 0
    f:SetScript("OnUpdate", function(_, dt)
        elapsed = elapsed + dt
        if elapsed >= 0.05 then
            elapsed = 0
            self:RefreshDisplay()
        end
    end)

    self.frame = f
    self:ApplyPosition()
    self:ApplyConfig()
end

function Indicator:Initialize()
    self:GetGlobalConfig()
    self:GetCharConfig()
    self:CreateFrame()
end
