-- Ticker.lua
-- Displays the top 6 visible timers, sorted by time remaining, no duplicates by zone

if not TimerFrame or not TimerScrollFrame then return end

----------------------------
-- Utility and Formatting --
----------------------------
local function FormatTime(seconds)
    local mins = math.floor(seconds / 60)
    local secs = math.floor(seconds % 60)
    return string.format("%02d:%02d", mins, secs)
end

local zoneColors = {
    ["Azj-Kahet"]         = "|cffA330C9",
    ["Siren Isle"]        = "|cffC79C6E",
    ["Isle of Dorn"]      = "|cff40C7EB",
    ["The Ringing Deeps"] = "|cffC41F3B",
    ["Hallowfall"]        = "|cff00FF96",
    ["Undermine"]         = "|cffffa500",
}

----------------------------
-- Create Ticker Display --
----------------------------
TickerFrame = CreateFrame("Frame", "TickerFrame", TimerFrame)
local TickerText = TickerFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
TickerFrame:SetHeight(20)
TickerFrame:SetPoint("BOTTOM", TimerFrame, "BOTTOM", 0, 5)
TickerFrame:SetPoint("LEFT", TimerFrame, "LEFT", 5, 0)
TickerFrame:SetPoint("RIGHT", TimerFrame, "RIGHT", -5, 0)
TickerFrame:SetClipsChildren(true)
TickerFrame:SetFrameStrata("MEDIUM")
TickerFrame:SetFrameLevel(TimerFrame:GetFrameLevel() + 5)

TickerText:SetFont("Fonts\\FRIZQT__.TTF", 12, "OUTLINE")
TickerText:SetTextColor(1, 1, 0, 1)
TickerText:SetJustifyH("LEFT")
TickerText:SetPoint("LEFT", TickerFrame, "RIGHT", 0, 0)

