-- Pedro Addon: Wow Version 12.0.1
-- Pedro Addon: Pedro Version 8.4.1
-- Author: Darthcutie

-- DBs
PedroDB_Global = PedroDB_Global or {}
PedroDB_Char   = PedroDB_Char   or {}

-- Local references bound to SavedVariables
local G = PedroDB_Global
local C = PedroDB_Char

-- Version
local ADDON_VERSION = "Pedro v8.4.1 (WoW 12.0.5)"


-- Define PedroSounds Base
local BasePedroSounds = {
    {name = "Pedro",      path = "Interface\\AddOns\\Pedro\\Media\\Pedro.ogg",      duration = 9},
    {name = "PedroLong",  path = "Interface\\AddOns\\Pedro\\Media\\PedroLong.ogg",  duration = 40},
    {name = "GoldenKpop", path = "Interface\\AddOns\\Pedro\\Media\\GoldenKpop.ogg", duration = 48},
}

-- Runtime list (base + up to 5 custom)
local PedroSounds = {}
local PedroSongLengths = {}

local function RebuildPedroSounds()
    wipe(PedroSounds)
    wipe(PedroSongLengths)
	
    -- Add built-in sounds
    for _, s in ipairs(BasePedroSounds) do
        table.insert(PedroSounds, s)
	end
	
    -- 5 is the limit
    if G and G.customSongs then
        local count = 0
        for _, s in ipairs(G.customSongs) do
            count = count + 1
            if count > 5 then break end
            table.insert(PedroSounds, s)
		end
	end
	
    -- Rebuild length
    for _, sound in ipairs(PedroSounds) do
        if sound.path and sound.duration then
            PedroSongLengths[sound.path] = sound.duration
		end
	end
end

