local PT = AhUI
if not PT then return end

PT.InfoPanel = PT.InfoPanel or {}
local IP = PT.InfoPanel

IP.DEFAULTS = {
    enabled = true,
    scope = "account",

    appearance = {
        height = 24,
        width  = 800,
        bgTexture = "Interface\\Buttons\\WHITE8x8",
        bgAlpha   = 0.70,

        borderTexture = "Interface\\Buttons\\WHITE8x8",
        borderSize    = 2,
        borderColor   = { 0, 0, 0, 1 },

        showBorder = true,
    },

    locked = false,
    panelPoint = { x = 0, y = 0 },

    elements = {},
    layout   = {},
}

local function GetScope()
    AhUI_DB = AhUI_DB or {}
    AhUI_DB.infopanel_settings = AhUI_DB.infopanel_settings or {}
    if AhUI_DB.infopanel_settings.scope ~= "character" then
        AhUI_DB.infopanel_settings.scope = "account"
    end
    return AhUI_DB.infopanel_settings.scope
end

local function GetDB()
    AhUI_DB = AhUI_DB or {}
    AhUI_CharConfig = AhUI_CharConfig or {}

    if GetScope() == "character" then
        AhUI_CharConfig.infopanel = AhUI_CharConfig.infopanel or {}
        return AhUI_CharConfig.infopanel
    end

    AhUI_DB.infopanel = AhUI_DB.infopanel or {}
    return AhUI_DB.infopanel
end

local function CopyDefaults(dst, src)
    for k, v in pairs(src) do
        if type(v) == "table" then
            dst[k] = dst[k] or {}
            CopyDefaults(dst[k], v)
        elseif dst[k] == nil then
            dst[k] = v
        end
    end
end

function IP:SetScope(scope)
    AhUI_DB = AhUI_DB or {}
    AhUI_DB.infopanel_settings = AhUI_DB.infopanel_settings or {}

    if scope ~= "character" then
        scope = "account"
    end

    AhUI_DB.infopanel_settings.scope = scope

    self.config = nil
end

function IP:Rebuild()
    self.config = nil

    self:InitConfig()

    if self.frame then
        self.frame:Hide()
        self.frame = nil
    end

    self:CreateFrame()

    if self.AttachAllElements then
        self:AttachAllElements()
    end

    if self.UpdateAppearance then
        self:UpdateAppearance()
    end

    if self.UpdateElements then
        self:UpdateElements()
    end
end

function IP:InitConfig()
    if self.config then return end

    local db = GetDB()
    CopyDefaults(db, IP.DEFAULTS)

    db.elements = db.elements or {}
    db.layout   = db.layout   or {}

    self.config = db
end

function IP:EnsureLayout()
		self:InitConfig()
end

function IP:AddElementToPanel(elemType)
    if not elemType then return end
    self:InitConfig()

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

local info = self.availableTypeInfo and self.availableTypeInfo[elemType]
local allowMulti = info and info.multi == true

if not allowMulti then
    for _, e in ipairs(self.config.layout) do
        if e.type == elemType then
            return
        end
    end
end
    local index = 1
    local uid
    repeat
        uid = elemType .. "_" .. index
        index = index + 1
    until not self.config.elements[uid]

    table.insert(self.config.layout, {
        type = elemType,
        uid  = uid,
    })

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

    if self.AttachAllElements then
        self:AttachAllElements()
    end
    if self.UpdateElements then
        self:UpdateElements()
    end
end

function IP:RemoveElementFromPanel(uid)
    if not uid then return end
    self:InitConfig()

    if not self.config.layout then return end

    for i = #self.config.layout, 1, -1 do
        if self.config.layout[i].uid == uid then
            table.remove(self.config.layout, i)
        end
    end

    if self.config.elements then
        self.config.elements[uid] = nil
    end

    if self.AttachAllElements then
        self:AttachAllElements()
    end
    if self.UpdateElements then
        self:UpdateElements()
    end