----------------------------
-- Ticker Text Building --
----------------------------
local function GetTopSortedTimers()
    if not timers then return {} end

    local seenZones = {}
    local top6 = {}

    -- Step 1: get first 6 timers from the list
    local rawTop = {}
    for i = 1, math.min(6, #timers) do
        table.insert(rawTop, timers[i])
    end

    -- Step 2: filter one per zone
    for _, frame in ipairs(rawTop) do
        local rawZone = frame.zoneName or "Unknown"
        local zone = zoneNameRemap and zoneNameRemap[rawZone] or rawZone
        if not seenZones[zone] then
            table.insert(top6, frame)
            seenZones[zone] = true
        end
    end

    -- Step 3: sort the remaining by duration
    table.sort(top6, function(a, b)
        local aTime = a.remainingSeconds or a.duration or 0
        local bTime = b.remainingSeconds or b.duration or 0
        return aTime < bTime
    end)

    return top6
end

_G.GetTopSortedTimers = GetTopSortedTimers


local function GetTickerText()
    local timers = GetTopSortedTimers()
    if #timers == 0 then return "No active timers" end

    local text = ""
    for _, timer in ipairs(timers) do
        local zone = timer.zoneName or "Unknown"
        local shard = timer.shardID or "?"
        local time = timer.remainingSeconds or timer.duration or 0
        local color = zoneColors[zone] or "|cffffffff"
        local timeColor = time < 180 and "|cffff0000" or "|cffffffff"
        text = text .. string.format("%s%s|r (%s): %s%s|r   ", color, zone, shard, timeColor, FormatTime(time))
    end
    return text
end

local function GetTickerData()
    local timers = GetTopSortedTimers()
    local data = {}
    for _, timer in ipairs(timers) do
        local zone = timer.zoneName or "Unknown"
        local shard = timer.shardID or "?"
        local time = timer.remainingSeconds or timer.duration or 0
        table.insert(data, string.format("%s~%s~%d", zone, shard, time))
    end
    return table.concat(data, ";")
end


---------------------------
-- Scrolling Ticker Loop --
---------------------------
local scrollTickerStarted = false
local scrollSpeed = 50
local tickerOffset = 0

---------------------------
-- Initialize Scroll Speed on PLAYER_LOGIN
---------------------------
local function InitializeScrollSpeed()
    if BlackBoxDB and BlackBoxDB.scrollSpeed then
        scrollSpeed = BlackBoxDB.scrollSpeed
    else
        scrollSpeed = 50
    end

    -- If the drawer and its slider exist, update them immediately.
    if SpeedAdjustDrawer and SpeedAdjustDrawer.Slider then
        local slider = SpeedAdjustDrawer.Slider
        slider:SetValue(scrollSpeed)
        local text = _G[slider:GetName() .. "Text"]
        text:SetText("Scroll Speed: " .. math.floor(scrollSpeed))
        text:ClearAllPoints()
        text:SetPoint("TOP", slider, "BOTTOM", 0, -5) -- Position the text below the slider
    end
end

local initFrame = CreateFrame("Frame")
initFrame:RegisterEvent("PLAYER_LOGIN")
initFrame:SetScript("OnEvent", function(self, event, ...)
    InitializeScrollSpeed()
    -- If the drawer and its slider exist, update them immediately.
    if SpeedAdjustDrawer and SpeedAdjustDrawer.Slider then
        local slider = SpeedAdjustDrawer.Slider
        slider:SetValue(scrollSpeed)
        _G[slider:GetName() .. "Text"]:SetText("Scroll Speed: " .. math.floor(scrollSpeed))
    end
end)


local function ScrollTickerText(_, elapsed)
    if not scrollTickerStarted then return end
    local frameWidth = TickerFrame:GetWidth()
    local textWidth = TickerText:GetStringWidth()
    tickerOffset = tickerOffset - (scrollSpeed * elapsed)
    if tickerOffset + textWidth < 0 then tickerOffset = frameWidth end
    TickerText:SetPoint("LEFT", TickerFrame, "LEFT", tickerOffset, 0)
end

TickerFrame:SetScript("OnUpdate", ScrollTickerText)

C_Timer.After(0.2, function()
    if UnitIsGroupLeader("player") or not IsInGroup() then
        TickerText:SetText(GetTickerText())
    else
        TickerText:SetText("Waiting for leader ticker...")
    end
    tickerOffset = TickerFrame:GetWidth()
    scrollTickerStarted = true
end)

-- Update the ticker text periodically
C_Timer.NewTicker(0.1, function()
    if scrollTickerStarted and TickerText then
        if UnitIsGroupLeader("player") or not IsInGroup() then
            -- Show own top 6 timers if the player is the leader or not in a group
            TickerText:SetText(GetTickerText())
        else
            if #syncedTimerData > 0 then
                -- Show synced data from the leader
                local elapsed = GetTime() - syncTimestamp
                local text = ""
                local seenZones = {}
                for _, timer in ipairs(syncedTimerData) do
                    if not seenZones[timer.zone] then
                        seenZones[timer.zone] = true
                        local updated = (timer.remaining - elapsed) % 1097
                        local color = zoneColors[timer.zone] or "|cffffffff"
                        local timeColor = updated < 180 and "|cffff0000" or "|cffffffff"
                        text = text .. string.format("%s%s|r (%s): %s%s|r   ", color, timer.zone, timer.shardID, timeColor, FormatTime(updated))
                        if #seenZones >= 6 then break end
                    end
                end
                TickerText:SetText(text)
            else
                -- Fallback: Show own top 6 timers if no synced data is available
                TickerText:SetText(GetTickerText())
            end
        end
    end
end)

---------------------------
-- Sync and Messaging    --
---------------------------
local TICKER_PREFIX = "RUFFTICKER"
C_ChatInfo.RegisterAddonMessagePrefix(TICKER_PREFIX)

local tickerEventFrame = CreateFrame("Frame")
tickerEventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
tickerEventFrame:RegisterEvent("CHAT_MSG_ADDON")

tickerEventFrame:SetScript("OnEvent", function(_, event, arg1, arg2, arg3, ...)
    if event == "GROUP_ROSTER_UPDATE" then
        -- Check if the player is in a group and not the leader
        if IsInGroup() and not UnitIsGroupLeader("player") and not IsInInstance() then
            local channel = IsInRaid() and "RAID" or (IsInGroup(LE_PARTY_CATEGORY_HOME) and "PARTY" or nil)
            if channel then
                C_ChatInfo.SendAddonMessage(TICKER_PREFIX, "TICKER_REQUEST", channel)
            end
        elseif IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
            -- Handle instance groups separately
            syncedTimerData = {}
            syncTimestamp = nil
        else
            -- If the player is no longer in a group or is the leader, reset synced data
            syncedTimerData = {}
            syncTimestamp = nil
        end
    elseif event == "CHAT_MSG_ADDON" then
        local prefix, msg, channel, sender = arg1, arg2, arg3, ...
        if prefix ~= TICKER_PREFIX then return end

        if msg == "TICKER_REQUEST" then
            if UnitIsGroupLeader("player") then
                local data = GetTickerData()
                C_ChatInfo.SendAddonMessage(TICKER_PREFIX, "TICKER_REPLY:" .. data, channel)
            end
        elseif msg:sub(1,13) == "TICKER_REPLY:" then
            if IsInGroup() and not UnitIsGroupLeader("player") then
                syncTimestamp = GetTime()
                syncedTimerData = {}
                local dataString = msg:sub(14)
                for entry in string.gmatch(dataString, "([^;]+)") do
                    local zone, shard, remaining = entry:match("([^~]+)~([^~]+)~(%d+)")
                    if zone and shard and remaining then
                        table.insert(syncedTimerData, {
                            zone = zone,
                            shardID = shard,
                            remaining = tonumber(remaining)
                        })
                    end
                end
            end
        end
    end
end)

C_Timer.NewTicker(3, function()
    if IsInGroup() and not UnitIsGroupLeader("player") and not IsInInstance() and not IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
        local channel = IsInRaid() and "RAID" or (IsInGroup() and "PARTY" or nil)
        if channel then
            C_ChatInfo.SendAddonMessage(TICKER_PREFIX, "TICKER_REQUEST", channel)
        end
    end
end)

---------------------------
-- Tooltip Info          --
---------------------------
local flashingColor = "|cff00ff00" -- Start with green
local isGreen = true

C_Timer.NewTicker(0.5, function()
    if isGreen then
        flashingColor = "|cffffff00" -- Yellow
    else
        flashingColor = "|cff00ff00" -- Green
    end
    isGreen = not isGreen
end)

local tooltipTicker -- Declare a variable to store the tooltip update ticker

local function UpdateTickerTooltip()
    GameTooltip:SetOwner(TickerFrame, "ANCHOR_TOP")
    GameTooltip:ClearLines()

    if UnitIsGroupLeader("player") or not IsInGroup() then
        GameTooltip:AddLine("Rotation = Your Top 6 Timers. |cffffff00New Timers Are Added To Top.|r")
        GameTooltip:AddLine("Your Top 6 Timers Are Being Displayed For Everyone In The Group", 1, 1, 0)
    else
        if #syncedTimerData > 0 then
            GameTooltip:AddLine("Rotation\n(From Leader):")
        else
            GameTooltip:AddLine("Waiting for leader ticker...", 1, 0, 0)
        end
    end

    -- Add the right-click instruction
    GameTooltip:AddLine("Right-click to adjust scroll speed", 0.8, 0.8, 0.8)
    -- Add the left-click instruction with flashing "NEW"
    GameTooltip:AddLine("Left-click to open/close rotation window. " .. flashingColor .. "<-------NEW|r", 0.8, 0.8, 0.8)
    GameTooltip:Show()

    -- Start a ticker to refresh the tooltip periodically
    if not tooltipTicker then
        tooltipTicker = C_Timer.NewTicker(0.5, function()
            if GameTooltip:IsOwned(TickerFrame) then
                UpdateTickerTooltip()
            else
                tooltipTicker:Cancel()
                tooltipTicker = nil
            end
        end)
    end
end

TickerFrame:SetScript("OnEnter", UpdateTickerTooltip)
TickerFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)

