-- Start Up
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)

if not MDungeonTeleports then
    MDungeonTeleports = {}
end

if not MDungeonTeleports.KeyTrackerPos then
    MDungeonTeleports.KeyTrackerPos = {x = 442, y = -429}
end

-- Save Function
local function SaveKeyTrackerPos()
    local DungeonFrame = PVEFrame
    if DungeonFrame then
        local frameScale = KeyTrackerPlayer:GetScale()
        local parentScale = DungeonFrame:GetScale()

        local keyLeft = KeyTrackerPlayer:GetLeft() * frameScale
        local keyTop = KeyTrackerPlayer:GetTop() * frameScale
        local dungeonLeft = DungeonFrame:GetLeft() * parentScale
        local dungeonTop = DungeonFrame:GetTop() * parentScale

        local offsetX = (keyLeft - dungeonLeft) / parentScale
        local offsetY = (keyTop - dungeonTop) / parentScale

        MDungeonTeleports.KeyTrackerPos = {x = offsetX, y = offsetY}
    end
end

-- Load Function
local function LoadKeyTrackerPos()
    local DungeonFrame = PVEFrame
    if DungeonFrame and MDungeonTeleports.KeyTrackerPos then
        local pos = MDungeonTeleports.KeyTrackerPos

        local frameScale = KeyTrackerPlayer:GetScale()
        local parentScale = DungeonFrame:GetScale()

        local adjustedX = pos.x * parentScale / frameScale
        local adjustedY = pos.y * parentScale / frameScale

        KeyTrackerPlayer:ClearAllPoints()
        KeyTrackerPlayer:SetPoint("TOPLEFT", DungeonFrame, "TOPLEFT", adjustedX, adjustedY)
    end
end

-- Reattach Function
local function ReattachKeyTracker()
    local DungeonFrame = PVEFrame
    if DungeonFrame and MDungeonTeleports.KeyTrackerPos then
        local pos = MDungeonTeleports.KeyTrackerPos

        local frameScale = KeyTrackerPlayer:GetScale()
        local parentScale = DungeonFrame:GetScale()

        local adjustedX = pos.x * parentScale / frameScale
        local adjustedY = pos.y * parentScale / frameScale

        KeyTrackerPlayer:ClearAllPoints()
        KeyTrackerPlayer:SetPoint("TOPLEFT", DungeonFrame, "TOPLEFT", adjustedX, adjustedY)
    end
end

local function GetDungeonInfo(mapID)
    for _, dungeon in ipairs(KeyTrackerIcons) do
        if dungeon.mapID == mapID then
            return dungeon.icon, dungeon.short, dungeon.spellID
        end
    end
    return nil, "Unknown", nil
end


-- MARK: Visibility Toggle
function KeyFrame_UpdateVisibility(show)
    local KeyF = _G["KeyTrackerPlayer"]
    if KeyF then
        KeyF:SetShown(show)
    end
end

-- MARK: Save Function on Close
local function OnPVEFrameClose()
    SaveKeyTrackerPos()
end

-- MARK: Login Start Up
local function OnPlayerLogin()
    LoadKeyTrackerPos()
end

local loginFrame = CreateFrame("Frame")
loginFrame:RegisterEvent("PLAYER_LOGIN")
loginFrame:SetScript(
    "OnEvent",
    function(self, event)
        if event == "PLAYER_LOGIN" then
            OnPlayerLogin()
        end
    end
)

-- MARK: Key Tracker Player
local KeyTrackerPlayer = CreateFrame("Frame", "KeyTrackerPlayer", PVEFrame, "BackdropTemplate")
KeyTrackerPlayer:SetPoint("TOPRIGHT", PVEFrame, "BOTTOMRIGHT", 0, -1)
KeyTrackerPlayer:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
KeyTrackerPlayer:SetSize(120, 30)
KeyTrackerPlayer:EnableMouse(true)
KeyTrackerPlayer:SetMovable(true)
KeyTrackerPlayer:RegisterForDrag("LeftButton")
KeyTrackerPlayer:SetClampedToScreen(true)
KeyTrackerPlayer:Show()

KeyTrackerPlayer.isBeingDragged = false

KeyTrackerPlayer:SetScript(
    "OnDragStart",
    function(self)
        self.isBeingDragged = true
        self:StartMoving()
    end
)