end

function IP:CreateFrame()
    self:InitConfig()

    if self.config.enabled == false then
        return
    end

    if self.frame then
        return self.frame
    end

    local f = CreateFrame("Frame", "AhUIInfoPanel", UIParent, "BackdropTemplate")
    f:SetFrameStrata("LOW")
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
	f:SetClampedToScreen(true)

    local pp = self.config.panelPoint
    f:SetPoint("BOTTOM", UIParent, "BOTTOM", pp.x or 0, pp.y or 0)
    f:SetSize(self.config.appearance.width, self.config.appearance.height)

    f:SetScript("OnDragStart", function(self)
        if IP:IsLocked() then return end
        self:StartMoving()
    end)

f:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
    if IP:IsLocked() then return end

    local uiW = UIParent:GetWidth()
    local uiH = UIParent:GetHeight()

local cx = self:GetCenter()
local bottom = self:GetBottom()
if not cx or not bottom then return end

local x = math.floor(cx - uiW / 2)
local y = math.floor(bottom)


    IP:InitConfig()
    IP.config.panelPoint.x = x
    IP.config.panelPoint.y = y

    self:ClearAllPoints()
    self:SetPoint("BOTTOM", UIParent, "BOTTOM", x, y)

    if IP.SyncPositionToUI then
        IP:SyncPositionToUI()
    end
end)
	
    local a = self.config.appearance

    f:SetBackdrop({
        bgFile   = a.bgTexture,
        edgeFile = a.showBorder ~= false and a.borderTexture or nil,
        edgeSize = a.showBorder ~= false and a.borderSize or 0,
    })

    local bc = self.config.appearance.borderColor
    f:SetBackdropColor(0, 0, 0, self.config.appearance.bgAlpha)
    if a.showBorder ~= false then
        f:SetBackdropBorderColor(bc[1], bc[2], bc[3], bc[4])
    end

    local content = CreateFrame("Frame", nil, f)
    content:SetAllPoints()
    f.content = content

    self.frame = f
    return f
end

function IP:SetLocked(v)
    self:InitConfig()
    self.config.locked = v == true

    if self.frame then
        self.frame:EnableMouse(not self.config.locked)
    end
end

function IP:IsLocked()
    self:InitConfig()
    return self.config.locked == true
end

function IP:SetEnabled(v)
    self:InitConfig()
    self.config.enabled = v == true

    if self.config.enabled == false then
        if self.frame then
            self.frame:Hide()
        end
        return
    end

    if not self.frame then
        self:CreateFrame()

        if self.AttachAllElements then
            self:AttachAllElements()
        end

        if self.UpdateAppearance then
            self:UpdateAppearance()
        end

        if self.UpdateElements then
            self:UpdateElements()
        end
        return
    end

    self.frame:Show()
end

function IP:UpdateAppearance()
    if not self.frame then return end
    local a = self.config.appearance

    self.frame:SetSize(a.width, a.height)

    self.frame:SetBackdrop({
        bgFile   = a.bgTexture,
        edgeFile = a.showBorder ~= false and a.borderTexture or nil,
        edgeSize = a.showBorder ~= false and a.borderSize or 0,
    })

    self.frame:SetBackdropColor(0, 0, 0, a.bgAlpha)

    if a.showBorder ~= false then
        local bc = a.borderColor
        self.frame:SetBackdropBorderColor(bc[1], bc[2], bc[3], bc[4])
    end
end

local ev = CreateFrame("Frame")
ev:RegisterEvent("PLAYER_LOGIN")
ev:SetScript("OnEvent", function()
    IP:InitConfig()
    IP:EnsureLayout()

    if IP.config.enabled == false then
        return
    end

    IP:CreateFrame()

    if IP.AttachAllElements then
        IP:AttachAllElements()
    end

    IP:UpdateAppearance()
    if IP.UpdateElements then
        IP:UpdateElements()
    end
end)