--------------------------------------------------
-- Functions for Rotation Drawer (Left-Click)   --
--------------------------------------------------

-- Save the position and visibility state of the RotationDrawer
local function SaveRotationDrawerState()
    if not BlackBoxDB then BlackBoxDB = {} end
    if not RotationDrawer then return end

    local point, relativeTo, relativePoint, xOfs, yOfs = RotationDrawer:GetPoint()
    BlackBoxDB.RotationDrawerState = {
        isVisible = RotationDrawer:IsShown(),
        point = point,
        relativePoint = relativePoint,
        xOfs = xOfs,
        yOfs = yOfs,
    }
end

-- Restore the position and visibility state of the RotationDrawer
local function RestoreRotationDrawerState()
    if not BlackBoxDB or not BlackBoxDB.RotationDrawerState then return end
    local state = BlackBoxDB.RotationDrawerState

    if not RotationDrawer then
        CreateRotationDrawer()
    end

    if state.point and state.relativePoint and state.xOfs and state.yOfs then
        RotationDrawer:ClearAllPoints()
        RotationDrawer:SetPoint(state.point, UIParent, state.relativePoint, state.xOfs, state.yOfs)
    end

    if state.isVisible then
        RotationDrawer:Show()
    else
        RotationDrawer:Hide()
    end