KeyTrackerPlayer:SetScript(
    "OnDragStop",
    function(self)
        if self.isBeingDragged then
            self:StopMovingOrSizing()
            SaveKeyTrackerPos()
            self.isBeingDragged = false
            ReattachKeyTracker()
        end
    end
)

-- Function to create spell cast button
local function CreateTeleportButton(parent)
    local button = CreateFrame("Button", nil, parent, "SecureActionButtonTemplate")
    button:RegisterForClicks("AnyDown", "AnyUp")


    button:SetAttribute("type", "spell")
    button:SetAttribute("spell", spellID)
    button.spellID = spellID

    button.icon = button:CreateTexture(nil, "ARTWORK")
    button.icon:SetSize(24, 24)
    button.icon:SetPoint("CENTER")

    button.highlight = button:CreateTexture(nil, "HIGHLIGHT")
    button.highlight:SetSize(24, 24)
    button.highlight:SetPoint("CENTER")
    button.highlight:SetColorTexture(1, 1, 1, 0.2)

    button.border = button:CreateTexture(nil, "OVERLAY")
    button.border:SetSize(24, 24)
    button.border:SetPoint("CENTER")
    button.border:SetTexture("Interface/AddOns/MDungeonTeleports/media/ui/ui_default/button_border.blp")

    button:SetScript(
        "OnEnter",
        function(self)
            if self.spellID then
                GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
                GameTooltip:Show()
            end
        end
    )

    button:SetScript(
        "OnLeave",
        function(self)
            GameTooltip:Hide()
        end
    )

    button:RegisterForClicks("AnyUp", "AnyDown")

    return button
end

-- My Keystone Entry
local MyCurrentKeystone = {}

MyCurrentKeystone.icon = KeyTrackerPlayer:CreateTexture(nil, "ARTWORK")
MyCurrentKeystone.icon:SetSize(24, 24)
MyCurrentKeystone.icon:SetPoint("TOPLEFT", KeyTrackerPlayer, "TOPLEFT", 3, -3)

MyCurrentKeystone.teleportButton = CreateTeleportButton(KeyTrackerPlayer)
MyCurrentKeystone.teleportButton:SetSize(24, 24)
MyCurrentKeystone.teleportButton:SetPoint("LEFT", KeyTrackerPlayer, "LEFT", 3, 0)

MyCurrentKeystone.keystoneLevel = KeyTrackerPlayer:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
MyCurrentKeystone.keystoneLevel:SetPoint("CENTER", MyCurrentKeystone.icon, "CENTER", 0, 0)
MyCurrentKeystone.keystoneLevel:SetFont("Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf", 14, "OUTLINE")
MyCurrentKeystone.keystoneLevel:SetText("")

MyCurrentKeystone.dungeonName = KeyTrackerPlayer:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
MyCurrentKeystone.dungeonName:SetPoint("LEFT", MyCurrentKeystone.icon, "RIGHT", 3, 0)
MyCurrentKeystone.dungeonName:SetFont("Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf", 11, "OUTLINE")
MyCurrentKeystone.dungeonName:SetText("")
MyCurrentKeystone.dungeonName:SetJustifyH("LEFT")

MyCurrentKeystone.playerName = KeyTrackerPlayer:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
MyCurrentKeystone.playerName:SetPoint("TOPLEFT", MyCurrentKeystone.dungeonName, "BOTTOMLEFT", 0, -1)
MyCurrentKeystone.playerName:SetFont("Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf", 9, "OUTLINE")
MyCurrentKeystone.playerName:SetText("")
MyCurrentKeystone.playerName:SetJustifyH("LEFT")

-- MARK: Party Keystone Frame
local KeyTrackerParty = CreateFrame("Frame", "KeystoneUIFrame", KeyTrackerPlayer, "BackdropTemplate")
KeyTrackerParty:SetSize(120, 128)
KeyTrackerParty:SetPoint("TOP", KeyTrackerPlayer, "TOP", 0, -32)
KeyTrackerParty:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
KeyTrackerParty:SetMovable(false)
KeyTrackerParty:EnableMouse(false)
KeyTrackerParty:RegisterForDrag("LeftButton")
KeyTrackerParty:SetScript("OnDragStart", KeyTrackerParty.StartMoving)
KeyTrackerParty:SetScript("OnDragStop", KeyTrackerParty.StopMovingOrSizing)