local function ResizePedroMainUI()
    if not PedroMainUI then return end
	
    local perCustom = 24     
    local baseHeight = 520  
	
    local totalSounds = #PedroSounds
    local baseSounds = (BasePedroSounds and #BasePedroSounds) or 3
	
    local customCount = totalSounds - baseSounds
    if customCount < 0 then customCount = 0 end
	
    local newHeight = baseHeight + (customCount * perCustom)
	
    -- Clamp just in case
    if newHeight < baseHeight then newHeight = baseHeight end
    if newHeight > 700 then newHeight = 700 end
	
    PedroMainUI:SetHeight(newHeight)
end

local function GetSelectedSongLength()
    return PedroSongLengths[G.selectedSound] or 10
end

local animationTimer = 0
local frameDuration = G.animationSpeed or 0.15
local currentFrame = 1
local elapsedTime = 0
local isAnimating = false
local tickerInCombat = nil
local PedroPositioningMode = false
local isFadingOut = false


function StartAnimation(songLength)
    if not songLength or songLength <= 0 then
        songLength = 10
	end
	
    if isAnimating then
        return
	end
	
    isAnimating = true
    isFadingOut = false
    PedroAnimationFrame:SetAlpha(1)
	
    if PedroAnimationFrame.closeBtn then
        PedroAnimationFrame.closeBtn:Hide()
	end
	
    animationTimer = 0
    elapsedTime = 0
    currentFrame = 1
	
	frameDuration = G.animationSpeed or 0.15
	
    -- Sprite sheet settings (4x8 inside 1024x2048 canvas)
    local cellSize = 193 -- actual frame size
    local iconSize = 193 -- on-screen size
    
	
    local numCols = 4
    local numRows = 8
	
    -- Full texture size
    local totalWidth  = 1024
    local totalHeight = 2048
	
    PedroAnimationFrame:SetSize(iconSize, iconSize)
	
    -- Animation Loop
    PedroAnimationFrame:SetScript("OnUpdate", function(self, elapsed)
        if elapsed > 0.05 then
            elapsed = 0.05
		end
		
        animationTimer = animationTimer + elapsed
        elapsedTime = elapsedTime + elapsed
		
        if not isFadingOut and elapsedTime >= frameDuration then
            elapsedTime = elapsedTime - frameDuration
            currentFrame = currentFrame + 1
			
            if currentFrame > (numCols * numRows) then
                currentFrame = 1
			end
			
            local col = (currentFrame - 1) % numCols
            local row = math.floor((currentFrame - 1) / numCols)
			
			-- Pixel coords inside the region where icons actually are														  
            local left_px   = col * cellSize
            local right_px  = left_px + cellSize
            local top_px    = row * cellSize
            local bottom_px = top_px + cellSize
			
			-- Convert to normalized coords relative to full texture size															 
            local left   = left_px / totalWidth
            local right  = right_px / totalWidth
            local top    = top_px / totalHeight
            local bottom = bottom_px / totalHeight
			
            PedroAnimationTexture:SetTexCoord(left, right, top, bottom)
		end
		
        if not isFadingOut and animationTimer >= songLength then
            isFadingOut = true
            self.fadeStart = GetTime()
		end
		
        if isFadingOut then
            local fadeDuration = 0.25
            local progress = (GetTime() - self.fadeStart) / fadeDuration
			
            if progress >= 1 then
                -- Fade complete
                PedroAnimationFrame:SetAlpha(0)
                PedroAnimationFrame:EnableMouse(false)
                if PedroAnimationFrame.closeBtn then
                    PedroAnimationFrame.closeBtn:EnableMouse(false)
				end
				
                isAnimating = false
                isFadingOut = false
                PedroAnimationFrame:SetScript("OnUpdate", nil)
                return
				else
                -- Fade in progress
                PedroAnimationFrame:SetAlpha(1 - progress)
			end
		end
	end)
end

-- Audio channels
local PedroAudioChannels = {
    {name = "Master (Default, Recommended)", value = "Master"},
    {name = "Sound Effects (Recommended if sound cuts out)", value = "SFX"},
    {name = "Dialog (Not recommended)", value = "Dialog"},
    {name = "Music (Not recommended)", value = "Music"},
    {name = "Ambience (Not recommended)", value = "Ambience"},
}

-- Core state variables
local lustActive = false
local canPlay = true
local lastTriggerTime = nil
local cooldown = 1.5
local lustGuardDuration = 48 -- seconds between allowed Pedro triggers

local pedroAudioChannel = G.audioChannel or "Master"
local pedroPlayingID = nil

local function ResetCooldown()
    canPlay = true
end

local function PlayPedroIfAllowed(ignoreGuard)
	if not ignoreGuard then
		if not canPlay then return false end
		if lastTriggerTime and (GetTime() - lastTriggerTime) < lustGuardDuration then return false end
	end
	
	if type(pedroPlayingID) == "number" then
		StopSound(pedroPlayingID)
		pedroPlayingID = nil
	end
	
	local id = PlaySoundFile(G.selectedSound, pedroAudioChannel)
	if not id then
		print("Pedro: Failed to play sound. File missing or invalid.")
		return false
	end
	pedroPlayingID = id
	
	if not ignoreGuard then
		canPlay = false
		lastTriggerTime = GetTime()
		C_Timer.After(cooldown, ResetCooldown)
	end
	
	return true
end

-- Debuffs to trigger Pedro (spell IDs)
local lustDebuffs = {
    [57723] = true,      -- Exhaustion
    [57724] = true,      -- Sated
    [80354] = true,      -- Temporal Displacement
    [95809] = true,      -- Hunter Pet Insanity
    [160455] = true,     -- Hunter Pet Fatigued
    [264689] = true,     -- Hunter Pet Fatigued (alt)
    [390435] = true,     -- Exhaustion (alt)
}
local function CheckLustDebuffByID()
    if EditModeManager and EditModeManager:ShouldIgnoreUnitEvents() then
        return false
	end
	
    local found = false
	
    for spellID in pairs(lustDebuffs) do
        local aura = C_UnitAuras.GetPlayerAuraBySpellID(spellID)
		
        if aura and aura.expirationTime then
            local timeLeft = aura.expirationTime - GetTime()
			
            -- Ignore nearly-expired lust debuffs 570 means if the debuff has less than 9:30 mins left, ignore it and don't trigger.
            if timeLeft >= 570 then
                found = true
                break
			end
		end
	end
	
    lustActive = found
    return found
end

-- Central trigger for Pedro based on debuffs
local function TryPlayPedro()
    if not G.enabled then return false end
	
    local songLength = GetSelectedSongLength()
    local played = false
	
    local hasDebuff = CheckLustDebuffByID()
    lustActive = hasDebuff
	
    if hasDebuff then
        if not isAnimating then
            local playedSound = PlayPedroIfAllowed()
            if playedSound and not G.disableAnimation then
                StartAnimation(songLength)
			end
            played = playedSound
		end
	end
	
    return played
end

-- Manual play
local function TryPlayPedroManual()
    if not G.enabled then
        print("Pedro: Addon is disabled.")
        return
	end
	
    PlayPedroIfAllowed(true)
	
    -- Find the song in use
    local soundName = "Unknown"
    for _, sound in ipairs(PedroSounds) do
        if sound.path == G.selectedSound then
            soundName = sound.name
            break
		end
	end
	
    print("Pedro: Played " .. soundName .. " manually.")
	
    if not G.disableAnimation then
        local songLength = GetSelectedSongLength()
        StartAnimation(songLength)
	end
end


-- Show Sound Selection Frame
local function ShowSoundFrame()
	
    if PedroSoundSelector then
        PedroSoundSelector:Show()
        PedroSoundSelector:Raise()
        return
	end
	
    local SoundFrame = CreateFrame("Frame", "PedroSoundSelector", UIParent, "BasicFrameTemplateWithInset")
    local count = #PedroSounds
    SoundFrame:SetSize(200, 120 + (count * 25) + 35)
    SoundFrame:SetPoint("CENTER")
    SoundFrame:SetMovable(true)
    SoundFrame:EnableMouse(true)
    SoundFrame:RegisterForDrag("LeftButton")
    SoundFrame:SetScript("OnDragStart", SoundFrame.StartMoving)
    SoundFrame:SetScript("OnDragStop", SoundFrame.StopMovingOrSizing)
	
    SoundFrame.title = SoundFrame:CreateFontString(nil, "OVERLAY")
    SoundFrame.title:SetFontObject("GameFontHighlight")
    SoundFrame.title:SetPoint("TOP", 0, -5)
    SoundFrame.title:SetText("Select Pedro Sound")
	
    local okButton = CreateFrame("Button", nil, SoundFrame, "UIPanelButtonTemplate")
    okButton:SetSize(80, 22)
    okButton:SetPoint("BOTTOM", 0, 10)
    okButton:SetText("OK")
    okButton:SetScript("OnClick", function()
        SoundFrame:Hide()
	end)
	
    local radioButtons = {}
	
    for i, sound in ipairs(PedroSounds) do
        local btn = CreateFrame("CheckButton", "PedroSoundBtn"..i, SoundFrame, "UICheckButtonTemplate")
        btn:SetPoint("TOPLEFT", 10, -(i * 25) - 20)
        btn.text:SetText(string.format("%s - %d second%s", sound.name, sound.duration or 0, (sound.duration == 1 and "" or "s")))
		
        if G.selectedSound == sound.path then
            btn:SetChecked(true)
		end
		
        btn:SetScript("OnClick", function(self)
            for _, other in ipairs(radioButtons) do
                if other ~= self then
                    other:SetChecked(false)
				end
			end
            G.selectedSound = sound.path
            print("Pedro: Selected song " .. sound.name)
		end)
		
        table.insert(radioButtons, btn)
	end
	
    SoundFrame:Show()
end  

-- Show Audio Channel Selection Frame 
local function ShowAudioChannelFrame()
	
    if PedroAudioSelector then
        PedroAudioSelector:Show()
        PedroAudioSelector:Raise()
        return
	end
	
    local ChannelFrame = CreateFrame("Frame", "PedroAudioSelector", UIParent, "BasicFrameTemplateWithInset")
    local count = #PedroAudioChannels
    ChannelFrame:SetSize(320, 120 + (count * 25) + 35)
    ChannelFrame:SetPoint("CENTER")
    ChannelFrame:SetMovable(true)
    ChannelFrame:EnableMouse(true)
    ChannelFrame:RegisterForDrag("LeftButton")
    ChannelFrame:SetScript("OnDragStart", ChannelFrame.StartMoving)
    ChannelFrame:SetScript("OnDragStop", ChannelFrame.StopMovingOrSizing)
	
    ChannelFrame.title = ChannelFrame:CreateFontString(nil, "OVERLAY")
    ChannelFrame.title:SetFontObject("GameFontHighlight")
    ChannelFrame.title:SetPoint("TOP", 0, -5)
    ChannelFrame.title:SetText("Select Audio Channel")
	
    local okButton = CreateFrame("Button", nil, ChannelFrame, "UIPanelButtonTemplate")
    okButton:SetSize(80, 22)
    okButton:SetPoint("BOTTOM", 0, 10)
    okButton:SetText("OK")
    okButton:SetScript("OnClick", function()
        ChannelFrame:Hide()
	end)
	
    local radioButtons = {}
	
    for i, channel in ipairs(PedroAudioChannels) do
        local btn = CreateFrame("CheckButton", "PedroAudioBtn"..i, ChannelFrame, "UICheckButtonTemplate")
        btn:SetPoint("TOPLEFT", 10, -(i * 25) - 20)
        btn.text:SetText(channel.name)
		
        if G.audioChannel == channel.value then
            btn:SetChecked(true)
		end
		
        btn:SetScript("OnClick", function(self)
            for _, other in ipairs(radioButtons) do
                if other ~= self then
                    other:SetChecked(false)
				end
			end
            G.audioChannel = channel.value
            pedroAudioChannel = channel.value
            print("Pedro: Audio channel set to " .. channel.name)
		end)
		
        table.insert(radioButtons, btn)
	end
	
    ChannelFrame:Show()
end	

local function RebuildSoundList()
    if not PedroMainUI then return end
	
    -- Remove old buttons
    if PedroMainUI.soundButtons then
        for _, btn in ipairs(PedroMainUI.soundButtons) do
            btn:Hide()
		end
	end
	
    PedroMainUI.soundButtons = {}
	
    local last = PedroMainUI.soundLabel
	
    for i, sound in ipairs(PedroSounds) do
        local btn = CreateFrame("CheckButton", nil, PedroMainUI, "UICheckButtonTemplate")
        btn:SetPoint("TOPLEFT", last, "BOTTOMLEFT", 0, -20)
        btn.text:SetText(sound.name)
		
        if G.selectedSound == sound.path then
            btn:SetChecked(true)
		end
		
        btn:SetScript("OnClick", function(self)
            for _, other in ipairs(PedroMainUI.soundButtons) do
                if other ~= self then other:SetChecked(false) end
			end
            G.selectedSound = sound.path
		end)
		
        table.insert(PedroMainUI.soundButtons, btn)
        last = btn
	end
end

local function RefreshSoundListUI()
    if not PedroMainUI or not PedroMainUI.soundLabel then return end
	
    -- Clear old buttons
    if PedroMainUI.soundButtons then
        for _, btn in ipairs(PedroMainUI.soundButtons) do
            btn:Hide()
            if btn.removeBtn then
                btn.removeBtn:Hide()
			end
		end
	end
	
    local soundButtons = {}
    PedroMainUI.soundButtons = soundButtons
	
    local soundLabel = PedroMainUI.soundLabel
    local previous = soundLabel  -- anchor point for stacking
	
    for i, sound in ipairs(PedroSounds) do
        -- Create the sound button
        local btn = CreateFrame("CheckButton", nil, PedroMainUI, "UIRadioButtonTemplate")
		
        -- Stacking anchor to previous element not fixed maths
        btn:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -4)
        btn.text:SetText(sound.name)
		
        -- Remove button for custom songs
        if i > #BasePedroSounds then
            local removeBtn = CreateFrame("Button", nil, PedroMainUI, "UIPanelButtonTemplate")
            removeBtn:SetSize(60, 18)
            removeBtn:SetPoint("LEFT", btn, "LEFT", 30 + btn.text:GetStringWidth(), 0)
            removeBtn:SetText("Remove")
			
            removeBtn:SetScript("OnClick", function()
                -- Remove from saved list
                for idx, s in ipairs(G.customSongs) do
                    if s.path == sound.path then
                        table.remove(G.customSongs, idx)
                        break
					end
				end
				
                -- Reset selected sound if needed
                if G.selectedSound == sound.path then
                    G.selectedSound = BasePedroSounds[1].path
                    print("Pedro: Selected song was removed. Reverting to default.")
				end
				
                print("Pedro: Removed custom song:", sound.name)
				
                RebuildPedroSounds()
                RefreshSoundListUI()
			end)
			
            btn.removeBtn = removeBtn
		end
		
        if G.selectedSound == sound.path then
            btn:SetChecked(true)
		end
		
        btn:SetScript("OnClick", function(self)
            if not self:GetChecked() then
                self:SetChecked(true)
                return
			end
			
            for _, other in ipairs(soundButtons) do
                if other ~= self then
                    other:SetChecked(false)
				end
			end
			
            G.selectedSound = sound.path
            print("Pedro: Selected sound " .. sound.name)
		end)
		
        table.insert(soundButtons, btn)
        previous = btn  -- update stacking anchor
	end
	
    -- Re-anchor Audio Channel label if it exists
    if PedroMainUI.channelLabel then
        local lastButton = PedroMainUI.soundButtons[#PedroMainUI.soundButtons]
        PedroMainUI.channelLabel:ClearAllPoints()
        PedroMainUI.channelLabel:SetPoint("TOPLEFT", lastButton, "BOTTOMLEFT", 0, -10)
	end
	ResizePedroMainUI()
end

SLASH_PEDRO1 = "/pedro"
SlashCmdList.PEDRO = function()
    ShowPedroMainUI()
end

function ShowAddSongWindow()
    if #G.customSongs >= 5 then
        print("Pedro: You can only add 5 custom songs.")
        return
	end
	
    if PedroAddSong then
		-- Reset fields when reopening
		PedroAddSong.nameBox:SetText("Song Name")
		PedroAddSong.fileBox:SetText("MySong.ogg")
		PedroAddSong.durBox:SetText("Duration (sec)")
		
		PedroAddSong:Show()
		PedroAddSong:Raise()
		return
	end
	
    -- Create the frame once
    local w = CreateFrame("Frame", "PedroAddSong", UIParent, "BasicFrameTemplateWithInset")
    PedroAddSong = w
	
    w:SetSize(260, 230)
    w:SetPoint("CENTER")
    w:SetFrameStrata("DIALOG")
    w:SetFrameLevel(1000)
	
    -- ESC to close (only needs to be done once)
    if not tContains(UISpecialFrames, "PedroAddSong") then
        table.insert(UISpecialFrames, "PedroAddSong")
	end
	
    w:SetMovable(true)
    w:EnableMouse(true)
    w:RegisterForDrag("LeftButton")
    w:SetScript("OnDragStart", w.StartMoving)
    w:SetScript("OnDragStop", w.StopMovingOrSizing)
	
    w.title = w:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    w.title:SetPoint("TOP", 0, -5)
    w.title:SetText("Add Custom Song")
	
	-- Instruction text
	local info = w:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
	info:SetPoint("TOPLEFT", w, "TOPLEFT", 15, -30)
	info:SetWidth(230)
	info:SetJustifyH("LEFT")
	info:SetText("Place your .ogg files in:\nInterface/AddOns/Pedro/Media/\n\nOnly .ogg files are supported.")
	
    -- Name box
    local nameBox = CreateFrame("EditBox", nil, w, "InputBoxTemplate")
    nameBox:SetSize(200, 20)
    nameBox:SetPoint("TOPLEFT", info, "BOTTOMLEFT", 0, -10)
    nameBox:SetAutoFocus(false)
    nameBox:SetText("Song Name")
	
    -- File box
    local fileBox = CreateFrame("EditBox", nil, w, "InputBoxTemplate")
    fileBox:SetSize(200, 20)
    fileBox:SetPoint("TOP", nameBox, "BOTTOM", 0, -10)
    fileBox:SetAutoFocus(false)
    fileBox:SetText("MySong.ogg")
	
    -- Duration box
    local durBox = CreateFrame("EditBox", nil, w, "InputBoxTemplate")
    durBox:SetSize(200, 20)
    durBox:SetPoint("TOP", fileBox, "BOTTOM", 0, -10)
    durBox:SetAutoFocus(false)
    durBox:SetText("Duration (sec)")
	
    -- Tab
    nameBox:SetScript("OnTabPressed", function() fileBox:SetFocus() end)
    fileBox:SetScript("OnTabPressed", function() durBox:SetFocus() end)
    durBox:SetScript("OnTabPressed", function() nameBox:SetFocus() end)
	
	w.nameBox = nameBox
	w.fileBox = fileBox
	w.durBox = durBox
	
    -- Add button
    local ok = CreateFrame("Button", nil, w, "UIPanelButtonTemplate")
    ok:SetSize(80, 22)
    ok:SetPoint("BOTTOM", 0, 10)
    ok:SetText("Add")
	
    ok:SetScript("OnClick", function()
        local name = nameBox:GetText()
        local file = fileBox:GetText()
		-- Auto-append .ogg if missing
		if not file:lower():match("%.ogg$") then
			file = file .. ".ogg"
		end
        local dur  = tonumber(durBox:GetText())
		
        -- Clean name
        local cleanName = name:gsub("[^%w%s]", "")
        if cleanName == "" then
            print("Pedro: Song name must contain letters or numbers.")
            return
		end
		
        if not file or file == "" then
            print("Pedro: Invalid file name.")
            return
		end
		
        if not dur or dur <= 0 then
            print("Pedro: Invalid duration.")
            return
		end
		
        if dur < 1 or dur > 50 then
            print("Pedro: Duration must be between 1 and 50 seconds.")
            return
		end
		
        local fullPath = "Interface\\AddOns\\Pedro\\Media\\" .. file
		
		for _, s in ipairs(G.customSongs) do
			if s.path:lower() == fullPath:lower() then
				print("Pedro: That file is already added.")
				return
			end
		end
		
        -- Validate file exists (Dialog channel = mostly silent)
        local ok = PlaySoundFile(fullPath, "Dialog")
        if not ok then
            print("Pedro: File not found or unsupported format. If you just added it, type /reload.")
            return
		end
		
        table.insert(G.customSongs, {
            name = cleanName,
            path = fullPath,
            duration = dur,
		})
		
        print("Pedro: Added custom song:", cleanName)
		
        RebuildPedroSounds()
		
		-- Refresh main UI sound list if it's open
		if PedroMainUI and PedroMainUI:IsShown() then
			RebuildPedroSounds()
			RefreshSoundListUI()
		end
		
		w:Hide()
	end)
end

-- /Pedro debug command
SLASH_PEDRODEBUG1 = "/pedrodebug"
SlashCmdList.PEDRODEBUG = function()
	local soundName = PedroSounds[1].name
	for _, sound in ipairs(PedroSounds) do
		if PedroDB_Global.selectedSound == sound.path then
			soundName = sound.name
			break
		end
	end
	
	local audioChannel = PedroDB_Global.audioChannel or "Master"
	local lustState = lustActive and "Yes" or "No"
	
	-- Debuff info
	local debuffName = "None"
	local timeLeft = 0
	local valid = false
	
	for spellID in pairs(lustDebuffs) do
		local aura = C_UnitAuras.GetPlayerAuraBySpellID(spellID)
		if aura and aura.expirationTime then
			debuffName = GetSpellInfo(spellID)
			timeLeft = aura.expirationTime - GetTime()
			valid = timeLeft >= 570
			break
		end
	end
	
	print("---- Pedro Info ----")
	print("Version:", ADDON_VERSION)
	print("Lust Detected:", lustState)
	print("Debuff:", debuffName)
	print("Time Left:", string.format("%.1f seconds", timeLeft))
	print("Debuff Valid (>=570s):", valid and "Yes" or "No")
	print("Pedro Enabled:", G.enabled and "Yes" or "No")
	print("Sound:", soundName)
	print("Channel:", audioChannel)
	print("Animation Enabled:", not G.disableAnimation and "Yes" or "No")
	print("Animation Speed:", G.animationSpeed or "Default")
end

-- Main Pedro event frame
local f = CreateFrame("Frame")
f:RegisterEvent("ADDON_LOADED")
f:RegisterEvent("UNIT_AURA")
f:RegisterEvent("PLAYER_REGEN_DISABLED")
f:RegisterEvent("PLAYER_REGEN_ENABLED")

f:SetScript("OnEvent", function(self, event, arg1)
	
	-- Addon loaded
	if event == "ADDON_LOADED" and arg1 == "Pedro" then
		
		-- Ensure SavedVariables exist
		PedroDB_Global = PedroDB_Global or {}
		PedroDB_Char   = PedroDB_Char   or {}
		
		-- Rebind locals
		G = PedroDB_Global
		C = PedroDB_Char
		
		-- Ensure customSongs table exists
		G.customSongs = G.customSongs or {}
		
		-- Build runtime sound list (base + custom) and lengths
		RebuildPedroSounds()
		
		-- Set default selected sound if missing
		if G.selectedSound == nil then
			if PedroSounds[1] and PedroSounds[1].path then
				G.selectedSound = PedroSounds[1].path
			end
		end		
		
		-- Global defaults
		if G.audioChannel == nil then
			G.audioChannel = "Master"
		end
		if G.disableAnimation == nil then
			G.disableAnimation = false
		end
		if G.animationSpeed == nil then
			G.animationSpeed = 0.15
		end
		if G.enabled == nil then
			G.enabled = true
		end
		
		-- Mark initialized
		C._initialized = true
		
		-- Create animation frame if missing
		if not PedroAnimationFrame then
			PedroAnimationFrame = CreateFrame("Frame", "PedroAnimationFrame", UIParent)
			PedroAnimationFrame:SetClampedToScreen(true)
			
			PedroAnimationTexture = PedroAnimationFrame:CreateTexture(nil, "BACKGROUND")
			PedroAnimationTexture:SetAllPoints()
			PedroAnimationTexture:SetTexture("Interface\\AddOns\\Pedro\\Media\\Pedro_Animation.tga")
			
			-- Ensure close button is hidden on load
			if PedroAnimationFrame.closeBtn then
				PedroAnimationFrame.closeBtn:Hide()
				PedroAnimationFrame.closeBtn:EnableMouse(false)
			end
			
			-- Set initial TexCoord to the first frame stops weird random static sheet on first frame
			local cellSize = 193
			local totalWidth = 1024
			local totalHeight = 2048
			
			local left   = 0 / totalWidth
			local right  = cellSize / totalWidth
			local top    = 0 / totalHeight
			local bottom = cellSize / totalHeight
			
			PedroAnimationTexture:SetTexCoord(left, right, top, bottom)
		end
		
		-- Set size and position
		PedroAnimationFrame:SetSize(193, 193)
		if G.animPoint and G.animPoint.point then
			PedroAnimationFrame:SetPoint(
				G.animPoint.point,
				UIParent,
				G.animPoint.relativePoint,
				G.animPoint.x,
				G.animPoint.y
			)
			else
			PedroAnimationFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 100, -120)
		end
		
		-- Make movable
		PedroAnimationFrame:SetMovable(true)
		PedroAnimationFrame:EnableMouse(true)
		PedroAnimationFrame:RegisterForDrag("LeftButton")
		
		PedroAnimationFrame:SetScript("OnDragStart", function(self)
			if InCombatLockdown() then return end
			self:StartMoving()
		end)
		
		PedroAnimationFrame:SetScript("OnDragStop", function(self)
			self:StopMovingOrSizing()
			local point, relativeTo, relativePoint, xOfs, yOfs = self:GetPoint()
			G.animPoint = {
				point = point,
				relativePoint = relativePoint,
				x = xOfs,
				y = yOfs
			}
		end)
		
		PedroAnimationFrame:SetAlpha(0)
		PedroAnimationFrame:EnableMouse(false)
		
		-- Player auras changed
		elseif event == "UNIT_AURA" then
		if arg1 == "player" then
			if G.enabled and not InCombatLockdown() then
				TryPlayPedro()
			end
		end
		
		-- Entering combat
		elseif event == "PLAYER_REGEN_DISABLED" then
		if tickerInCombat then
			tickerInCombat:Cancel()
			tickerInCombat = nil
		end
		
		if G.enabled then
			tickerInCombat = C_Timer.NewTicker(1.0, TryPlayPedro)
		end
		
		-- Leaving combat
		elseif event == "PLAYER_REGEN_ENABLED" then
		if tickerInCombat then
			tickerInCombat:Cancel()
			tickerInCombat = nil
		end
		
		lustActive = false
	end
end)

