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

-- Ensure both DB tables exist
PedroDB_Global = PedroDB_Global or {}
PedroDB_Char   = PedroDB_Char   or {}

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

-- Define PedroSounds
local PedroSounds = {
    {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},
}

-- Global defaults
--G.selectedSound    = G.selectedSound    or PedroSounds[1].path
--G.audioChannel     = G.audioChannel     or "Master"
--G.animPoint        = G.animPoint        or nil
--G.disableAnimation = G.disableAnimation or false

-- Song length lookup table 
local PedroSongLengths = {}

for _, sound in ipairs(PedroSounds) do
    if sound.path and sound.duration then
        PedroSongLengths[sound.path] = sound.duration
	end
end

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


local animationTimer = 0
local frameDuration = 0.15
local currentFrame = 1
local elapsedTime = 0
local isAnimating = false
local lustTriggered = false
-- local currentPedroSongLength = nil


function StartAnimation(songLength)
    if not songLength or songLength <= 0 then
        songLength = 10
	end
    
    if isAnimating then
        return
	end
    
    isAnimating = true
    PedroAnimationFrame:SetAlpha(1)
    
    animationTimer = 0
    elapsedTime = 0
    currentFrame = 1
    
    -- 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
    
    -- Where the icons actually are
    --local activeWidth  = numCols * cellSize -- 772
    --local activeHeight = numRows * cellSize -- 1544
    
    -- 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 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 animationTimer >= songLength then
            PedroAnimationFrame:SetAlpha(0)
            PedroAnimationFrame:EnableMouse(false)
            if PedroAnimationFrame.closeBtn then
                PedroAnimationFrame.closeBtn:EnableMouse(false)
			end
			
            isAnimating = false
            PedroAnimationFrame:SetScript("OnUpdate", nil)
		end
	end)
end
--SAFE
-- 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 suppressPedro = false
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
--SAFE
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
	
	pedroPlayingID = PlaySoundFile(G.selectedSound, pedroAudioChannel)
	
	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()
    -- Skip in Edit Mode
    if EditModeManager and EditModeManager:ShouldIgnoreUnitEvents() then
        return false
    end

    if not AuraUtil then
        return false
    end

    local found = false

    AuraUtil.ForEachAura("player", "HARMFUL", nil, function(...)
        local _, _, _, _, duration, expirationTime, _, _, _, spellID = ...

        if lustDebuffs[spellID] then
            -- Calculate remaining time
            local timeLeft = 0
            if expirationTime and expirationTime > 0 then
                timeLeft = expirationTime - GetTime()
            end

            -- Block Pedro if debuff is nearly expired
            if timeLeft < 570 then
                return true -- stop scanning, but treat as NOT found
            end

            found = true
            return true -- stop scanning
        end
    end)

    lustActive = found
    return found
end
--safe

local function GetDebuffTimeLeft(spellID)
    local timeLeft = 0

    AuraUtil.ForEachAura("player", "HARMFUL", nil, function(...)
        local _, _, _, _, duration, expirationTime, _, _, _, id = ...
        if id == spellID then
            if expirationTime and expirationTime > 0 then
                timeLeft = expirationTime - GetTime()
            end
            return true
        end
    end)

    return timeLeft
end

-- Central trigger for Pedro based on debuffs
local function TryPlayPedro()
	if suppressPedro then
    return false
end
    local songLength = GetSelectedSongLength()
    local played = false

    -- Check harmful debuffs
    local hasDebuff = CheckLustDebuffByID()
    lustActive = hasDebuff

    if hasDebuff then
        -- Only trigger Pedro if not already animating
        if not isAnimating then
            local playedSound = PlayPedroIfAllowed()
            if playedSound and not G.disableAnimation then
                StartAnimation(songLength)
            end
            played = playedSound
        end
    else
        -- No debuff: reset state
        if not isAnimating then
            lustActive = false
        end
    end

    return played
end
--safe

-- Manual play
local function TryPlayPedroManual()
	PlayPedroIfAllowed(true)
	print("Pedro sound played manually!")
	
	if not G.disableAnimation then
		local songLength = GetSelectedSongLength()
		StartAnimation(songLength)
	end
end


-- Show Sound Selection Frame
local function ShowSoundFrame()
	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							   
--safe

-- Show Audio Channel Selection Frame 
local function ShowAudioChannelFrame()
	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
--safe