-- Table to store key icons and labels
local keystoneEntries = {}

local function CreateKeystoneEntry(index)
    local entry = {}

    -- Dungeon icon
    entry.icon = KeyTrackerParty:CreateTexture(nil, "ARTWORK")
    entry.icon:SetSize(26, 26)
    entry.icon:SetPoint("TOPLEFT", KeyTrackerParty, "TOPLEFT", 5, 25 - (index * 30))

    -- Create teleport button 
    entry.teleportButton = CreateTeleportButton(KeyTrackerParty)
    entry.teleportButton:SetSize(26, 26)
    entry.teleportButton:SetPoint("TOPLEFT", KeyTrackerParty, "TOPLEFT", 5, 25 - (index * 30))

    -- Keystone level
    entry.keystoneLevel = KeyTrackerParty:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    entry.keystoneLevel:SetPoint("CENTER", entry.icon, "CENTER", 0, 0)
    entry.keystoneLevel:SetFont("Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf", 14, "OUTLINE")
    entry.keystoneLevel:SetText("")

    -- Dungeon name
    entry.dungeonName = KeyTrackerParty:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    entry.dungeonName:SetPoint("LEFT", entry.icon, "RIGHT", 3, 6)
    entry.dungeonName:SetFont("Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf", 11, "OUTLINE")
    entry.dungeonName:SetText("")
    entry.dungeonName:SetJustifyH("LEFT")

    -- Player name
    entry.playerName = KeyTrackerParty:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    entry.playerName:SetPoint("TOPLEFT", entry.dungeonName, "BOTTOMLEFT", 0, -1)
    entry.playerName:SetFont("Interface/AddOns/MDungeonTeleports/media/fonts/expressway.ttf", 9, "OUTLINE")
    entry.playerName:SetText("")
    entry.playerName:SetJustifyH("LEFT")

    keystoneEntries[index] = entry
end

-- Create slots for 5 players
for i = 1, 5 do
    CreateKeystoneEntry(i)
end

local function UpdateMyKeystone()
    if InCombatLockdown() then return end
    local myKeystoneInfo = openRaidLib.GetKeystoneInfo("player")
    if myKeystoneInfo then
        local dungeonName = C_ChallengeMode.GetMapUIInfo(myKeystoneInfo.challengeMapID) or "No Key"
        local dungeonIconID, dungeonShortName, spellID = GetDungeonInfo(myKeystoneInfo.challengeMapID)

        local _, class = UnitClass("player")
        local classColor = RAID_CLASS_COLORS[class] and RAID_CLASS_COLORS[class].colorStr or "FFFFFFFF"

        local keystoneLevelFull = myKeystoneInfo.level > 0 and "+" .. myKeystoneInfo.level or ""

        MyCurrentKeystone.icon:SetTexture(dungeonIconID or "Interface\\Icons\\misc_rnrredxbutton")
        MyCurrentKeystone.dungeonName:SetText(dungeonShortName)
        MyCurrentKeystone.playerName:SetText("|c" .. classColor .. "" .. "|r")
        MyCurrentKeystone.keystoneLevel:SetText(keystoneLevelFull)

        if spellID then
            MyCurrentKeystone.teleportButton:SetAttribute("type", "spell")
            MyCurrentKeystone.teleportButton:SetAttribute("spell", spellID)
            MyCurrentKeystone.teleportButton.spellID = spellID
            MyCurrentKeystone.teleportButton.dungeonFullName = dungeonName
        else
            MyCurrentKeystone.teleportButton:SetAttribute("type", nil)
            MyCurrentKeystone.teleportButton:SetAttribute("spell", nil)
            MyCurrentKeystone.teleportButton.spellID = nil
            MyCurrentKeystone.teleportButton.dungeonFullName = nil
        end
    end
end