end

--------------------------------------------------
-- Create RotationDrawer with Always-Movable Feature,
-- Reduced Scroll Bar Height, and Smaller Close Button
--------------------------------------------------
local function CreateRotationDrawer()
    if not RotationDrawer then
        RotationDrawer = CreateFrame("Frame", "RotationDrawer", UIParent, "BackdropTemplate")
        RotationDrawer:SetSize(260, 100) -- Overall dimensions of the rotation window
        RotationDrawer:SetBackdrop({
            bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
            edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
            tile = true,
            tileSize = 16,
            edgeSize = 16,
            insets = { left = 4, right = 4, top = 4, bottom = 4 }
        })
        RotationDrawer:SetBackdropColor(0, 0, 0, 0.8)
        RotationDrawer:SetBackdropBorderColor(1, 0.84, 0, 1) -- Gold border color (R, G, B, Alpha)
        RotationDrawer:Hide()

        -- Always movable
        RotationDrawer:EnableMouse(true)
        RotationDrawer:SetMovable(true)
        RotationDrawer:RegisterForDrag("LeftButton")
        RotationDrawer:SetScript("OnDragStart", function(self)
            self:StartMoving()
        end)
        RotationDrawer:SetScript("OnDragStop", function(self)
            self:StopMovingOrSizing()
            SaveRotationDrawerState()
        end)

        -- Add a title to the top-left of the RotationDrawer
        local title = RotationDrawer:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        title:SetPoint("TOPLEFT", RotationDrawer, "TOPLEFT", 5, -5)
        title:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE")
        title:SetTextColor(1, 0.84, 0, 1) -- Gold color (R, G, B, Alpha)
        title:SetText("Rotation")
        RotationDrawer.title = title

        -- Ensure the frame stays within the screen boundaries
        RotationDrawer:SetClampedToScreen(true)

        -- Add a close button ("X") at the top-right and reduce its size
        RotationDrawer.CloseButton = CreateFrame("Button", nil, RotationDrawer, "UIPanelCloseButton")
        RotationDrawer.CloseButton:SetSize(16, 16) -- Reduced size
        RotationDrawer.CloseButton:SetPoint("TOPRIGHT", RotationDrawer, "TOPRIGHT", -5, -5)
        RotationDrawer.CloseButton:SetScript("OnClick", function()
            RotationDrawer:Hide()
            SaveRotationDrawerState()
        end)

        -- Add a scrollable text area for rotation info
        -- The scroll frame is named so we can adjust its scroll bar.
        RotationDrawer.ScrollFrame = CreateFrame("ScrollFrame", "RotationDrawerScrollFrame", RotationDrawer, "UIPanelScrollFrameTemplate")
        -- Adjust the scroll frame to leave extra space at the top and bottom for a smaller scrollbar
        RotationDrawer.ScrollFrame:SetPoint("TOPLEFT", 10, -15)
        RotationDrawer.ScrollFrame:SetPoint("BOTTOMRIGHT", -30, 10)

        RotationDrawer.Content = CreateFrame("Frame", nil, RotationDrawer.ScrollFrame)
        RotationDrawer.Content:SetSize(220, 100) -- Content size
        RotationDrawer.ScrollFrame:SetScrollChild(RotationDrawer.Content)

        RotationDrawer.Text = RotationDrawer.Content:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        RotationDrawer.Text:SetPoint("TOPLEFT")
        RotationDrawer.Text:SetWidth(220)
        RotationDrawer.Text:SetJustifyH("LEFT")
        RotationDrawer.Text:SetJustifyV("TOP")

        -- Adjust the scroll bar of the scroll frame so it doesn't span the full height.
        local scrollBar = _G["RotationDrawerScrollFrameScrollBar"]
        if scrollBar then
            scrollBar:SetWidth(12) -- Reduce the width if desired
            scrollBar:ClearAllPoints()
            -- Anchor the scrollbar with some vertical padding (here 20 pixels from top and bottom)
            scrollBar:SetPoint("TOPRIGHT", RotationDrawer, "TOPRIGHT", -7, -38)
            scrollBar:SetPoint("BOTTOMRIGHT", RotationDrawer, "BOTTOMRIGHT", -7, 20)
        end
    end