--[[
-- Help / Read Me Frame
local function ShowPedroHelpFrame()
	-- If the frame already exists, just show it and reset scroll
	if PedroHelpFrame then
		PedroHelpFrame:Show()
		
		local scrollFrame = PedroHelpFrame.scrollFrame
		if scrollFrame then
			scrollFrame:UpdateScrollChildRect()
			scrollFrame:SetVerticalScroll(0)
		end
		
		return
	end
	
	-- Main frame
	local f = CreateFrame("Frame", "PedroHelpFrame", UIParent, "BasicFrameTemplateWithInset")
	f:SetSize(520, 420)
	f:SetPoint("CENTER")
	f:SetMovable(true)
	f:EnableMouse(true)
	f:RegisterForDrag("LeftButton")
	f:SetScript("OnDragStart", f.StartMoving)
	f:SetScript("OnDragStop", f.StopMovingOrSizing)
	
	-- Title
	f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
	f.title:SetPoint("CENTER", f.TitleBg, "CENTER", 0, 0)
	f.title:SetText("Pedro / Help / Information")
	
	-- Scroll frame
	local scrollFrame = CreateFrame("ScrollFrame", nil, f, "UIPanelScrollFrameTemplate")
	scrollFrame:SetPoint("TOPLEFT", 12, -36)
	scrollFrame:SetPoint("BOTTOMRIGHT", -30, 44)
	
	-- Content box
	local editBox = CreateFrame("EditBox", nil, scrollFrame)
	editBox:SetMultiLine(true)
	editBox:SetFontObject("GameFontHighlight")
	editBox:SetWidth(460)
	editBox:SetAutoFocus(false)
	editBox:EnableMouse(false) -- fully read-only
	
	-- Load help text
	if PedroHelpText and PedroHelpText ~= "" then
		editBox:SetText(PedroHelpText)
		else
		editBox:SetText("Help text missing. Please check if the README text is correctly loaded.")
	end
	
	-- Disable editing
	editBox:SetEnabled(false)
	
	-- Attach editBox to scrollFrame
	scrollFrame:SetScrollChild(editBox)
	
	-- Update scroll region when text changes
	editBox:SetScript("OnTextChanged", function(self)
		scrollFrame:UpdateScrollChildRect()
	end)
	
	-- Close button
	local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
	closeButton:SetSize(80, 22)
	closeButton:SetPoint("BOTTOM", 0, 12)
	closeButton:SetText("Close")
	closeButton:SetScript("OnClick", function()
		f:Hide()
	end)
	
	-- Show frame first
	f:Show()
	
	-- Reset scroll to top
	scrollFrame:UpdateScrollChildRect()
	scrollFrame:SetVerticalScroll(0)
	
	-- Save reference for reopen resets
	f.scrollFrame = scrollFrame
end
]]--


-- /Pedro debug command
SLASH_PEDRO1 = "/pedro"
SlashCmdList.PEDRO = 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 pedroStatus = lustActive and "Active" or "Inactive"

    print(string.format(
        "Pedro Debug Info: Status: %s | Sound: %s | Channel: %s",
        pedroStatus,
        soundName,
        audioChannel
    ))
end
--safe
-- Main Pedro event frame
local f = CreateFrame("Frame")
f:RegisterEvent("ADDON_LOADED")
f:RegisterEvent("PLAYER_ENTERING_WORLD")
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

        -- Global defaults
        if G.selectedSound == nil then
            G.selectedSound = PedroSounds[1].path
        end
        if G.audioChannel == nil then
            G.audioChannel = "Master"
        end
        if G.disableAnimation == nil then
            G.disableAnimation = false
        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")
        end

        -- Set size and position
        PedroAnimationFrame:SetSize(128, 128)
        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 entering world
    elseif event == "PLAYER_ENTERING_WORLD" then
    suppressPedro = true
    C_Timer.After(20, function() suppressPedro = false end)



    -- Player auras changed
    elseif event == "UNIT_AURA" then
        if arg1 == "player" then
            if not InCombatLockdown() then
                TryPlayPedro()
            end
        end



    -- Entering combat
    elseif event == "PLAYER_REGEN_DISABLED" then
        if tickerInCombat then
            tickerInCombat:Cancel()
            tickerInCombat = nil
        end

        tickerInCombat = C_Timer.NewTicker(1.0, TryPlayPedro)



    -- Leaving combat
    elseif event == "PLAYER_REGEN_ENABLED" then
        if tickerInCombat then
            tickerInCombat:Cancel()
            tickerInCombat = nil
        end

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

local PedroLDB = LDB:NewDataObject("Pedro", {
    type = "launcher",
    icon = "Interface\\AddOns\\Pedro\\Media\\Pedro.tga",
    label = "Pedro",
    OnClick = function(_, button)
        if button == "LeftButton" then
            -- Show Pedro/Sound info
            SlashCmdList.PEDRO()
        elseif button == "RightButton" then
            local dropdown = CreateFrame("Frame", "PedroDropdown", UIParent, "UIDropDownMenuTemplate")
            UIDropDownMenu_Initialize(dropdown, function(self, level)
                if level == 1 then
                    UIDropDownMenu_AddButton({text = "Play Pedro Now", func = TryPlayPedroManual})
                    UIDropDownMenu_AddButton({text = "Select Song", func = ShowSoundFrame})
                    UIDropDownMenu_AddButton({text = "Select Audio Channel", func = ShowAudioChannelFrame})
                    UIDropDownMenu_AddButton({text = "Reset Audio Channel", func = function()
                        G.audioChannel = "Master"
                        pedroAudioChannel = "Master"
                        print("Pedro: Audio channel reset to Master")
                    end})
                    UIDropDownMenu_AddButton({
                        text = G.disableAnimation and "Enable Animation" or "Disable Animation",
                        func = function()
                            G.disableAnimation = not G.disableAnimation
                            print("Pedro: Animation " .. (G.disableAnimation and "disabled" or "enabled"))
                        end
                    })
                    UIDropDownMenu_AddButton({
                        text = "Position Animation",
                        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, relativeTo, 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: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)
                        end
                    })
                    UIDropDownMenu_AddButton({
                        text = "Reset Animation Position",
                        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({
                        text = "Help / Info / Read Me",
                        func = ShowPedroHelpFrame
                    })
					]]--
                end
            end)
            ToggleDropDownMenu(1, nil, dropdown, "cursor", 0, 0)
        end
    end,
    OnTooltipShow = function(tt)
        tt:AddLine("Pedro")
        tt:AddLine("Left-Click: Pedro/Sound Information")
        tt:AddLine("Right-Click: Options")
    end,
})

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