local function UpdatePartyKeystones()
    if InCombatLockdown() then return end
    local allKeystoneInfo = openRaidLib.GetAllKeystonesInfo()
    local index = 1

    -- Clear existing entries
    for i = 1, #keystoneEntries do
        keystoneEntries[i].icon:SetTexture(nil)
        keystoneEntries[i].keystoneLevel:SetText("")
        keystoneEntries[i].dungeonName:SetText("")
        keystoneEntries[i].playerName:SetText("")
        keystoneEntries[i].teleportButton:SetAttribute("type", nil)
        keystoneEntries[i].teleportButton:SetAttribute("spell", nil)
        keystoneEntries[i].teleportButton.spellID = nil
        keystoneEntries[i].teleportButton.dungeonFullName = nil
    end

    for i = 1, GetNumGroupMembers() - 1 do 
        local unitId = "party" .. i
        local unitName, realm = UnitName(unitId)

        if unitName then
            if realm and realm ~= "" then
                unitName = unitName .. "-" .. realm
            end

            local playerNameWithoutRealm = unitName

            if playerNameWithoutRealm then
                if realm and realm ~= "" then
                playerNameWithoutRealm = unitName:match("([^%-]+)")
                end
            end

            local keystoneInfo = allKeystoneInfo[unitName]

            if keystoneInfo then
                if keystoneEntries[index] then
                    local dungeonName = C_ChallengeMode.GetMapUIInfo(keystoneInfo.challengeMapID) or "No Key"
                    local dungeonIconID, dungeonShortName, spellID = GetDungeonInfo(keystoneInfo.challengeMapID)

                    local _, class = UnitClass(unitId)
                    local classColor = RAID_CLASS_COLORS[class] and RAID_CLASS_COLORS[class].colorStr or "FFFFFFFF"

                    local keystoneLevelFullParty = keystoneInfo.level > 0 and "+" .. keystoneInfo.level or ""

                    keystoneEntries[index].icon:SetTexture(dungeonIconID or "Interface\\Icons\\misc_rnrredxbutton")
                    keystoneEntries[index].dungeonName:SetText(dungeonShortName)
                    keystoneEntries[index].playerName:SetText("|c" .. classColor .. playerNameWithoutRealm .. "|r")
                    keystoneEntries[index].keystoneLevel:SetText(keystoneLevelFullParty)

                    if spellID then
                        keystoneEntries[index].teleportButton:SetAttribute("type", "spell")
                        keystoneEntries[index].teleportButton:SetAttribute("spell", spellID)
                        keystoneEntries[index].teleportButton.spellID = spellID
                        keystoneEntries[index].teleportButton.dungeonFullName = dungeonName
                        keystoneEntries[index].teleportButton.border:SetSize(26, 26)
                        keystoneEntries[index].teleportButton:Show()
                    else
                        keystoneEntries[index].teleportButton:SetAttribute("type", nil)
                        keystoneEntries[index].teleportButton:SetAttribute("spell", nil)
                        keystoneEntries[index].teleportButton.spellID = nil
                        keystoneEntries[index].teleportButton.dungeonFullName = nil
                        keystoneEntries[index].teleportButton.border:SetSize(26, 26)
                        keystoneEntries[index].teleportButton:Hide()
                    end

                    index = index + 1
                end
            end
        end
    end

    -- Clear any unused entries
    for i = index, #keystoneEntries do
        keystoneEntries[i].icon:SetTexture(nil)
        keystoneEntries[i].keystoneLevel:SetText("")
        keystoneEntries[i].dungeonName:SetText("")
        keystoneEntries[i].playerName:SetText("")
        keystoneEntries[i].teleportButton:SetAttribute("type", nil)
        keystoneEntries[i].teleportButton:SetAttribute("spell", nil)
        keystoneEntries[i].teleportButton.spellID = nil
        keystoneEntries[i].teleportButton.dungeonFullName = nil
        keystoneEntries[i].teleportButton:Hide()
    end

    -- Adjust the display height based on the number of keys
    local totalKeys = index - 1
    if totalKeys == 0 or (IsInRaid() and not (GetNumGroupMembers() <= 5)) then
        KeyTrackerParty:SetHeight(0)
        KeyTrackerParty:Hide()
    else
        local heights = {36, 67, 98, 127}  -- Predefined heights for 1-4 keys
        KeyTrackerParty:SetHeight(heights[totalKeys] or 127)
        KeyTrackerParty:Show()
    end
end

