-- ## Author: Giftia + GPT-5.2 ## Version: 0.2.4 DamageMeterFormatFix
local CONSTANTS = {
    MATERIALS_TEXTURE = "Interface\\AddOns\\OrzUI\\Media\\Modules\\Skada\\YaSkada05.blp",  -- 自定义纹理路径
    MAX_WINDOWS = 3,  -- 最大伤害统计窗口数量
    WINDOW_PREFIX = "DamageMeterSessionWindow",  -- 窗口名称前缀
    HIDE_DELAY = 3  -- 鼠标离开后自动隐藏的延迟时间（秒）
}

-- 纹理替换模块
-- 此模块负责将默认的伤害统计条纹理替换为自定义纹理
local processedStatusBars = {}  -- 已处理的状态条表，避免重复处理

-- 标记状态条为已处理
-- 参数: statusBar - 需要标记的状态条
local function markStatusBarAsProcessed(statusBar)
    if statusBar then
        processedStatusBars[statusBar] = true
    end
end

-- 检查状态条是否已处理
-- 参数: statusBar - 需要检查的状态条
-- 返回: 布尔值，表示是否已处理
local function isStatusBarProcessed(statusBar)
    return processedStatusBars[statusBar] == true
end

-- 处理状态条纹理替换的辅助函数
-- 为状态条设置自定义纹理并隐藏背景元素
-- 参数: statusBar - 需要处理的状态条
local function applyMaterialsToStatusBar(statusBar)
    if statusBar and not isStatusBarProcessed(statusBar) then
        statusBar:SetStatusBarTexture(CONSTANTS.MATERIALS_TEXTURE)
        
        -- 隐藏默认的边框和背景，使用自定义纹理
        if statusBar.BackgroundEdge then
            statusBar.BackgroundEdge:Hide()
        end
        
        if statusBar.Background then
            statusBar.Background:Hide()
        end
        
        markStatusBarAsProcessed(statusBar)
    end
end

-- 主要纹理替换和边框背景隐藏函数
-- 遍历所有伤害统计窗口，替换其中的状态条纹理
local function replaceDamageMeterTextures()
    -- 检查所有伤害统计窗口（通常最多3个）
    for i = 1, CONSTANTS.MAX_WINDOWS do
        local mainWindow = _G[CONSTANTS.WINDOW_PREFIX .. i]
        
        -- 如果窗口存在且可见
        if mainWindow and mainWindow:IsVisible() then
            -- 处理LocalPlayerEntry的状态条
            if mainWindow.LocalPlayerEntry and mainWindow.LocalPlayerEntry.StatusBar then
                applyMaterialsToStatusBar(mainWindow.LocalPlayerEntry.StatusBar)
            end
            
            -- 如果窗口有ScrollBox
            if mainWindow.ScrollBox and mainWindow.ScrollBox.ScrollTarget then
                local scrollTarget = mainWindow.ScrollBox.ScrollTarget
                
                -- 遍历滚动目标下的所有子元素（伤害统计条）
                for _, child in ipairs({scrollTarget:GetChildren()}) do
                    -- 如果子元素有StatusBar
                    if child.StatusBar then
                        applyMaterialsToStatusBar(child.StatusBar)
                    end
                end
            end
        end
    end
end

-- 创建定时器定期执行替换
local textureTimer = C_Timer.NewTicker(1, function()
    replaceDamageMeterTextures()
end)

-- 玩家登录时立即执行一次
local loginFrame = CreateFrame("Frame")
loginFrame:RegisterEvent("PLAYER_LOGIN")
loginFrame:SetScript("OnEvent", function()
    C_Timer.After(1, function()
        replaceDamageMeterTextures()
    end)
end)


-- 悬停效果模块
-- 此模块负责实现鼠标悬停时显示标题栏元素，离开时自动隐藏的效果
local processedWindows = {}  -- 已处理的窗口表，避免重复处理

local function markWindowAsProcessed(windowName)
    processedWindows[windowName] = true
end

local function isWindowProcessed(windowName)
    return processedWindows[windowName] == true
end

