local PT = AhUI
if not PT then return end

local IP = PT.InfoPanel
IP.elements = IP.elements or {}
IP.elementTypes = IP.elementTypes or {}
IP.availableTypeInfo = IP.availableTypeInfo or {}

function IP:GetAvailableElementTypes()
    return self.availableTypeInfo or {}
end

function IP:RegisterElementType(type, factory)
    if not type or not factory then return end
    IP.elementTypes[type] = factory
end

function IP:RegisterElement(uid, element)
    IP:InitConfig()

    self.elements = self.elements or {}
    self.config.elements = self.config.elements or {}

    self.config.elements[uid] = self.config.elements[uid] or {
        x = 0,
        enabled = true,
        width = element.width or 60,
    }

    element.id = uid
    element.db = self.config.elements[uid]
    self.elements[uid] = element
end

function IP:AttachAllElements()
    if not (self.frame and self.frame.content) then return end
    self:InitConfig()

    local used = {}

for _, entry in ipairs(self.config.layout or {}) do
    local type = entry.type
    local uid  = entry.uid

    if not uid and type then
        uid = type:lower() .. "_1"
        entry.uid = uid
    end

    if uid then
        used[uid] = true
    end

        if not self.elements[uid] then
            local factory = self.elementTypes[type]
            if factory then
                local element = factory(uid)
                if element then
                    self:RegisterElement(uid, element)
                end
            end
        end
    end

    for uid, element in pairs(self.elements) do
        if not used[uid] then
            if element.frame then
                element.frame:Hide()
                element.frame:SetParent(nil)
            end
            self.elements[uid] = nil
            self.config.elements[uid] = nil
        end
    end
end

function IP:UpdateElements()
    if not (self.frame and self.frame.content) then return end
    local panel = self.frame.content
    local panelWidth = panel:GetWidth()
    local h = self.config.appearance.height

    for _, element in pairs(self.elements or {}) do
        if element.frame and element.db then
            element.frame:SetHeight(h)
            element.frame:SetWidth(element.db.width or element.width or 60)

            local x = tonumber(element.db.x) or 0
            local maxX = panelWidth - element.frame:GetWidth()
            if maxX < 0 then maxX = 0 end

            x = math.max(0, math.min(x, maxX))
            element.db.x = x

            element.frame:ClearAllPoints()
            element.frame:SetPoint("LEFT", panel, "LEFT", x, 0)

            if element.db.enabled then
                element.frame:Show()
            else
                element.frame:Hide()
            end

            if element.ApplyHeight then
                element:ApplyHeight(h)
            end
            if element.Update then
                element:Update()
            end
        end
    end
end