-- VaultSpecReminder - Shows loot spec warning when opening Great Vault
--## Author: Azare-Terokkar ## Version: 0.0.2 ## SavedVariables: VaultSpecReminderDB

local VaultSpecReminder = CreateFrame("Frame", "VaultSpecReminder")

local VAULT_OPENING_SPELL_IDS = {
    449976, -- Great Vault opening
    1271478, -- Great Vault opening Silvermoon
    -- 212040, -- resto druid revitalize for testing
}

-- Debug: add spell for testing purposes for Azare-Terokkar
local function GetVaultOpeningSpellIds()
    local ids = VAULT_OPENING_SPELL_IDS
    local name = UnitName("player")
    local realm = GetNormalizedRealmName()
    local fullName = realm and (name .. "-" .. realm) or name
    if fullName == "Azare-Terokkar" then
        ids = {}
        for i = 1, #VAULT_OPENING_SPELL_IDS do
            ids[i] = VAULT_OPENING_SPELL_IDS[i]
        end
        ids[#ids + 1] = 286353 -- Brewfest Reveler's Hearthstone
    end
    return ids
end

local function IsVaultOpeningSpell(spellID)
    local ids = GetVaultOpeningSpellIds()
    for i = 1, #ids do
        if ids[i] == spellID then
            return true
        end
    end
    return false
end

-- Display frame
local displayFrame = nil
local displayText = nil

-- timer is a fallback to be sure to hide a warning if something goes wrong in stop cast event handler
-- or something else unexpected happens
local hideTimer = nil
local AUTO_HIDE_DELAY = 10 -- Auto-hide after 15 seconds as safety measure

-- Saved variables
local db = nil

-- Initialize saved variables
function VaultSpecReminder:InitializeDB()
    if not VaultSpecReminderDB then
        VaultSpecReminderDB = {}
    end
    db = VaultSpecReminderDB
    
    -- Initialize default position if not set
    if not db.position then
        db.position = {
            point = "CENTER",
            relativeTo = "UIParent",
            relativePoint = "CENTER",
            xOfs = 0,
            yOfs = 100
        }
    end
end

-- Save frame position
function VaultSpecReminder:SavePosition()
    if not displayFrame or not db then
        return
    end
    
    local point, relativeTo, relativePoint, xOfs, yOfs = displayFrame:GetPoint()
    db.position = {
        point = point,
        relativeTo = relativeTo and relativeTo:GetName() or "UIParent",
        relativePoint = relativePoint,
        xOfs = xOfs,
        yOfs = yOfs
    }
end

-- Load frame position
function VaultSpecReminder:LoadPosition()
    if not displayFrame or not db or not db.position then
        return
    end
    
    local pos = db.position
    local relativeTo = pos.relativeTo == "UIParent" and UIParent or _G[pos.relativeTo] or UIParent
    
    displayFrame:ClearAllPoints()
    displayFrame:SetPoint(pos.point, relativeTo, pos.relativePoint, pos.xOfs, pos.yOfs)
end

-- Initialize the addon
function VaultSpecReminder:Initialize()
    -- Initialize saved variables
    self:InitializeDB()
    
    -- Create the display frame
    displayFrame = CreateFrame("Frame", "VaultSpecReminderDisplayFrame", UIParent)
    displayFrame:SetSize(400, 100)
    displayFrame:SetFrameStrata("DIALOG")
    displayFrame:Hide()
    
    -- Make frame draggable
    displayFrame:SetMovable(true)
    displayFrame:EnableMouse(true)
    displayFrame:RegisterForDrag("LeftButton")
    
    -- Set initial position from saved data
    self:LoadPosition()
    
    -- If no saved position, use default
    if not db.position or not db.position.point then
        displayFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 100)
    end
    
    -- Drag handlers
    displayFrame:SetScript("OnDragStart", function(self)
        self:StartMoving()
    end)
    
    displayFrame:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
        VaultSpecReminder:SavePosition()
    end)
    
    -- Create text
    displayText = displayFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
    displayText:SetPoint("CENTER", displayFrame, "CENTER", 0, 0)
    displayText:SetFont(GameFontNormal:GetFont(), 72, "OUTLINE")
    displayText:SetJustifyH("CENTER")
    displayText:SetShadowColor(0, 0, 0, 1)
    displayText:SetShadowOffset(2, -2)
    
    -- Pulsing animation (medium speed, ~1s cycle)
    local pulseGroup = displayText:CreateAnimationGroup()
    pulseGroup:SetLooping("REPEAT")
    local fadeDown = pulseGroup:CreateAnimation("Alpha")
    fadeDown:SetFromAlpha(1)
    fadeDown:SetToAlpha(0.5)
    fadeDown:SetDuration(0.5)
    fadeDown:SetOrder(1)
    local fadeUp = pulseGroup:CreateAnimation("Alpha")
    fadeUp:SetFromAlpha(0.5)
    fadeUp:SetToAlpha(1)
    fadeUp:SetDuration(0.5)
    fadeUp:SetOrder(2)
    displayFrame.pulseGroup = pulseGroup
    
    -- Register events
    self:RegisterEvent("UNIT_SPELLCAST_START")
    self:RegisterEvent("UNIT_SPELLCAST_STOP")
    self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
    self:RegisterEvent("UNIT_SPELLCAST_FAILED")
    
    -- Set script handlers
    self:SetScript("OnEvent", function(self, event, ...)
        if event == "UNIT_SPELLCAST_START" then
            self:OnSpellCastStart(...)
        elseif event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_INTERRUPTED" or event == "UNIT_SPELLCAST_FAILED" then
            self:OnSpellCastStop(...)
        end
    end)