-- 创建智能的鼠标检测区域
local function createSmartHoverFrame(parentWindow)
    if not parentWindow then return nil end
    
    local hoverFrame = CreateFrame("Frame", parentWindow:GetName().."SmartHoverController", parentWindow)
    
    -- 获取窗口尺寸
    local windowWidth = parentWindow:GetWidth() or 300
    local windowHeight = parentWindow:GetHeight() or 200
    
    -- 创建三个悬停检测区域：左上、右上、以及除交互元素外的其他区域
    local leftHover = CreateFrame("Frame", nil, hoverFrame)
    leftHover:SetPoint("TOPLEFT", parentWindow, "TOPLEFT", 0, 0)
    leftHover:SetPoint("BOTTOMLEFT", parentWindow, "TOPLEFT", 0, -30)
    leftHover:SetWidth(windowWidth * 0.3)  -- 左侧30%区域
    
    local rightHover = CreateFrame("Frame", nil, hoverFrame)
    rightHover:SetPoint("TOPRIGHT", parentWindow, "TOPRIGHT", 0, 0)
    rightHover:SetPoint("BOTTOMRIGHT", parentWindow, "TOPRIGHT", 0, -30)
    rightHover:SetWidth(windowWidth * 0.3)  -- 右侧30%区域
    
    local centerHover = CreateFrame("Frame", nil, hoverFrame)
    centerHover:SetPoint("TOPLEFT", leftHover, "TOPRIGHT", 0, 0)
    centerHover:SetPoint("TOPRIGHT", rightHover, "TOPLEFT", 0, 0)
    centerHover:SetPoint("BOTTOM", parentWindow, "TOP", 0, -30)
    
    -- 启用鼠标检测但不拦截点击
    leftHover:EnableMouse(true)
    rightHover:EnableMouse(true)
    centerHover:EnableMouse(true)
    
    -- 设置较低的层级
    leftHover:SetFrameStrata("BACKGROUND")
    rightHover:SetFrameStrata("BACKGROUND")
    centerHover:SetFrameStrata("BACKGROUND")
    
    hoverFrame.leftHover = leftHover
    hoverFrame.rightHover = rightHover
    hoverFrame.centerHover = centerHover
    
    return hoverFrame
end

-- 创建智能悬停检测区域
local mainHoverFrame = createSmartHoverFrame(DamageMeterSessionWindow1)
local hideTimer = nil
local isMouseOverHoverArea = false
local fadeElements = {}

-- 悬停显示/隐藏函数
local function ShowFadeElements()
    if hideTimer then
        hideTimer:Cancel()
        hideTimer = nil
    end
    
    for _, element in ipairs(fadeElements) do
        if element:GetAlpha() < 1 then
            UIFrameFadeIn(element, 0.3, element:GetAlpha(), 1)
        end
    end
end

local function HideFadeElements()
    for _, element in ipairs(fadeElements) do
        if element:GetAlpha() > 0 then
            UIFrameFadeOut(element, 0.3, element:GetAlpha(), 0)
        end
    end
end

-- 鼠标进入悬停区域时的处理
local function OnEnterHoverArea()
    isMouseOverHoverArea = true
    
    -- 取消任何待定的隐藏计时器
    if hideTimer then
        hideTimer:Cancel()
        hideTimer = nil
    end
    
    ShowFadeElements()
end

-- 鼠标离开悬停区域时的处理
local function OnLeaveHoverArea()
    isMouseOverHoverArea = false
    
    -- 取消任何已有的隐藏计时器
    if hideTimer then
        hideTimer:Cancel()
        hideTimer = nil
    end
    
    -- 设置新的隐藏计时器，延迟3秒
    hideTimer = C_Timer.After(CONSTANTS.HIDE_DELAY, function()
        if not isMouseOverHoverArea then
            HideFadeElements()
        end
    end)
end

-- 为标题栏元素添加鼠标检测
local function setupHeaderMouseInteraction(window)
    if not window or not window.Header then return end
    
    -- 为Header添加鼠标检测
    if window.Header then
        window.Header:EnableMouse(true)
        window.Header:SetScript("OnEnter", function(self)
            OnEnterHoverArea()
        end)
        window.Header:SetScript("OnLeave", function(self)
            OnLeaveHoverArea()
        end)
    end
    
    -- 为下拉菜单添加鼠标检测
    if window.SettingsDropdown then
        window.SettingsDropdown:EnableMouse(true)
        window.SettingsDropdown:SetScript("OnEnter", function(self)
            OnEnterHoverArea()
        end)
        window.SettingsDropdown:SetScript("OnLeave", function(self)
            OnLeaveHoverArea()
        end)
    end
    
    if window.DamageMeterTypeDropdown then
        window.DamageMeterTypeDropdown:EnableMouse(true)
        window.DamageMeterTypeDropdown:SetScript("OnEnter", function(self)
            OnEnterHoverArea()
        end)
        window.DamageMeterTypeDropdown:SetScript("OnLeave", function(self)
            OnLeaveHoverArea()
        end)
    end
    
    if window.SessionDropdown then
        window.SessionDropdown:EnableMouse(true)
        window.SessionDropdown:SetScript("OnEnter", function(self)
            OnEnterHoverArea()
        end)
        window.SessionDropdown:SetScript("OnLeave", function(self)
            OnLeaveHoverArea()
        end)
    end