end

--------------------------------------------------
-- Update RotationDrawer Content in Real-Time
--------------------------------------------------
local function UpdateRotationDrawer()
    if not RotationDrawer then return end

    local timers
    if UnitIsGroupLeader("player") or not IsInGroup() then
        -- Use own timers if the player is the leader or not in a group
        timers = GetTopSortedTimers()
    else
        if #syncedTimerData > 0 then
            -- Use synced data from the leader
            timers = {}
            local elapsed = GetTime() - syncTimestamp
            for _, timer in ipairs(syncedTimerData) do
                local updatedTime = (timer.remaining - elapsed) % 1097
                table.insert(timers, {
                    zoneName = timer.zone,
                    shardID = timer.shardID,
                    remainingSeconds = updatedTime
                })
            end
        else
            -- Fallback: Use own timers if no synced data is available
            timers = GetTopSortedTimers()
        end
    end

    if #timers == 0 then
        RotationDrawer.Text:SetText("No active timers")
    else
        local text = ""
        for _, timer in ipairs(timers) do
            local zone = timer.zoneName or "Unknown"
            local shard = timer.shardID or "?"
            local time = timer.remainingSeconds or timer.duration or 0
            local color = zoneColors[zone] or "|cffffffff"
            local timeColor = (time < 180) and "|cffff0000" or "|cffffffff"
            text = text .. string.format("%s%s|r (%s): %s%s|r\n", color, zone, shard, timeColor, FormatTime(time))
        end
        RotationDrawer.Text:SetText(text)
    end
end

--------------------------------------------------
-- Toggle RotationDrawer with Animation
--------------------------------------------------
local function ToggleRotationDrawer()
    if not RotationDrawer then
        CreateRotationDrawer()
    end

    if RotationDrawer:IsShown() then
        local ag = RotationDrawer:CreateAnimationGroup()
        local slide = ag:CreateAnimation("Translation")
        slide:SetOffset(-300, 0) -- Slide left to hide
        slide:SetDuration(0.3)
        slide:SetSmoothing("IN_OUT")
        ag:SetScript("OnFinished", function()
            RotationDrawer:Hide()
            SaveRotationDrawerState()
        end)
        ag:Play()
    else
        RotationDrawer:Show()
        RotationDrawer:ClearAllPoints()
        RotationDrawer:SetPoint("TOPLEFT", TimerFrame, "TOPRIGHT", 0, 0)
        -- Update title with ShardID information
        if BlackBoxDB and BlackBoxDB.shardID then
            RotationDrawer.title:SetText("Rotation - ShardID: " .. BlackBoxDB.shardID)
        else
            RotationDrawer.title:SetText("Rotation - ShardID: N/A")
        end
        local ag = RotationDrawer:CreateAnimationGroup()
        local slide = ag:CreateAnimation("Translation")
        slide:SetOffset(300, 0) -- Slide right to show
        slide:SetDuration(0.3)
        slide:SetSmoothing("IN_OUT")
        ag:SetScript("OnFinished", SaveRotationDrawerState)
        ag:Play()
    end
end