local PedroMainUI = nil

function ShowPedroMainUI()
    -- If the frame already exists, just show it
    if PedroMainUI then
        PedroMainUI:Show()
        PedroMainUI:Raise()
        return
	end
	
    -- Create the frame 
    local f = CreateFrame("Frame", "PedroMainUI", UIParent, "BasicFrameTemplateWithInset")
    PedroMainUI = f
    f:SetScale(1.0) -- prevent UI from becoming huge after refresh
	
    -- ESC to close
    if not tContains(UISpecialFrames, "PedroMainUI") then
        table.insert(UISpecialFrames, "PedroMainUI")
	end
	
    f:SetSize(350, 420)
    f:SetPoint("CENTER")
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
	
    f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    f.title:SetPoint("TOP", 0, -5)
    f.title:SetText("Pedro Settings")
	
	-- Enable Pedro checkbox
	local enableCB = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
	enableCB:SetPoint("TOPLEFT", 15, -25)
	enableCB.text:SetText("Enable Pedro - Turns on/off the entire addon")
	enableCB:SetChecked(G.enabled)
	enableCB:SetScript("OnClick", function(self)
		G.enabled = self:GetChecked()
		print("Pedro: " .. (G.enabled and "Enabled" or "Disabled"))
	end)
	
	-- Enable Animation checkbox
	local animCB = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
	animCB:SetPoint("TOPLEFT", enableCB, "BOTTOMLEFT", 0, -2)
	animCB.text:SetText("Enable Animation")
	animCB:SetChecked(not G.disableAnimation)
	animCB:SetScript("OnClick", function(self)
		G.disableAnimation = not self:GetChecked()
		print("Pedro: Animation " .. (G.disableAnimation and "disabled" or "enabled"))
	end)
	
	-- Sound selection
	local soundLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	soundLabel:SetPoint("TOPLEFT", animCB, "BOTTOMLEFT", 0, -6)
	soundLabel:SetText("Sound:")
	
	PedroMainUI.soundLabel = soundLabel
	-- RebuildSoundList() 
	
	-- Add Song button (opens the custom song popup)
	local addSongBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
	addSongBtn:SetSize(100, 22)
	addSongBtn:SetPoint("LEFT", soundLabel, "RIGHT", 10, 0)
	addSongBtn:SetText("Add Song")
	addSongBtn:SetScript("OnClick", function()
		ShowAddSongWindow()
	end)
	
	RefreshSoundListUI()
	ResizePedroMainUI()
	
	-- Audio channel selection
	local channelLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	local lastButton = PedroMainUI.soundButtons[#PedroMainUI.soundButtons]
	channelLabel:SetPoint("TOPLEFT", lastButton, "BOTTOMLEFT", 0, -6)
	channelLabel:SetText("Audio Channel:")
	
	PedroMainUI.channelLabel = channelLabel 
	local previous = channelLabel
	
	local channelButtons = {}
	for i, channel in ipairs(PedroAudioChannels) do
		local btn = CreateFrame("CheckButton", nil, f, "UIRadioButtonTemplate")
		btn:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -4)
		previous = btn
		btn.text:SetText(channel.name)
		
		if G.audioChannel == channel.value then
			btn:SetChecked(true)
		end
		
		btn:SetScript("OnClick", function(self)
			if not self:GetChecked() then
				self:SetChecked(true)
				return
			end
			
			for _, other in ipairs(channelButtons) do
				if other ~= self then other:SetChecked(false) end
			end
			
			G.audioChannel = channel.value
			pedroAudioChannel = channel.value
			print("Pedro: Audio channel set to " .. channel.name)
		end)
		
		table.insert(channelButtons, btn)
	end
	
	-- Reset Audio Channel button
	local resetBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
	resetBtn:SetSize(140, 22)
	resetBtn:SetPoint("TOPLEFT", channelButtons[#channelButtons], "BOTTOMLEFT", 0, -6)
	resetBtn:SetText("Reset Audio Channel")
	
	resetBtn:SetScript("OnClick", function()
		-- Reset saved variables
		G.audioChannel = "Master"
		pedroAudioChannel = "Master"
		print("Pedro: Audio channel reset to Master")
		
		-- Update the radio buttons visually
		for i, channel in ipairs(PedroAudioChannels) do
			local isMaster = (channel.value == "Master")
			channelButtons[i]:SetChecked(isMaster)
		end
	end)
	
	-- Animation Speed
	local speedLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	speedLabel:SetPoint("TOPLEFT", resetBtn, "BOTTOMLEFT", 0, -6)
	speedLabel:SetText("Animation Speed:")
	
	local speeds = {
		{label = "Slow",   value = 0.30},
		{label = "Normal", value = 0.15},
		{label = "Fast",   value = 0.10},
		{label = "Turbo",  value = 0.05},
	}
	
	local previous = speedLabel
	local speedButtons = {}
	
	for i, s in ipairs(speeds) do
		local btn = CreateFrame("CheckButton", nil, f, "UIRadioButtonTemplate")
		
		btn:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -4)
		previous = btn
		
		btn.text:SetText(s.label)
		
		if G.animationSpeed == s.value then
			btn:SetChecked(true)
		end
		
		btn:SetScript("OnClick", function(self)
			-- prevent unchecking the selected radio button
			if not self:GetChecked() then
				self:SetChecked(true)
				return
			end
			
			-- uncheck all other radio buttons
			for _, other in ipairs(speedButtons) do
				if other ~= self then
					other:SetChecked(false)
				end
			end
			
			G.animationSpeed = s.value
			print("Pedro: Animation speed set to " .. s.label)
		end)
		
		table.insert(speedButtons, btn)
	end
	
	-- Position Animation button
	local posBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
	posBtn:SetSize(140, 22)
	posBtn:SetPoint("TOPLEFT", speedButtons[#speedButtons], "BOTTOMLEFT", 0, -6)
	posBtn:SetText("Position Animation")
	
	posBtn:SetScript("OnClick", function()
		if InCombatLockdown() then
			print("Pedro: Leave combat to move the animation.")
			return
		end
		
		-- If already positioning, clicking again should save + close
		if PedroPositioningMode then
			local point, _, relativePoint, xOfs, yOfs = PedroAnimationFrame:GetPoint()
			G.animPoint = { point = point, relativePoint = relativePoint, x = xOfs, y = yOfs }
			
			PedroPositioningMode = false
			PedroAnimationFrame:SetAlpha(0)
			PedroAnimationFrame:EnableMouse(false)
			
			if PedroAnimationFrame.closeBtn then
				PedroAnimationFrame.closeBtn:EnableMouse(false)
				PedroAnimationFrame.closeBtn:Hide()
			end
			
			print("Pedro: Animation position saved.")
			return
		end
		
		-- Otherwise: enter positioning mode
		PedroPositioningMode = true
		PedroAnimationFrame:SetAlpha(1)
		PedroAnimationFrame:Raise()
		PedroAnimationFrame:EnableMouse(true)
		
		-- Create or re-enable the X button
		if not PedroAnimationFrame.closeBtn then
			local closeBtn = CreateFrame("Button", nil, PedroAnimationFrame, "UIPanelCloseButton")
			closeBtn:SetPoint("TOPRIGHT", PedroAnimationFrame, "TOPRIGHT", 0, 0)
			closeBtn:SetScript("OnClick", function()
				local point, _, relativePoint, xOfs, yOfs = PedroAnimationFrame:GetPoint()
				G.animPoint = { point = point, relativePoint = relativePoint, x = xOfs, y = yOfs }
				
				PedroPositioningMode = false
				PedroAnimationFrame:SetAlpha(0)
				PedroAnimationFrame:EnableMouse(false)
				closeBtn:EnableMouse(false)
				closeBtn:Hide()
			end)
			PedroAnimationFrame.closeBtn = closeBtn
			else
			PedroAnimationFrame.closeBtn:EnableMouse(true)
			PedroAnimationFrame.closeBtn:Show()
		end
		
		print("Pedro: Drag the animation. Click X or press the button again to finish.")
	end)
	
	
	-- Reset Animation Position button
	local resetPosBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
	resetPosBtn:SetSize(160, 22)
	resetPosBtn:SetPoint("TOPLEFT", posBtn, "BOTTOMLEFT", 0, -6)
	resetPosBtn:SetText("Reset Animation Position")
	resetPosBtn:SetScript("OnClick", function()
		PedroAnimationFrame:ClearAllPoints()
		PedroAnimationFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 100, -120)
		G.animPoint = { point = "TOPLEFT", relativePoint = "TOPLEFT", x = 100, y = -120 }
		print("Pedro: Animation position reset.")
	end)
	
	-- Play Pedro Now button
	local playBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
	playBtn:SetSize(140, 22)
	playBtn:SetPoint("TOPLEFT", resetPosBtn, "BOTTOMLEFT", 0, -6)
	playBtn:SetText("Play Pedro Now")
	playBtn:SetScript("OnClick", TryPlayPedroManual)
	
	--- Version label anchored to Play button
	f.version = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
	f.version:SetPoint("TOPLEFT", playBtn, "BOTTOMLEFT", 0, -8)
	f.version:SetJustifyH("LEFT")
	f.version:SetText("Version: " .. ADDON_VERSION)
	
	-- Ensure the frame is tall enough to fit everything
	C_Timer.After(0, function()
		if not f or not f:IsShown() then
			f:Show()
		end
		
		local top = f:GetTop()
		local bottom = f.version:GetBottom() or f:GetBottom()
		if top and bottom then
			local neededHeight = math.ceil(top - bottom + 18) -- 18px padding
			if (f:GetHeight() or 0) < neededHeight then
				f:SetHeight(neededHeight)
			end
		end
	end)
	
	
	f:Show()
	
	-- Safe resize after layout
	--[[
		f:SetScript("OnUpdate", function(self)
		local top = self:GetTop()
		local bottom = playBtn:GetBottom()
		if top and bottom then
		self:SetHeight(top - bottom + 30)
		self:SetScript("OnUpdate", nil)
		end
	end) ]]
end

-- Minimap icon setup
local LDB  = LibStub("LibDataBroker-1.1")
local LDBI = LibStub("LibDBIcon-1.0")

-- Create dropdown
if not PedroDropdown then
	PedroDropdown = CreateFrame("Frame", "PedroDropdown", UIParent, "UIDropDownMenuTemplate")
end

local PedroLDB = LDB:NewDataObject("Pedro", {
	type  = "launcher",
	icon  = "Interface\\AddOns\\Pedro\\Media\\Pedro.tga",
	label = "Pedro",
	
	OnClick = function(_, button)
		if button == "LeftButton" then
			if IsControlKeyDown() then
				SlashCmdList.PEDRODEBUG()
				else
				ShowPedroMainUI()
			end
			
			elseif button == "RightButton" then
			local dropdown = PedroDropdown
			
			UIDropDownMenu_Initialize(dropdown, function(self, level, menuList)
				-- LEVEL 1
				if level == 1 then
					local info
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "Play Pedro Now"
					info.func = TryPlayPedroManual
					info.notCheckable = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "Select Song"
					info.func = ShowSoundFrame
					info.notCheckable = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "Select Audio Channel"
					info.func = ShowAudioChannelFrame
					info.notCheckable = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "Reset Audio Channel"
					info.func = function()
						G.audioChannel = "Master"
						pedroAudioChannel = "Master"
						print("Pedro: Audio channel reset to Master")
					end
					info.notCheckable = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = G.enabled and "Disable Pedro" or "Enable Pedro"
					info.notCheckable = true
					info.func = function()
						G.enabled = not G.enabled
						print("Pedro: " .. (G.enabled and "Enabled" or "Disabled"))
					end
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = G.disableAnimation and "Enable Animation" or "Disable Animation"
					info.func = function()
						G.disableAnimation = not G.disableAnimation
						print("Pedro: Animation " .. (G.disableAnimation and "disabled" or "enabled"))
					end
					info.notCheckable = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "Position Animation"
					info.notCheckable = true
					info.func = function()
						if InCombatLockdown() then
							print("Pedro: Leave combat to move the animation.")
							return
						end
						
						PedroPositioningMode = true
						PedroAnimationFrame:SetAlpha(1)
						PedroAnimationFrame:Raise()
						PedroAnimationFrame:EnableMouse(true)
						
						if PedroAnimationFrame.closeBtn then
							PedroAnimationFrame.closeBtn:EnableMouse(true)
						end
						
						print("Pedro: Drag the animation to position it. Click the X to finish positioning.")
						
						if not PedroAnimationFrame.closeBtn then
							local closeBtn = CreateFrame("Button", nil, PedroAnimationFrame, "UIPanelCloseButton")
							closeBtn:SetPoint("TOPRIGHT", PedroAnimationFrame, "TOPRIGHT", 0, 0)
							closeBtn:SetScript("OnClick", function()
								local point, _, relativePoint, xOfs, yOfs = PedroAnimationFrame:GetPoint()
								G.animPoint = { point = point, relativePoint = relativePoint, x = xOfs, y = yOfs }
								
								PedroPositioningMode = false
								PedroAnimationFrame:SetAlpha(0)
								PedroAnimationFrame:EnableMouse(false)
								
								if PedroAnimationFrame.closeBtn then
									PedroAnimationFrame.closeBtn:EnableMouse(false)
								end
							end)
							PedroAnimationFrame.closeBtn = closeBtn
						end
						
						PedroAnimationFrame:SetMovable(true)
						PedroAnimationFrame:RegisterForDrag("LeftButton")
						PedroAnimationFrame:SetScript("OnDragStart", function(self)
							if InCombatLockdown() then return end
							self:StartMoving()
						end)
						PedroAnimationFrame:SetScript("OnDragStop", function(self)
							self:StopMovingOrSizing()
							local point, _, relativePoint, xOfs, yOfs = self:GetPoint()
							G.animPoint = { point = point, relativePoint = relativePoint, x = xOfs, y = yOfs }
						end)
					end
					UIDropDownMenu_AddButton(info, level)
					info = UIDropDownMenu_CreateInfo()
					info.text = "Animation Speed"
					info.hasArrow = true
					info.menuList = "ANIM_SPEED"
					info.notCheckable = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "Reset Animation Position"
					info.notCheckable = true
					info.func = function()
						PedroAnimationFrame:ClearAllPoints()
						PedroAnimationFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 100, -120)
						G.animPoint = { point = "TOPLEFT", relativePoint = "TOPLEFT", x = 100, y = -120 }
						print("Pedro: Animation position reset near top-left.")
					end
					UIDropDownMenu_AddButton(info, level)
				end
				
				-- LEVEL 2: 
				if level == 2 and menuList == "ANIM_SPEED" then
					local info
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "  Slow"
					info.func = function()
						G.animationSpeed = 0.30
						print("Pedro: Animation speed set to Slow")
						CloseDropDownMenus() 
					end
					info.checked = (G.animationSpeed == 0.30)
					info.closeWhenClicked = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "  Normal"
					info.func = function()
						G.animationSpeed = 0.15
						print("Pedro: Animation speed set to Normal")
						CloseDropDownMenus() 
					end
					info.checked = (G.animationSpeed == 0.15)
					info.closeWhenClicked = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "  Fast"
					info.func = function()
						G.animationSpeed = 0.10
						print("Pedro: Animation speed set to Fast")
						CloseDropDownMenus() 
					end
					info.checked = (G.animationSpeed == 0.10)
					info.closeWhenClicked = true
					UIDropDownMenu_AddButton(info, level)
					
					info = UIDropDownMenu_CreateInfo()
					info.text = "  Turbo"
					info.func = function()
						G.animationSpeed = 0.05
						print("Pedro: Animation speed set to Turbo")
						CloseDropDownMenus() 
					end
					info.checked = (G.animationSpeed == 0.05)
					info.closeWhenClicked = true
					UIDropDownMenu_AddButton(info, level)
				end
				
			end, "MENU") --
			-- Clear old watcher
			dropdown:SetScript("OnUpdate", nil)
			
			ToggleDropDownMenu(1, nil, dropdown, "cursor", 0, 0)
			
			local openTime = GetTime()
			local leaveTime = nil
			
			local function CursorOver(frame, padding)
				if not frame or not frame:IsShown() then return false end
				
				local scale = frame:GetEffectiveScale()
				local left   = frame:GetLeft()
				local right  = frame:GetRight()
				local bottom = frame:GetBottom()
				local top    = frame:GetTop()
				
				if not left or not right or not top or not bottom then
					return false
				end
				
				local cx, cy = GetCursorPosition()
				cx, cy = cx / scale, cy / scale
				
				padding = padding or 0
				
				return cx >= (left - padding)
				and cx <= (right + padding)
				and cy >= (bottom - padding)
				and cy <= (top + padding)
			end
			
			dropdown:SetScript("OnUpdate", function(self)
				local menu1 = _G["DropDownList1"]
				local menu2 = _G["DropDownList2"]
				
				if not menu1 or not menu1:IsShown() then
					self:SetScript("OnUpdate", nil)
					return
				end
				
				-- Delay to allow Blizzard to anchor the menu
				if GetTime() - openTime < 0.50 then return end
				
				local over1 = CursorOver(menu1, 25)
				local over2 = CursorOver(menu2, 25)
				
				if not over1 and not over2 then
					leaveTime = leaveTime or GetTime()
					
					if GetTime() - leaveTime > 0.2 then
						CloseDropDownMenus()
						self:SetScript("OnUpdate", nil)
					end
					else
					leaveTime = nil
				end
			end)
			
		end
	end,
	
	OnTooltipShow = function(tt)
		tt:AddLine("Pedro")
		tt:AddLine("Version: " .. ADDON_VERSION)
		tt:AddLine("Left-Click Pedro UI Options")
		tt:AddLine("Control+Left-Click: Pedro Debug Information")
		tt:AddLine("Right-Click: Drop Down Options")
	end,
})

-- Register with LibDBIcon
LDBI:Register("Pedro", PedroLDB, PedroDB_Global)
LDBI:Show("Pedro")