end

-- 动态构建fadeElements表，只包含实际存在的元素

local function processWindowForHover(window, windowName)
    if not window or isWindowProcessed(windowName) then
        return
    end
    
    local hoverFrame = createSmartHoverFrame(window)
    
    if hoverFrame then
        hoverFrame.leftHover:SetScript("OnEnter", OnEnterHoverArea)
        hoverFrame.leftHover:SetScript("OnLeave", OnLeaveHoverArea)
        
        hoverFrame.rightHover:SetScript("OnEnter", OnEnterHoverArea)
        hoverFrame.rightHover:SetScript("OnLeave", OnLeaveHoverArea)
        
        hoverFrame.centerHover:SetScript("OnEnter", OnEnterHoverArea)
        hoverFrame.centerHover:SetScript("OnLeave", OnLeaveHoverArea)
        
        setupHeaderMouseInteraction(window)
        markWindowAsProcessed(windowName)
    end
end

local function processAllWindowsForHover()
    local windowNames = {}
    for i = 1, CONSTANTS.MAX_WINDOWS do
        table.insert(windowNames, CONSTANTS.WINDOW_PREFIX .. i)
    end
    
    for _, windowName in ipairs(windowNames) do
        local window = _G[windowName]
        if window and window:IsVisible() then
            processWindowForHover(window, windowName)
        end
    end
end

local function buildFadeElements()
    local elements = {}
    local windowNames = {}
    for i = 1, CONSTANTS.MAX_WINDOWS do
        table.insert(windowNames, CONSTANTS.WINDOW_PREFIX .. i)
    end
    
    for _, windowName in ipairs(windowNames) do
        local window = _G[windowName]
        if window and window:IsVisible() then
            if window.ScrollBox and window.ScrollBox.ScrollTarget then
                window.ScrollBox:EnableMouse(true)
                window.ScrollBox.ScrollTarget:EnableMouse(true)
            end
            
            local windowElements = {
                window.Header,
                window.SettingsDropdown and window.SettingsDropdown.Icon,
                window.DamageMeterTypeDropdown and window.DamageMeterTypeDropdown.Arrow,
                window.SessionDropdown and window.SessionDropdown.Background,
                window.DamageMeterTypeDropdown and window.DamageMeterTypeDropdown.TypeName,
                window.SessionDropdown and window.SessionDropdown.SessionName,
                window.SessionDropdown and window.SessionDropdown.Text
            }
            
            for _, element in ipairs(windowElements) do
                if element then
                    table.insert(elements, element)
                end
            end
        end
    end
    
    return elements
end

local function refreshFadeElements()
    local newElements = buildFadeElements()
    
    for _, element in ipairs(newElements) do
        local found = false
        for _, existingElement in ipairs(fadeElements) do
            if element == existingElement then
                found = true
                break
            end
        end
        
        if not found then
            element:SetAlpha(0)
        end
    end
    
    fadeElements = newElements
end

fadeElements = buildFadeElements()
for _, element in ipairs(fadeElements) do
    element:SetAlpha(0)
end

if mainHoverFrame then
    processWindowForHover(DamageMeterSessionWindow1, "DamageMeterSessionWindow1")
end

local function createAdditionalHoverFrames()
    processAllWindowsForHover()
end

-- 创建框架管理器来处理初始化和事件
local hoverManager = CreateFrame("Frame", "DamageMeterHoverManager", UIParent)
hoverManager:RegisterEvent("PLAYER_ENTERING_WORLD")

hoverManager:SetScript("OnEvent", function(self, event)
    if event == "PLAYER_ENTERING_WORLD" then
        C_Timer.After(2, function()
            refreshFadeElements()
            createAdditionalHoverFrames()
            
            C_Timer.NewTicker(1, function()
                refreshFadeElements()
                createAdditionalHoverFrames()
            end)
        end)
        self:UnregisterEvent("PLAYER_ENTERING_WORLD")
    end
end)