end

-- Get loot spec display text
function VaultSpecReminder:GetLootSpecText()
    local specID = GetLootSpecialization()
    local lootSpecIcon, lootSpecName
    local _, class = UnitClass("player")
    local classColor = (RAID_CLASS_COLORS[class] and RAID_CLASS_COLORS[class].colorStr) or "FFFFFFFF"
    
    if specID == 0 then
        specID = GetSpecialization()
        if not specID then
            return "|cFFFFFFFF ？？？|r"
        end
        lootSpecName = select(2, GetSpecializationInfo(specID))
        lootSpecIcon = select(4, GetSpecializationInfo(specID))
    else
        lootSpecName = select(2, GetSpecializationInfoByID(specID))
        lootSpecIcon = select(4, GetSpecializationInfoByID(specID))
    end

    if not lootSpecName or not lootSpecIcon then
        return "|cFFFFFFFF XXX |r"
    end
    
    return "|c" .. classColor .. format("|T%d:0|t %s", lootSpecIcon, lootSpecName) .. "|r"
end

-- Handle spell cast start event
function VaultSpecReminder:OnSpellCastStart(unitTarget, castGUID, spellID)
    -- Only care about player's casts
    if unitTarget ~= "player" then
        return
    end

    -- local spellName = "Unknown"
    -- if C_Spell and C_Spell.GetSpellInfo then
    --     local spellInfo = C_Spell.GetSpellInfo(spellID)
    --     spellName = spellInfo and spellInfo.name or "Unknown"
    -- else
    --     spellName = GetSpellInfo(spellID) or "Unknown"
    -- end
    -- print(string.format("[%s] Spell Cast Start - ID: %d, Name: %s", "VaultSpecReminder", spellID, spellName))

    -- Safety: Hide display if starting a different spell cast (prevents stuck display)
    if displayFrame and displayFrame:IsVisible() and not IsVaultOpeningSpell(spellID) then
        self:HideDisplay()
    end

    -- First check by spell ID (most reliable)
    if IsVaultOpeningSpell(spellID) then
        self:ShowDisplay()
        return
    end
end

-- Handle spell cast stop/interrupt/failed events
function VaultSpecReminder:OnSpellCastStop(unitTarget, castGUID, spellID)
    -- Only care about player's casts
    if unitTarget ~= "player" then
        return
    end

    self:HideDisplay()
end

-- Show the display (no animation)
function VaultSpecReminder:ShowDisplay()
    if not displayFrame or not displayText then
        return
    end

    -- Cancel any existing hide timer
    if hideTimer then
        hideTimer:Cancel()
        hideTimer = nil
    end

    -- Update text
    displayText:SetText(self:GetLootSpecText())

    -- Show frame and start pulse
    displayFrame:SetAlpha(1)
    displayFrame:Show()
    if displayFrame.pulseGroup then
        displayFrame.pulseGroup:Play()
    end

    -- Set auto-hide timer as safety measure
    hideTimer = C_Timer.NewTimer(AUTO_HIDE_DELAY, function()
        self:HideDisplay()
        hideTimer = nil
    end)
end

-- Hide the display (no animation)
function VaultSpecReminder:HideDisplay()
    -- Cancel any pending hide timer
    if hideTimer then
        hideTimer:Cancel()
        hideTimer = nil
    end

    if not displayFrame or not displayFrame:IsVisible() then
        return
    end

    if displayFrame.pulseGroup then
        displayFrame.pulseGroup:Stop()
    end
    displayFrame:Hide()
end

-- Initialize when addon is loaded
local loader = CreateFrame("Frame")
loader:RegisterEvent("ADDON_LOADED")
loader:SetScript("OnEvent", function(self, event, addon)    
    if addon == "OrzUI" then
        VaultSpecReminder:Initialize()
    end
end)