--------------------------------------------------
-- Combined OnMouseDown Handler for TickerFrame
--------------------------------------------------
TickerFrame:SetScript("OnMouseDown", function(self, button)
    if button == "RightButton" then
        -- Right-click: Toggle SpeedAdjustDrawer (Scroll Speed Adjustment)
        if not SpeedAdjustDrawer then
            SpeedAdjustDrawer = CreateFrame("Frame", "SpeedAdjustDrawer", UIParent, "BackdropTemplate")
            SpeedAdjustDrawer:SetSize(300, 40)  -- Drawer dimensions

            local faction = UnitFactionGroup("player")
            local bgColor = (faction == "Alliance") and {0, 0, 1, 0.8} or {1, 0, 0, 0.8}

            SpeedAdjustDrawer:SetBackdrop({
                bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
                edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
                tile = true,
                tileSize = 16,
                edgeSize = 16,
                insets = { left = 4, right = 4, top = 4, bottom = 4 }
            })
            SpeedAdjustDrawer:SetBackdropColor(unpack(bgColor))
            SpeedAdjustDrawer:SetBackdropBorderColor(1, 0.84, 0, 1)
            SpeedAdjustDrawer:Hide()

            SpeedAdjustDrawer.Slider = CreateFrame("Slider", "SpeedSlider", SpeedAdjustDrawer, "OptionsSliderTemplate")
            local slider = SpeedAdjustDrawer.Slider
            slider:SetSize(280, 20)
            slider:SetPoint("CENTER", SpeedAdjustDrawer, "CENTER", 0, 10)
            slider:SetMinMaxValues(10, 200)
            local initialValue = (BlackBoxDB and BlackBoxDB.scrollSpeed) or scrollSpeed
            slider:SetValue(initialValue)
            slider:SetValueStep(5)
            slider:SetScript("OnValueChanged", function(self, value)
                value = math.floor(value)
                scrollSpeed = value
                if BlackBoxDB then
                    BlackBoxDB.scrollSpeed = value
                end
                local text = _G[self:GetName() .. "Text"]
                text:SetText("Scroll Speed: " .. value)
                text:ClearAllPoints()
                text:SetPoint("TOP", self, "BOTTOM", 0, -5)
            end)
            _G[slider:GetName() .. "Low"]:SetText("10")
            _G[slider:GetName() .. "High"]:SetText("200")
            _G[slider:GetName() .. "Text"]:SetText("Scroll Speed: " .. initialValue)
            slider:SetFrameLevel(SpeedAdjustDrawer:GetFrameLevel() + 1)
        end

        if not SpeedAdjustOverlay then
            SpeedAdjustOverlay = CreateFrame("Frame", nil, UIParent)
            SpeedAdjustOverlay:SetAllPoints(UIParent)
            SpeedAdjustOverlay:SetFrameStrata("FULLSCREEN_DIALOG")
            SpeedAdjustOverlay:EnableMouse(true)
            SpeedAdjustOverlay:Hide()
            SpeedAdjustOverlay:SetScript("OnMouseDown", function(self)
                local x, y = GetCursorPosition()
                local scale = UIParent:GetEffectiveScale()
                x, y = x / scale, y / scale
                local left = SpeedAdjustDrawer:GetLeft() or 0
                local right = SpeedAdjustDrawer:GetRight() or 0
                local bottom = SpeedAdjustDrawer:GetBottom() or 0
                local top = SpeedAdjustDrawer:GetTop() or 0
                if (x < left or x > right or y < bottom or y > top) then
                    local ag = SpeedAdjustDrawer:CreateAnimationGroup()
                    local slide = ag:CreateAnimation("Translation")
                    slide:SetOffset(0, 100)
                    slide:SetDuration(0.3)
                    slide:SetSmoothing("IN_OUT")
                    ag:SetScript("OnFinished", function()
                        if SpeedAdjustDrawer.Slider then
                            local currentValue = SpeedAdjustDrawer.Slider:GetValue()
                            if BlackBoxDB then
                                BlackBoxDB.scrollSpeed = currentValue
                            end
                            scrollSpeed = currentValue
                        end
                        SpeedAdjustDrawer:Hide()
                        SpeedAdjustOverlay:Hide()
                    end)
                    ag:Play()
                end
            end)
        end

        local cursorX, cursorY = GetCursorPosition()
        local uiScale = UIParent:GetEffectiveScale()
        cursorX, cursorY = cursorX / uiScale, cursorY / uiScale
        local screenHeight = UIParent:GetHeight()
        SpeedAdjustDrawer:ClearAllPoints()
        if (cursorY < screenHeight * 0.2) then
            SpeedAdjustDrawer:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", cursorX - 150, cursorY + 10)
        else
            SpeedAdjustDrawer:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", cursorX - 150, cursorY - 10)
        end
        SpeedAdjustDrawer:SetFrameStrata("FULLSCREEN_DIALOG")
        SpeedAdjustOverlay:SetFrameStrata("FULLSCREEN_DIALOG")
        SpeedAdjustDrawer:SetFrameLevel(SpeedAdjustOverlay:GetFrameLevel() + 5)

        if SpeedAdjustDrawer:IsShown() then
            local ag = SpeedAdjustDrawer:CreateAnimationGroup()
            local slide = ag:CreateAnimation("Translation")
            slide:SetOffset(0, 100)
            slide:SetDuration(0.3)
            slide:SetSmoothing("IN_OUT")
            ag:SetScript("OnFinished", function()
                if SpeedAdjustDrawer.Slider then
                    local currentValue = SpeedAdjustDrawer.Slider:GetValue()
                    if BlackBoxDB then
                        BlackBoxDB.scrollSpeed = currentValue
                    end
                    scrollSpeed = currentValue
                end
                SpeedAdjustDrawer:Hide()
                SpeedAdjustOverlay:Hide()
            end)
            ag:Play()
        else
            SpeedAdjustDrawer:Show()
            SpeedAdjustOverlay:Show()
            local ag = SpeedAdjustDrawer:CreateAnimationGroup()
            local slide = ag:CreateAnimation("Translation")
            slide:SetOffset(0, -100)
            slide:SetDuration(0.3)
            slide:SetSmoothing("IN_OUT")
            ag:Play()
        end

    elseif button == "LeftButton" then
        -- Left-click: Toggle RotationDrawer
        ToggleRotationDrawer()
    end
end)

