local mod	= DBM:NewMod(2659, "DBM-Party-Midnight", 3, 1300)
--local L		= mod:GetLocalizedStrings()--Nothing to localize for blank mods

mod:SetRevision("20260418051832")
mod:SetCreatureID(231861)--Iffy, doesn't report as instance boss
mod:SetEncounterID(3071)
--mod:SetHotfixNoticeRev(20250823000000)
--mod:SetMinSyncRevision(20250823000000)
mod:SetZone(2811)
mod.respawnTime = 29

mod:RegisterCombat("combat")

local warnEtherealShackles				= mod:NewCountAnnounce(1214038, 2)

local specWarnRefuelingProtocol			= mod:NewSpecialWarningCount(474345, nil, nil, nil, 2, 2)
local specWarnRepulsingSlam				= mod:NewSpecialWarningCount(474496, nil, nil, nil, 1, 2)
local specWarnArcaneExpulsion			= mod:NewSpecialWarningCount(1214081, nil, 28405, nil, 2, 2)

local timerRefuelingProtocolCD			= mod:NewCDCountTimer(20.5, 474345, nil, nil, nil, 6, nil, DBM_COMMON_L.IMPORTANT_ICON)
local timerRepulsingSlamCD				= mod:NewCDCountTimer(20.5, 474496, 182557, nil, nil, 5, nil, DBM_COMMON_L.TANK_ICON)--Short Text "Slam"
local timerEtherealShacklesCD			= mod:NewCDCountTimer(20.5, 1214038, DBM_COMMON_L.DISPELS.." (%s)", nil, nil, 3, nil, DBM_COMMON_L.MAGIC_ICON)
local timerArcaneExpulsionCD			= mod:NewCDCountTimer(20.5, 1214081, 28405, nil, nil, 2)--Short text "Knockback"

mod:AddPrivateAuraSoundOption(1214089, true, 1214089, 1, 2, "watchfeet", 8)--Arcane Residue (GTFO)
mod:AddPrivateAuraSoundOption(1214038, true, 1214038, 1, 1, "debuffyou", 17)--Ethereal Shackles

mod.vb.protocolCount = 0
mod.vb.slamCount = 0
mod.vb.shacklesCount = 0
mod.vb.expulsionCount = 0
local badStateDetected = false

---@param self DBMMod
local function setFallback(self)
	--Blizz API fallbacks
	specWarnRefuelingProtocol:SetAlert(281, "catchballs", 12, 3)
	if self:IsTank() then
		specWarnRepulsingSlam:SetAlert(286, "carefly", 2, 2)
	end
	specWarnArcaneExpulsion:SetAlert(288, "carefly", 2, 3)
	timerRefuelingProtocolCD:SetTimeline(281)
	timerRepulsingSlamCD:SetTimeline(286)
	timerEtherealShacklesCD:SetTimeline(287)
	timerArcaneExpulsionCD:SetTimeline(288)
end

function mod:OnLimitedCombatStart()
	self:TLCountReset()
	self.vb.protocolCount = 1
	self.vb.slamCount = 1
	self.vb.shacklesCount = 1
	self.vb.expulsionCount = 1
	if self:IsMythicPlus() and DBM.Options.HardcodedTimer and not badStateDetected then
		self:IgnoreBlizzardAPI()
		self:RegisterShortTermEvents(
			"ENCOUNTER_TIMELINE_EVENT_ADDED",
			"ENCOUNTER_TIMELINE_EVENT_STATE_CHANGED"
		)
	else
		setFallback(self)
	end
end

function mod:OnCombatEnd()
	self:TLCountReset()
	self:UnregisterShortTermEvents()
end

do
	---@param self DBMMod
	---@param timer number
	---@param timerExact number
	---@param eventID number
	local function timersAll(self, timer, timerExact, eventID)
		--Logic confirmed against M+ only. Normal, Heroic, and M0 not covered
		if timer > 900 then--Ignored long placeholder artifacts seen in logged pull
			return
		elseif timer == 48 then--Ignored protocol/reset artifact seen in logged pull (always canceled early)
			return
		elseif timer == 45 then--Refueling Protocol
			timerRefuelingProtocolCD:TLStart(timerExact, eventID, self:TLCountStart(eventID, "protocol", "protocolCount"))
		elseif timer == 5 or timer == 6 or timer == 7 then--Repulsing Slam opener after pull/refuel (state 1 can round to 7)
			timerRepulsingSlamCD:TLStart(timerExact, eventID, self:TLCountStart(eventID, "slam", "slamCount"))
		elseif timer == 15 or timer == 16 or timer == 17 then--Arcane Expulsion opener after pull/refuel (state 1 can round to 17)
			timerArcaneExpulsionCD:TLStart(timerExact, eventID, self:TLCountStart(eventID, "expulsion", "expulsionCount"))
		elseif timer == 22 then--Ethereal Shackles real cast
			timerEtherealShacklesCD:TLStart(timerExact, eventID, self:TLCountStart(eventID, "shackles", "shacklesCount"))
		elseif timer == 23 then--Repulsing Slam (22.5) or Arcane Expulsion (23.0)
			if timerExact < 22.75 then
				timerRepulsingSlamCD:TLStart(timerExact, eventID, self:TLCountStart(eventID, "slam", "slamCount"))
			else
				timerArcaneExpulsionCD:TLStart(timerExact, eventID, self:TLCountStart(eventID, "expulsion", "expulsionCount"))
			end
		else--Reached end of chain without finding a valid timer, this means hardcode mod has failed, so we need to disable hardcoded features and fall back to blizz API
			if not DBM.Options.DebugMode then
				badStateDetected = true
				self:ResumeBlizzardAPI()
				self:UnregisterShortTermEvents()
				setFallback(self)
				DBM:Debug("|cffff0000Failed to match encounter timeline events to expected timers, falling back to Blizzard API|r", nil, nil, nil, true)
			else
				DBM:Debug("|cffff0000Failed to match encounter timeline events to expected timers|r", nil, nil, nil, true)
			end
		end
	end
	--Note, bar state changing and canceling is handled by core
	function mod:ENCOUNTER_TIMELINE_EVENT_ADDED(eventInfo)
		if eventInfo.source ~= 0 then return end
		local eventID = eventInfo.id
		local timerExact = eventInfo.duration
		local timer = math.floor(timerExact + 0.5)
		if not badStateDetected then
			timersAll(self, timer, timerExact, eventID)
		end
	end

	function mod:ENCOUNTER_TIMELINE_EVENT_STATE_CHANGED(eventID)
		local eventState = C_EncounterTimeline.GetEventState(eventID)
		if not eventID or not eventState then return end
		if eventState == 2 then
			local eventType, eventCount = self:TLCountFinish(eventID)
			if eventType and eventCount then
				if eventType == "protocol" then
					specWarnRefuelingProtocol:Show(eventCount)
					specWarnRefuelingProtocol:Play("catchballs")
				elseif eventType == "slam" then
					if self:IsTank() then
						specWarnRepulsingSlam:Show(eventCount)
						specWarnRepulsingSlam:Play("carefly")
					end
				elseif eventType == "shackles" then
					warnEtherealShackles:Show(eventCount)
				elseif eventType == "expulsion" then
					specWarnArcaneExpulsion:Show(eventCount)
					specWarnArcaneExpulsion:Play("carefly")
				end
			end
		elseif eventState == 3 then
			self:TLCountCancel(eventID)
		end
	end
end