local function RequestPartyKeystones()
    openRaidLib.RequestKeystoneDataFromParty()
    if not RequestKeystoneTimer then
        RequestKeystoneTimer = C_Timer.NewTimer(2, function()
            UpdatePartyKeystones()
            RequestKeystoneTimer = nil
        end)
    end
end

local function RequestPersonalKeystone()
    openRaidLib.RequestKeystoneDataFromParty()
    if not RequestMyKeystoneTimer then
        RequestMyKeystoneTimer = C_Timer.NewTimer(2, function()
            UpdateMyKeystone()
            RequestMyKeystoneTimer = nil
        end)
    end
end

-- MARK: !keys button
local PartyChatButton = CreateFrame("Button", nil, KeyTrackerPlayer, "SecureActionButtonTemplate")
PartyChatButton:SetSize(24, 24)
PartyChatButton:SetPoint("RIGHT", KeyTrackerPlayer, "RIGHT", -5, 0)

PartyChatButton.icon = PartyChatButton:CreateTexture(nil, "OVERLAY")
PartyChatButton.icon:SetAllPoints()
PartyChatButton.icon:SetTexture("Interface/AddOns/MDungeonTeleports/media/ui/ui_default/button_refresh.blp")

local PartyChatButtonBorder = PartyChatButton:CreateTexture(nil, "OVERLAY")
PartyChatButtonBorder:SetAllPoints(PartyChatButton)
PartyChatButtonBorder:SetDrawLayer("OVERLAY", 2)
PartyChatButton.PartyChatButtonBorder = PartyChatButtonBorder

local PartyChatButtonHover = PartyChatButton:CreateTexture(nil, "HIGHLIGHT")
PartyChatButtonHover:SetAllPoints(PartyChatButton)
PartyChatButtonHover:SetTexture("Interface/AddOns/MDungeonTeleports/media/ui/ui_default/button_refresh_highlight.blp")
PartyChatButton.PartyChatButtonHover = PartyChatButtonHover

PartyChatButton:RegisterForClicks("AnyDown")

-- Add a tooltip
PartyChatButton:SetScript(
    "OnEnter",
    function(self)
        GameTooltip:SetOwner(self, "ANCHOR_TOP")
        GameTooltip:SetText("Refresh Keys", 1, 1, 1)
        GameTooltip:Show()
    end
)

PartyChatButton:SetScript(
    "OnLeave",
    function(self)
        GameTooltip:Hide()
    end
)

PartyChatButton:SetScript(
    "OnClick",
    function()
        if InCombatLockdown() then
            return
        end

        C_Timer.After(
            1,
            function()
                RequestPersonalKeystone()
                RequestPartyKeystones()
            end
        )
    end
)

-- MARK: Look for Key in Bag
local function FindKeystone()
    local keystoneDungeon, keystoneLevel, keystoneItemLink = nil, nil, nil
    local tooltipScanner = CreateFrame("GameTooltip", "KeystoneScanner", nil, "GameTooltipTemplate")
    tooltipScanner:SetOwner(UIParent, "ANCHOR_NONE")

    for bag = 0, 4 do
        local numSlots = C_Container.GetContainerNumSlots(bag)
        for slot = 1, numSlots do
            local itemID = C_Container.GetContainerItemID(bag, slot)
            if itemID == 180653 then
                local itemInfo = C_Container.GetContainerItemInfo(bag, slot)
                keystoneItemLink = itemInfo and itemInfo.hyperlink

                tooltipScanner:SetBagItem(bag, slot)

                for i = 1, tooltipScanner:NumLines() do
                    local lineText = _G["KeystoneScannerTextLeft" .. i]:GetText()
                    if lineText then
                        local dungeonMatch = lineText:match("^Keystone:%s*(.+)$")
                        if dungeonMatch then
                            keystoneDungeon = dungeonMatch
                        end
                        local levelMatch = lineText:match("^Mythic Level (%d+)$")
                        if levelMatch then
                            keystoneLevel = tonumber(levelMatch)
                        end
                    end
                end

                tooltipScanner:Hide()
                if keystoneDungeon and keystoneLevel then
                    return keystoneDungeon, keystoneLevel, keystoneItemLink
                end
            end
        end
    end

    tooltipScanner:Hide()
    return nil, nil, nil
end