--------------------------------------------------
-- Update RotationDrawer Content in Real-Time
--------------------------------------------------
C_Timer.NewTicker(0.1, function()
    if RotationDrawer and RotationDrawer:IsShown() then
        UpdateRotationDrawer()
    end
end)

-- Save the position and visibility state of the RotationDrawer
local function SaveRotationDrawerState()
    if not BlackBoxDB then BlackBoxDB = {} end
    if not RotationDrawer then return end

    local point, relativeTo, relativePoint, xOfs, yOfs = RotationDrawer:GetPoint()
    BlackBoxDB.RotationDrawerState = {
        isVisible = RotationDrawer:IsShown(),
        point = point,
        relativePoint = relativePoint,
        xOfs = xOfs,
        yOfs = yOfs,
    }
end

-- Restore the position and visibility state of the RotationDrawer
local function RestoreRotationDrawerState()
    if not BlackBoxDB or not BlackBoxDB.RotationDrawerState then return end
    local state = BlackBoxDB.RotationDrawerState

    if not RotationDrawer then
        CreateRotationDrawer()
    end

    if state.point and state.relativePoint and state.xOfs and state.yOfs then
        RotationDrawer:ClearAllPoints()
        RotationDrawer:SetPoint(state.point, UIParent, state.relativePoint, state.xOfs, state.yOfs)
    end

    if state.isVisible then
        RotationDrawer:Show()
    else
        RotationDrawer:Hide()
    end
end

-- Hook into the RotationDrawer's movement and toggling to save its state
if not RotationDrawer then
    CreateRotationDrawer()
end

RotationDrawer:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
    SaveRotationDrawerState()
end)

-- Restore the state on PLAYER_LOGIN
local initFrame = CreateFrame("Frame")
initFrame:RegisterEvent("PLAYER_LOGIN")
initFrame:SetScript("OnEvent", function(self, event, ...)
    RestoreRotationDrawerState()
end)

-- Add a ticker to update the RotationDrawer title with current ShardID in real time
C_Timer.NewTicker(1, function()
    if RotationDrawer and RotationDrawer:IsShown() then
        if BlackBoxDB and BlackBoxDB.shardID then
            RotationDrawer.title:SetText("Rotation - Your Current ShardID: " .. BlackBoxDB.shardID)
        else
            RotationDrawer.title:SetText("Rotation - ShardID: N/A")
        end
    end
end)