-- 框架绑定模块
-- 此模块负责同步多个伤害统计窗口的尺寸和位置
local processedWindows = {}  -- 已处理的窗口表，避免重复处理

-- 标记窗口为已处理
-- 参数: windowName - 需要标记的窗口名称
local function markWindowAsProcessed(windowName)
    processedWindows[windowName] = true
end

-- 检查窗口是否已处理
-- 参数: windowName - 需要检查的窗口名称
-- 返回: 布尔值，表示是否已处理
local function isWindowProcessed(windowName)
    return processedWindows[windowName] == true
end

-- 创建框架定位管理器
local frameManager = CreateFrame("Frame", "DamageMeterFrameManager", UIParent)
frameManager:RegisterEvent("PLAYER_ENTERING_WORLD")

-- 改进的主定位函数 - 自适应不同数量的窗口
-- 以第一个窗口为基准，排列其他窗口的位置
-- 参数: 无
local function setupDamageMeterPositions()
    local mainWindow = DamageMeterSessionWindow1
    
    -- 只处理可见的主窗口
    if not mainWindow or not mainWindow:IsVisible() then
        return
    end
    
    local previousWindow = mainWindow
    
    for i = 2, CONSTANTS.MAX_WINDOWS do
        local windowName = CONSTANTS.WINDOW_PREFIX..i
        local currentWindow = _G[windowName]
        
        if currentWindow and currentWindow:IsVisible() then
            if not isWindowProcessed(windowName) then
                local mainHeight = mainWindow:GetHeight()
                local mainWidth = mainWindow:GetWidth()
                
                if mainHeight and mainHeight > 0 and mainWidth and mainWidth > 0 then
                    currentWindow:SetHeight(mainHeight)
                    currentWindow:SetWidth(mainWidth)
                end
                
                currentWindow:ClearAllPoints()
                currentWindow:SetPoint("BOTTOM", previousWindow, "TOP", 0, 0)
                
                currentWindow:SetFrameStrata(previousWindow:GetFrameStrata() or "MEDIUM")
                
                markWindowAsProcessed(windowName)
            end
            previousWindow = currentWindow
        end
    end
end

-- 改进的尺寸同步函数
-- 同步所有可见窗口的尺寸，保持一致
-- 参数: 无
local function syncFrameSizes()
    local mainWindow = DamageMeterSessionWindow1
    
    -- 只处理可见的主窗口
    if not mainWindow or not mainWindow:IsVisible() then
        return
    end
    
    local mainHeight = mainWindow:GetHeight()
    local mainWidth = mainWindow:GetWidth()
    
    if mainHeight and mainHeight > 0 and mainWidth and mainWidth > 0 then
        -- 同步所有可见的窗口
        for i = 1, CONSTANTS.MAX_WINDOWS do
            local windowName = CONSTANTS.WINDOW_PREFIX..i
            local window = _G[windowName]
            if window and window:IsVisible() then
                window:SetHeight(mainHeight)
                window:SetWidth(mainWidth)
            end
        end
        
        -- 重新建立位置关系
        local previousWindow = mainWindow
        for i = 2, CONSTANTS.MAX_WINDOWS do
            local currentWindow = _G[CONSTANTS.WINDOW_PREFIX..i]
            if currentWindow and currentWindow:IsVisible() then
                currentWindow:ClearAllPoints()
                currentWindow:SetPoint("BOTTOM", previousWindow, "TOP", 0, 0)
                previousWindow = currentWindow
            end
        end
    end
end

-- 事件处理
frameManager:SetScript("OnEvent", function(self, event)
    if event == "PLAYER_ENTERING_WORLD" then
        C_Timer.After(2, function()
            setupDamageMeterPositions()
            
            C_Timer.NewTicker(1, function()
                setupDamageMeterPositions()
                
                local mainHeight = DamageMeterSessionWindow1:GetHeight()
                local mainWidth = DamageMeterSessionWindow1:GetWidth()
                
                if mainHeight and mainHeight ~= (self.lastHeight or 0) or 
                   mainWidth and mainWidth ~= (self.lastWidth or 0) then
                    
                    self.lastHeight = mainHeight
                    self.lastWidth = mainWidth
                    
                    syncFrameSizes()
                end
            end)
        end)
        self:UnregisterEvent("PLAYER_ENTERING_WORLD")
    end
end)