-- MARK: SyncKeys Function.
local addonPrefix = "MDT_PEEPO"
C_ChatInfo.RegisterAddonMessagePrefix(addonPrefix)

local storedMapID = nil
local storedLevel = nil

local function StoreCurrentKeystone()
    storedMapID = C_MythicPlus.GetOwnedKeystoneChallengeMapID()
    storedLevel = C_MythicPlus.GetOwnedKeystoneLevel()
end

local function SyncKeys()
    local currentMapID = C_MythicPlus.GetOwnedKeystoneChallengeMapID()
    local currentLevel = C_MythicPlus.GetOwnedKeystoneLevel()
    
    if currentMapID and currentLevel then
        if currentMapID ~= storedMapID or currentLevel ~= storedLevel then
            C_ChatInfo.SendAddonMessage(addonPrefix, "SyncKeys", "PARTY")
            
            storedMapID = currentMapID
            storedLevel = currentLevel
        else
        end
    end
end

local addonMessageFrame = CreateFrame("Frame")
addonMessageFrame:RegisterEvent("CHAT_MSG_ADDON")
addonMessageFrame:SetScript("OnEvent", function(self, event, prefix, message, channel, sender)
    if prefix == addonPrefix and message == "SyncKeys" then
        RequestPartyKeystones()
        RequestPersonalKeystone()
    end
end)

-- MARK: Respond to !keys
local function OnEvent(self, event, text, sender, ...)
    if MDungeonTeleports.isRespondChecked then
        if event == "CHAT_MSG_PARTY" or event == "CHAT_MSG_PARTY_LEADER" then
            if text:lower() == "!keys" then
                local keystoneDungeon, keystoneLevel, keystoneItemLink = FindKeystone()

                local message = "[M+DT]: "

                if keystoneDungeon and keystoneLevel and keystoneItemLink then
                    message = message .. keystoneItemLink
                else
                    message = message .. "No Keystone."
                end

                SendChatMessage(message, "PARTY")
            end
        end
    end
end

local frame = CreateFrame("Frame")
frame:RegisterEvent("CHAT_MSG_PARTY")
frame:RegisterEvent("CHAT_MSG_PARTY_LEADER")
frame:SetScript("OnEvent", OnEvent)

-- MARK: Events
local eventFrame = CreateFrame("Frame")
local previousGroupSize = GetNumGroupMembers()

eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
eventFrame:RegisterEvent("CHALLENGE_MODE_COMPLETED")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:RegisterEvent("GROUP_LEFT")
eventFrame:RegisterEvent("GROUP_JOINED")
eventFrame:RegisterEvent("GOSSIP_CLOSED")

eventFrame:SetScript("OnEvent", function(self, event, ...)
    if event == "GROUP_ROSTER_UPDATE" then
        C_Timer.After(5, function()
            if not InCombatLockdown() then
                local currentGroupSize = GetNumGroupMembers()
                if currentGroupSize ~= previousGroupSize then
                    RequestPartyKeystones()
                    previousGroupSize = currentGroupSize
                end
            end
        end)
    elseif event == "GROUP_LEFT" or event == "GROUP_JOINED" then
        C_Timer.After(1, function()
            if not InCombatLockdown() then
                RequestPartyKeystones()
            end
        end)
    elseif event == "CHALLENGE_MODE_COMPLETED" then
        C_Timer.After(3, function()
            RequestPartyKeystones()
            RequestPersonalKeystone()
        end)
    elseif event == "PLAYER_ENTERING_WORLD" then
        C_Timer.After(3, function()
            if not InCombatLockdown() then
                RequestPersonalKeystone()
                StoreCurrentKeystone()
            end
        end)
    elseif event == "GOSSIP_CLOSED" then
        C_Timer.After(3, function()
            RequestPersonalKeystone()
            SyncKeys()
        end)
    end
end)

-- MARK: Update on PVEFrame opening. Instead of some convoluted vault opening detection crap.
if PVEFrame then
    PVEFrame:HookScript("OnShow", function()
        C_Timer.After(1, function()
            if not InCombatLockdown() then
                RequestPersonalKeystone()
            end
        end)
    end)
end

RequestPersonalKeystone()
RequestPartyKeystones()
StoreCurrentKeystone()