local mod	= DBM:NewMod(2424, "DBM-CastleNathria", nil, 1190)
local L		= mod:GetLocalizedStrings()

mod:SetRevision("20220202021226")
mod:SetCreatureID(167406)
mod:SetEncounterID(2407)
mod:SetUsedIcons(1, 2, 3, 4, 7, 8)
mod:SetHotfixNoticeRev(20210202000000)--2021, 02, 02
mod:SetMinSyncRevision(20201227000000)
mod.respawnTime = 29

mod:RegisterCombat("combat")

mod:RegisterEventsInCombat(
	"SPELL_CAST_START 326707 326851 327227 328117 329181 333932 344776",
	"SPELL_CAST_SUCCESS 327796 329943 339196 330042 326005 332849 333980 332619 329181 333979",
	"SPELL_AURA_APPLIED 326699 338510 327039 327796 327992 329906 332585 329951 332794 329181 344313 338738 181089",
	"SPELL_AURA_APPLIED_DOSE 326699 329906 332585",
	"SPELL_AURA_REMOVED 326699 338510 327039 327796 328117 329951 332794 338738",
	"SPELL_AURA_REMOVED_DOSE 326699",
	"SPELL_PERIODIC_DAMAGE 327992",
	"SPELL_PERIODIC_MISSED 327992",
	"UNIT_DIED",
	"UNIT_SPELLCAST_SUCCEEDED boss1 boss2 boss3 boss4 boss5"
)

--TODO, any reason to track https://shadowlands.wowhead.com/spell=328839 ? gained each ravage cast
--TODO, https://shadowlands.wowhead.com/spell=336008/smoldering-ire need anything special?
--TODO, verify spellIds for two different blood prices, and make sure there isn't overlap/double triggering for any of them
--TODO, handling of https://www.wowhead.com/spell=341391/searing-censure 5 second loop timer
--TODO, likely doing not enough for tank stuff in terms of warnings, probably have to confur with some tanks on best approach
--[[
(ability.id = 326707 or ability.id = 326851 or ability.id = 327227 or ability.id = 328117 or ability.id = 329181 or ability.id = 333932) and type = "begincast"
 or (ability.id = 327796 or ability.id = 329943 or ability.id = 339196 or ability.id = 330042 or ability.id = 326005 or ability.id = 332849 or ability.id = 333980 or ability.id = 332619 or ability.id = 327039 or ability.id = 333979) and type = "cast"
 or (ability.id = 327039 or ability.id = 332794) and type = "applydebuff"
 or ability.id = 328117
 or (source.type = "NPC" and source.firstSeen = timestamp) or (target.type = "NPC" and target.firstSeen = timestamp)
--]]
--General
local warnPhase									= mod:NewPhaseChangeAnnounce(2, nil, nil, nil, nil, nil, 2)

mod:AddInfoFrameOption(nil, true)
--Stage One: Sinners Be Cleansed
mod:AddTimerLine(DBM:EJ_GetSectionInfo(22016))
local warnBloodPrice							= mod:NewCountAnnounce(326851, 4)
local warnFeedingTime							= mod:NewTargetAnnounce(327039, 2)--On this difficulty you don't need to help soak it so don't really NEED to know who it's on
local warnNightHunter							= mod:NewTargetNoFilterAnnounce(327796, 4)--General announce, if target special warning not enabled

local specWarnCleansingPain						= mod:NewSpecialWarningCount(326707, nil, nil, nil, 2, 2)
local specWarnFeedingTime						= mod:NewSpecialWarningMoveAway(327039, nil, nil, nil, 1, 2)--Normal/LFR
local yellFeedingTime							= mod:NewYell(327039)--Normal/LFR
local yellFeedingTimeFades						= mod:NewFadesYell(327039)--Normal/LFR
local specWarnNightHunter						= mod:NewSpecialWarningYouPos(327796, nil, nil, nil, 1, 2, 3)--Heroic/Mythic
local yellNightHunter							= mod:NewShortPosYell(327796)--Heroic/Mythic (not red on purpose, you do NOT want to be anywhere near victim, you want to soak the line before victim)
local yellNightHunterFades						= mod:NewIconFadesYell(327796)--Heroic/Mythic (not red on purpose, you do NOT want to be anywhere near victim, you want to soak the line before victim)
local specWarnNightHunterTarget					= mod:NewSpecialWarningTarget(327796, false, nil, nil, 1, 2, 3)--Opt in, for people who are assigned to this soak
local specWarnCommandRavage						= mod:NewSpecialWarningCount(327227, nil, 327122, nil, 2, 2)
--local specWarnMindFlay						= mod:NewSpecialWarningInterrupt(310552, "HasInterrupt", nil, nil, 1, 2)
local specWarnGTFO								= mod:NewSpecialWarningGTFO(327992, nil, nil, nil, 1, 8)

local timerCleansingPainCD						= mod:NewNextCountTimer(16.6, 326707, nil, nil, nil, 5, nil, DBM_COMMON_L.TANK_ICON, nil, 2, 3)
local timerBloodPriceCD							= mod:NewCDCountTimer(57.3, 326851, nil, nil, nil, 2, nil, DBM_COMMON_L.HEALER_ICON)
local timerFeedingTimeCD						= mod:NewCDCountTimer(44.3, 327039, nil, nil, nil, 3)--Normal/LFR
local timerNightHunterCD						= mod:NewNextCountTimer(44.3, 327796, nil, nil, nil, 3, nil, DBM_COMMON_L.HEROIC_ICON)--Heroic/mythic
local timerCommandRavageCD						= mod:NewCDCountTimer(57.2, 327227, 327122, nil, nil, 2, nil, DBM_COMMON_L.DEADLY_ICON, nil, 1, 4)--ShortName "Ravage" (the actual cast)

mod:AddSetIconOption("SetIconOnNightHunter", 327796, true, false, {1, 2, 3})
--Intermission: March of the Penitent
local specWarnMarchofthePenitent				= mod:NewSpecialWarningSpell(328117, nil, nil, nil, 2, 2)

local timerNextPhase							= mod:NewPhaseTimer(16.5, 328117, nil, nil, nil, 6, nil, nil, nil, 1, 4)
--Stage Two: The Crimson Chorus
mod:AddTimerLine(DBM:EJ_GetSectionInfo(22059))
----Crimson Cabalist
local warnCrimsonCabalists						= mod:NewSpellAnnounce("ej22131", 2, 329711)
local warnCrescendo								= mod:NewSpellAnnounce(336162, 3)

local specWarnCrescendo							= mod:NewSpecialWarningDodge(336162, false, nil, nil, 2, 2)

local timerCrimsonCabalistsCD					= mod:NewNextCountTimer(44.3, "ej22131", nil, nil, nil, 1, 329711)
----Horseman
local warnBalefulShadows						= mod:NewSpellAnnounce(344313, 3)

local specWarnVengefulWail						= mod:NewSpecialWarningInterruptCount(344776, "HasInterrupt", nil, nil, 1, 2, 4)

mod:AddSetIconOption("SetIconOnBalefulShadows", 344313, false, true, {7, 8})
----Remornia
local warnCarnage								= mod:NewStackAnnounce(329906, 2, nil, "Tank|Healer")
local warnImpale								= mod:NewTargetAnnounce(329951, 2)

local specWarnCarnage							= mod:NewSpecialWarningStack(329906, nil, 6, nil, nil, 1, 6)
local specWarnCarnageOther						= mod:NewSpecialWarningTaunt(329906, nil, nil, nil, 1, 6)
local specWarnImpale							= mod:NewSpecialWarningMoveAway(329951, nil, nil, nil, 1, 2)
local yellImpale								= mod:NewShortPosYell(329951)
local yellImpaleFades							= mod:NewIconFadesYell(329951)

local timerImpaleCD								= mod:NewNextCountTimer(44.3, 329951, nil, nil, nil, 3)

mod:AddSetIconOption("SetIconOnImpale", 329951, true, false, {1, 2, 3, 4})
----Sire Denathrius
local specWarnWrackingPain						= mod:NewSpecialWarningDefensive(329181, "Tank", nil, nil, 1, 2)--Change to defensive if it can't be dodged
local specWarnWrackingPainTaunt					= mod:NewSpecialWarningTaunt(329181, nil, nil, nil, 1, 2)
local specWarnHandofDestruction					= mod:NewSpecialWarningRun(333932, nil, nil, nil, 4, 2)
local specWarnCommandMassacre					= mod:NewSpecialWarningDodgeCount(330042, nil, 330137, nil, 2, 2)

local timerWrackingPainCD						= mod:NewCDCountTimer(16.6, 329181, nil, nil, nil, 5, nil, DBM_COMMON_L.TANK_ICON, true)
local timerHandofDestructionCD					= mod:NewCDCountTimer(44.3, 333932, nil, nil, nil, 2)
local timerCommandMassacreCD					= mod:NewCDCountTimer(49.8, 330042, 330137, nil, nil, 3, nil, DBM_COMMON_L.DEADLY_ICON)--Mythic 41-45, Heroic 47.4-51

--Stage Three: Indignation
mod:AddTimerLine(DBM:EJ_GetSectionInfo(22195))
local warnScorn									= mod:NewStackAnnounce(332585, 2, nil, "Tank|Healer")
local warnFatalFinesse							= mod:NewTargetNoFilterAnnounce(332794, 2)

local specWarnScorn								= mod:NewSpecialWarningStack(332585, nil, 6, nil, nil, 1, 6)
local specWarnScorneOther						= mod:NewSpecialWarningTaunt(332585, nil, nil, nil, 1, 6)
local specWarnShatteringPain					= mod:NewSpecialWarningCount(332619, nil, nil, nil, 2, 5)
local specWarnFatalfFinesse						= mod:NewSpecialWarningMoveAway(332794, nil, nil, nil, 1, 2)
local yellFatalfFinesse							= mod:NewShortPosYell(332794)
local yellFatalfFinesseFades					= mod:NewIconFadesYell(332794)
local specWarnSinisterReflection				= mod:NewSpecialWarningCount(333979, nil, nil, nil, 2, 2, 4)--Both Massacre and Ravage at same time

local timerShatteringPainCD						= mod:NewCDCountTimer(23, 332619, nil, nil, nil, 5, nil, DBM_COMMON_L.TANK_ICON)
local timerFatalFitnesseCD						= mod:NewCDCountTimer(22, 332794, nil, nil, nil, 3)
local timerSinisterReflectionCD					= mod:NewCDCountTimer(60, 333979, nil, nil, nil, 3, nil, DBM_COMMON_L.DEADLY_ICON)--Used on mythic, Massacre and Ravage combined
local timerSinisterReflection					= mod:NewCastTimer(3, 333979, nil, nil, nil, 5, nil, DBM_COMMON_L.IMPORTANT_ICON)

--local berserkTimer							= mod:NewBerserkTimer(600)

mod:AddSetIconOption("SetIconOnFatalFinesse", 332794, true, false, {1, 2, 3})

mod.vb.priceCount = 0
mod.vb.painCount = 0
mod.vb.RavageCount = 0
mod.vb.MassacreCount = 0
mod.vb.ImpaleCount = 0
mod.vb.HandCount = 0
mod.vb.addCount = 0
mod.vb.DebuffCount = 0
mod.vb.DebuffIcon = 1
--mod.vb.addIcon = 8
mod.vb.painCasting = false
local expectedStacks = 6
local P3Transition = false
local SinStacks, stage2Adds, deadAdds = {}, {}, {}
local castsPerGUID = {}
local difficultyName = "normal"
local playerGUID = UnitGUID("player")
local selfInMirror = false
local Timers = {
	["normal"] = {--Normal and LFR use same timers
		[1] = {
			--Feeding Time (Normal, LFR)
			[327039] = {15, 25, 35, 25, 35, 25},
			--Cleansing Pain (P1)
			[326707] = {5.8, 26.7, 32.8, 26.7, 32.7, 26.7},
		},
		[2] = {
			--Impale (Seems same as heroic)
			[329943] = {27.5, 25.9, 27, 23, 31.9, 18, 39, 35},
			--Hand of Destruction P2 (Seems same as heroic)
			[333932] = {47.6, 40.9, 40, 57, 19.7},
			--Adds P2 (Different from heroic)
			[181089] = {9.7, 84.5, 75},--75-79 for that last set?
		},
		[3] = {--Totally different from heroic
			--Hand of Destruction P3
			[333932] = {72.6, 76.4, 94.7},
			--Fatal Finesse P3
			[332794] = {17.4, 24, 24.9, 29, 22, 34, 22, 26, 32},
			--Adds P2 (There are none in phase 3 but sometimes message can trigger after p2 trigger, this stops nil error)
			[181089] = {},
		}
	},
	["heroic"] = {
		[1] = {
			--Night Hunter (Heroic)
			[327796] = {12.3, 24.9, 30, 28, 30, 28},--Heroic
			--Cleansing Pain (Heroic) (P1)
			[326707] = {5.8, 24.4, 32.8, 24.5, 32.7, 24.3},
		},
		[2] = {
			--Impale
			[329943] = {27.5, 25.9, 27, 23, 31.9, 18, 39, 35},
			--Hand of Destruction P2
			[333932] = {47.6, 40.9, 40, 57, 19.7},
			--Adds P2
			[181089] = {9.7, 85, 55},
		},
		[3] = {
			--Hand of Destruction P3
			[333932] = {27.6, 88, 31.7, 47.5},
			--Fatal Finesse P3
			[332794] = {17.4, 48, 6, 21, 27, 19, 26, 21, 40},
			--Adds P2 (There are none in phase 3 but sometimes message can trigger after p2 trigger, this stops nil error)
			[181089] = {},
		}
	},
	["mythic"] = {
		[1] = {
			--Night Hunter
			[327796] = {14, 24.9, 32.9, 24.8, 32.9, 24.9},
			--Cleansing Pain (P1)
			[326707] = {5.8, 24.4, 32.8, 24.5, 32.7, 24.3},
		},
		[2] = {
			--Impale
			[329943] = {49.5, 39.0, 36.0, 45},
			--Hand of Destruction P2
			[333932] = {44.2, 32.3, 39.7, 44.7, 44.8},
			--Adds P2
			[181089] = {9.6, 75, 54.9},
		},
		[3] = {
			--Fatal Finesse P3
			[332794] = {27, 21.9, 25, 25, 38.9, 33, 12, 12},
			--Shattering Pain Pain
			[332619] = {12.8, 25.4, 21.7, 24.2, 24.2, 25.4, 21.8, 23, 25.5},
			--Adds P2 (There are none in phase 3 but sometimes message can trigger after p2 trigger, this stops nil error)
			[181089] = {},
		}
	},
}

local updateInfoFrame
do
	local DBM = DBM
	local addName = DBM:EJ_GetSectionInfo(22131)
	local pairs, twipe, tsort, mfloor = pairs, table.wipe, table.sort, math.floor
	local UnitGUID, UnitName = UnitGUID, UnitName
	local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax
	local lines = {}
	local sortedLines = {}
	local horsemanAdded = {}
	local function addLine(key, value)
		-- sort by insertion order
		lines[key] = value
		sortedLines[#sortedLines + 1] = key
	end
	updateInfoFrame = function()
		twipe(lines)
		twipe(sortedLines)
		twipe(horsemanAdded)
		for uId in DBM:GetGroupMembers() do
			if uId then
				local targetuId = uId.."target"
				local guid = UnitGUID(targetuId)
				if guid then
					local cid = mod:GetCIDFromGUID(guid)
					if (cid == 173163 or cid == 173162 or cid == 173164 or cid == 173161) and not deadAdds[guid] then--Horseman
						stage2Adds[guid] = mfloor(UnitHealth(targetuId) / UnitHealthMax(targetuId) * 100)
						local name = UnitName(targetuId)
						if not horsemanAdded[name] then
							addLine(name, stage2Adds[guid] .. '%')
							horsemanAdded[name] = true
						end
					end
					if cid == 169196 and not deadAdds[guid] then--Crimson Cabalis
						stage2Adds[guid] = mfloor(UnitHealth(targetuId) / UnitHealthMax(targetuId) * 100)
					end
				end
			end
		end
		local CableGuys = 0
		for _, health in pairs(stage2Adds) do
			CableGuys = CableGuys + 1
			addLine(addName .. " " .. CableGuys, health .. '%')
		end
		return lines, sortedLines
	end
end

function mod:OnCombatStart(delay)
	table.wipe(SinStacks)
	table.wipe(stage2Adds)
	table.wipe(deadAdds)
	table.wipe(castsPerGUID)
	self:SetStage(1)
	self.vb.priceCount = 0
	self.vb.painCount = 0
	self.vb.RavageCount = 0
	self.vb.MassacreCount = 0
	self.vb.ImpaleCount = 0
	self.vb.HandCount = 0
	self.vb.addCount = 0
	self.vb.DebuffCount = 0
	self.vb.DebuffIcon = 1
	self.vb.painCasting = false
	P3Transition = false
	selfInMirror = false
	--Same on all difficulties
	timerCleansingPainCD:Start(5.8-delay, 1)--5.8-6.3
	timerBloodPriceCD:Start(22.3-delay, 1)--22-24
	timerCommandRavageCD:Start(self:IsEasy() and 52.2 or 50.2-delay, 1)--50-51
	--Where timers diverge
	if self:IsMythic() then
		difficultyName = "mythic"
		expectedStacks = 6
		timerNightHunterCD:Start(14-delay, 1)--14+
	else
		if self:IsHeroic() then
			difficultyName = "heroic"
			expectedStacks = 5
			timerNightHunterCD:Start(12.1-delay, 1)--12+
		else
			difficultyName = "normal"
			expectedStacks = 4
			timerFeedingTimeCD:Start(15-delay, 1)
		end
	end
--	berserkTimer:Start(-delay)--Confirmed normal and heroic
	if self.Options.InfoFrame then
		DBM.InfoFrame:SetHeader(DBM:GetSpellInfo(326699))
		DBM.InfoFrame:Show(self:IsHard() and 30 or 10, "table", SinStacks, 1)--Show everyone on heroic+, filter down to 10 on normal/lfr
	end
end

function mod:OnCombatEnd()
	if self.Options.InfoFrame then
		DBM.InfoFrame:Hide()
	end
end

function mod:OnTimerRecovery()
	if self:IsMythic() then
		difficultyName = "mythic"
	elseif self:IsHeroic() then
		difficultyName = "heroic"
	else
		difficultyName = "normal"
	end
	if not DBM:UnitDebuff("player", 338738) and not UnitIsDeadOrGhost("player") then
		selfInMirror = true
	end
end

function mod:SPELL_CAST_START(args)
	local spellId = args.spellId
	if spellId == 326707 then--Sire Cleansing Pain
		self.vb.painCount = self.vb.painCount + 1
		specWarnCleansingPain:Show(self.vb.painCount)
		specWarnCleansingPain:Play("shockwave")
		local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.painCount+1]
		--Use scripted timer but if running out of script fall back to the 32/24 alternation
		timerCleansingPainCD:Start(timer or self.vb.painCount % 2 == 0 and 32.5 or 24.4, self.vb.painCount+1)
	elseif spellId == 326851 then
		self.vb.priceCount = self.vb.priceCount + 1
		warnBloodPrice:Show(self.vb.priceCount)
		timerBloodPriceCD:Start(self.vb.phase == 3 and 71.6 or self:IsEasy() and 59.5 or 57.3, self.vb.priceCount+1)
	elseif spellId == 327227 then
		self.vb.RavageCount = self.vb.RavageCount + 1
		specWarnCommandRavage:Show(self.vb.RavageCount)
		specWarnCommandRavage:Play("specialsoon")
		timerCommandRavageCD:Start(self:IsEasy() and 59.5 or 57.3, self.vb.RavageCount+1)
	elseif spellId == 328117 then--March of the Penitent (first intermission)
		self:SetStage(1.5)
		specWarnMarchofthePenitent:Show()
		timerCleansingPainCD:Stop()
		timerBloodPriceCD:Stop()
		timerCommandRavageCD:Stop()
		timerNightHunterCD:Stop()
		timerFeedingTimeCD:Stop()
		timerNextPhase:Start(16.5)
	elseif spellId == 329181 then
		specWarnWrackingPain:Show()
		specWarnWrackingPain:Play("shockwave")
		--"Wracking Pain-329181-npc:167406 = pull:197.3, 19.5, 20.6, 19.5, 20.8, 19.5, 20.6, 19.4, 20.6", -- [10]
		--"Wracking Pain-329181-npc:167406 = pull:210.1, 18.3, 17.1, 18.3, 18.3, 21.4"
		if not self.vb.painCasting then
			self.vb.painCount = self.vb.painCount + 1
			timerWrackingPainCD:Start(self:IsMythic() and 17 or 19.4, self.vb.painCount+1)
			self.vb.painCasting = true--Work around a bug where boss stutter casts, but incurrs cd from begin of first cast
		end
	elseif spellId == 333932 and self:AntiSpam(10, 10) then
		self.vb.HandCount = self.vb.HandCount + 1
		specWarnHandofDestruction:Show()
		specWarnHandofDestruction:Play("justrun")
		local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.HandCount+1] or 41.2--Or part may not be accurate
		if timer then
			timerHandofDestructionCD:Start(timer, self.vb.HandCount+1)
		end
	elseif spellId == 344776 then
		if not castsPerGUID[args.sourceGUID] then
			castsPerGUID[args.sourceGUID] = 0
--			if self.Options.SetIconOnBalefulShadows and self.vb.addIcon > 3 then--Only use up to 5 icons
--				self:ScanForMobs(args.sourceGUID, 2, self.vb.addIcon, 1, nil, 12, "SetIconOnBalefulShadows")
--			end
--			self.vb.addIcon = self.vb.addIcon - 1
		end
		castsPerGUID[args.sourceGUID] = castsPerGUID[args.sourceGUID] + 1
		local count = castsPerGUID[args.sourceGUID]
		if self:CheckInterruptFilter(args.sourceGUID, false, false) then
			specWarnVengefulWail:Show(args.sourceName, count)
			if count == 1 then
				specWarnVengefulWail:Play("kick1r")
			elseif count == 2 then
				specWarnVengefulWail:Play("kick2r")
			elseif count == 3 then
				specWarnVengefulWail:Play("kick3r")
			elseif count == 4 then
				specWarnVengefulWail:Play("kick4r")
			elseif count == 5 then
				specWarnVengefulWail:Play("kick5r")
			else
				specWarnVengefulWail:Play("kickcast")
			end
		end
	end
end

function mod:SPELL_CAST_SUCCESS(args)
	local spellId = args.spellId
	if spellId == 327796 and self:AntiSpam(5, 1) then
		self.vb.DebuffIcon = 1
		self.vb.DebuffCount = self.vb.DebuffCount + 1
		local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.DebuffCount+1]
		if timer then
			timerNightHunterCD:Start(timer, self.vb.DebuffCount+1)
		end
	elseif spellId == 329943 then
		self.vb.DebuffIcon = 1
		self.vb.ImpaleCount = self.vb.ImpaleCount + 1
		local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.ImpaleCount+1]
		if timer then
			timerImpaleCD:Start(timer, self.vb.ImpaleCount+1)
		end
	elseif spellId == 339196 and self.vb.phase == 3 then
		self.vb.priceCount = self.vb.priceCount + 1
		warnBloodPrice:Show(self.vb.priceCount)
		timerBloodPriceCD:Start(nil, self.vb.priceCount+1)
	elseif spellId == 330042 then
		self.vb.MassacreCount = self.vb.MassacreCount + 1
		specWarnCommandMassacre:Show(self.vb.MassacreCount)
		specWarnCommandMassacre:Play("watchstep")--Perhaps farfromline?
		timerCommandMassacreCD:Start(self:IsMythic() and 41.4 or 47.4, self.vb.MassacreCount+1)--Mythic 41-45
	elseif spellId == 326005 then
		self:SetStage(3)
		self.vb.priceCount = 0
		self.vb.painCount = 0--reused for shattering pain
		self.vb.RavageCount = 0
		self.vb.MassacreCount = 0
		self.vb.DebuffCount = 0
		self.vb.HandCount = 0
		warnPhase:Show(DBM_CORE_L.AUTO_ANNOUNCE_TEXTS.stage:format(3))
		warnPhase:Play("pthree")
		--Remornia
		timerImpaleCD:Stop()
		--Denathrius
		timerWrackingPainCD:Stop()
		timerHandofDestructionCD:Stop()
		timerCommandMassacreCD:Stop()
		timerCrimsonCabalistsCD:Stop()
		timerNextPhase:Stop()
		if self:IsMythic() then
			timerShatteringPainCD:Start(12.8, 1)--SUCCESS
			timerBloodPriceCD:Start(21.7, 1)
			timerFatalFitnesseCD:Start(27, 1)--SUCCESS/APPLIED
			timerSinisterReflectionCD:Start(70.5, 1)--Both ravage and masacre at same time
			if self.Options.InfoFrame then
				DBM.InfoFrame:SetHeader(DBM:GetSpellInfo(326699))
				DBM.InfoFrame:Show(20, "table", SinStacks, 1)
			end
		else
			--All the same
			timerShatteringPainCD:Start(13.3, 1)--SUCCESS
			timerFatalFitnesseCD:Start(17.4, 1)--SUCCESS/APPLIED
			if self:IsEasy() then
				timerCommandMassacreCD:Start(49.7, 1)--Seems massacre always first Reflection
				timerHandofDestructionCD:Start(71.6, 1)
			else
				timerHandofDestructionCD:Start(27.6, 1)--27-29
				timerCommandRavageCD:Start(50, 1)--Seems ravage always first Reflection
			end
			if self.Options.InfoFrame then
				DBM.InfoFrame:Hide()--Nothing to show it for on non mythic
			end
		end
	elseif spellId == 332849 then--Reflection: Ravage
		self.vb.RavageCount = self.vb.RavageCount + 1
		specWarnCommandRavage:Show(self.vb.RavageCount)
		specWarnCommandRavage:Play("specialsoon")
		timerCommandMassacreCD:Start(40, self.vb.MassacreCount+1)
	elseif spellId == 333980 then
		self.vb.MassacreCount = self.vb.MassacreCount + 1
		specWarnCommandMassacre:Show(self.vb.MassacreCount)
		specWarnCommandMassacre:Play("watchstep")--Perhaps farfromline?
		timerCommandRavageCD:Start(40, self.vb.RavageCount+1)
	elseif spellId == 332619 then
		self.vb.painCount = self.vb.painCount + 1
		specWarnShatteringPain:Show(self.vb.painCount)
		if self:IsMythic() then
			local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.painCount+1] or 21.9--TODO< hardcore more timer data
			if timer then
				timerShatteringPainCD:Start(timer, self.vb.painCount+1)
			end
			if selfInMirror then
				specWarnShatteringPain:Play("teleyou")
			else
				specWarnShatteringPain:Play("carefly")
			end
		else
			timerShatteringPainCD:Start(23, self.vb.painCount+1)
			specWarnShatteringPain:Play("carefly")
		end
	elseif spellId == 329181 then
		self.vb.painCasting = false
	elseif spellId == 333979 and self:IsMythic() then--Mythic filter just in case
		self.vb.RavageCount = self.vb.RavageCount + 1
		specWarnSinisterReflection:Show(self.vb.RavageCount)
		specWarnSinisterReflection:Play("specialsoon")
		timerSinisterReflection:Start()
		timerSinisterReflectionCD:Start(60, self.vb.RavageCount+1)
	end
end

function mod:SPELL_AURA_APPLIED(args)
	local spellId = args.spellId
	if spellId == 326699 then
		local amount = args.amount or expectedStacks
		SinStacks[args.destName] = amount
		if self.Options.InfoFrame then
			DBM.InfoFrame:UpdateTable(SinStacks, 0.2)
		end
	elseif spellId == 338510 then
		if self.Options.NPAuraOnShield then
			DBM.Nameplate:Show(true, args.destGUID, spellId, nil, 14)
		end
	elseif spellId == 327039 then
		if args:IsPlayer() then
			specWarnFeedingTime:Show()
			specWarnFeedingTime:Play("runout")
			yellFeedingTime:Yell()
			yellFeedingTimeFades:Countdown(spellId)
		else
			warnFeedingTime:CombinedShow(0.3, args.destName)
		end
		if self:AntiSpam(5, 1) then--Cast event isn't in combat log, hava to use debuffs
			self.vb.DebuffCount = self.vb.DebuffCount + 1
			local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.DebuffCount+1]
			if timer then
				timerFeedingTimeCD:Start(timer, self.vb.DebuffCount+1)
			end
		end
	elseif spellId == 327796 then
		local icon = self.vb.DebuffIcon
		if self.Options.SetIconOnNightHunter then
			self:SetIcon(args.destName, icon)
		end
		if args:IsPlayer() then
			--Unschedule target warning if you've become one of victims
			specWarnNightHunterTarget:Cancel()
			specWarnNightHunterTarget:CancelVoice()
			--Now show your warnings
			specWarnNightHunter:Show(self:IconNumToTexture(icon))
			specWarnNightHunter:Play("mm"..icon)
			yellNightHunter:Yell(icon, icon)
			yellNightHunterFades:Countdown(spellId, nil, icon)
		elseif self.Options.SpecWarn327796target and not DBM:UnitDebuff("player", spellId) then
			--Don't show special warning if you're one of victims
			specWarnNightHunterTarget:CombinedShow(0.5, args.destName)
			specWarnNightHunterTarget:ScheduleVoice(0.5, "helpsoak")
		else
			warnNightHunter:CombinedShow(0.5, args.destName)
		end
		self.vb.DebuffIcon = self.vb.DebuffIcon + 1
	elseif spellId == 327992 and args:IsPlayer() and self:AntiSpam(2, 2) then
		specWarnGTFO:Show(args.spellName)
		specWarnGTFO:Play("watchfeet")
	elseif spellId == 329906 then
		local amount = args.amount or 1
		if (amount % 3 == 0) then
			if amount >= 6 then
				if args:IsPlayer() then
					specWarnCarnage:Show(amount)
					specWarnCarnage:Play("stackhigh")
				else
					--Don't show taunt warning if you're 3 tanking and aren't near the boss (this means you are the add tank)
					--Show taunt warning if you ARE near boss, or if number of alive tanks is less than 3
					if (self:CheckNearby(8, args.destName) or self:GetNumAliveTanks() < 3) and not DBM:UnitDebuff("player", spellId) and not UnitIsDeadOrGhost("player") then--Can't taunt less you've dropped yours off, period.
						specWarnCarnageOther:Show(args.destName)
						specWarnCarnageOther:Play("tauntboss")
					else
						warnCarnage:Show(args.destName, amount)
					end
				end
			else
				warnCarnage:Show(args.destName, amount)
			end
		end
	elseif spellId == 332585 then
		local amount = args.amount or 1
		if (amount % 3 == 0) then
			if amount >= 6 then
				if args:IsPlayer() then
					specWarnScorn:Show(amount)
					specWarnScorn:Play("stackhigh")
				else
					--Don't show taunt warning if you're 3 tanking and aren't near the boss (this means you are the add tank)
					--Show taunt warning if you ARE near boss, or if number of alive tanks is less than 3
					if (self:CheckNearby(8, args.destName) or self:GetNumAliveTanks() < 3) and not DBM:UnitDebuff("player", spellId) and not UnitIsDeadOrGhost("player") then--Can't taunt less you've dropped yours off, period.
						specWarnScorneOther:Show(args.destName)
						specWarnScorneOther:Play("tauntboss")
					else
						warnScorn:Show(args.destName, amount)
					end
				end
			else
				warnScorn:Show(args.destName, amount)
			end
		end
	elseif spellId == 329951 then
		local icon = self.vb.DebuffIcon
		if self.Options.SetIconOnImpale then
			self:SetIcon(args.destName, icon)
		end
		if args:IsPlayer() then
			specWarnImpale:Show()
			specWarnImpale:Play("runout")
			yellImpale:Yell(icon, icon)
			yellImpaleFades:Countdown(spellId, nil, icon)
		end
		warnImpale:CombinedShow(0.3, args.destName)
		self.vb.DebuffIcon = self.vb.DebuffIcon + 1
	elseif spellId == 332794 then
		if self:AntiSpam(4, 4) then
			self.vb.DebuffIcon = 1
			self.vb.DebuffCount = self.vb.DebuffCount + 1
			local timer = Timers[difficultyName][self.vb.phase][spellId][self.vb.DebuffCount+1]
			if timer then
				timerFatalFitnesseCD:Start(timer, self.vb.DebuffCount+1)
			end
		end
		local icon = self.vb.DebuffIcon
		if self.Options.SetIconOnFatalFinesse then
			self:SetIcon(args.destName, icon)
		end
		if args:IsPlayer() then
			specWarnFatalfFinesse:Show()
			specWarnFatalfFinesse:Play("runout")
			yellFatalfFinesse:Yell(icon, icon)
			yellFatalfFinesseFades:Countdown(spellId, nil, icon)
		end
		warnFatalFinesse:CombinedShow(0.3, args.destName)
		self.vb.DebuffIcon = self.vb.DebuffIcon + 1
	elseif spellId == 329181 then
		if not args:IsPlayer() then
			specWarnWrackingPainTaunt:Show(args.destName)
			specWarnWrackingPainTaunt:Play("tauntboss")
		end
	elseif spellId == 344313 then
--		self.vb.addIcon = 8
		warnBalefulShadows:Show()
	elseif spellId == 338738 then--Infinity's Toll being applied (Players leaving mind)
		if args.sourceGUID == playerGUID then
			selfInMirror = false
		end
	elseif spellId == 181089 then--Encounter Event
		self.vb.addCount = self.vb.addCount + 1
		warnCrimsonCabalists:Show(self.vb.addCount)
		local timer = Timers[difficultyName][self.vb.phase][181089][self.vb.addCount+1]
		if timer then
			timerCrimsonCabalistsCD:Start(timer, self.vb.addCount+1)
		end
		if self.Options.SetIconOnBalefulShadows then--Only use up to 5 icons
			self:ScanForMobs(175205, 0, 8, 2, nil, 25, "SetIconOnBalefulShadows")
		end
	end
end
mod.SPELL_AURA_APPLIED_DOSE = mod.SPELL_AURA_APPLIED

function mod:SPELL_AURA_REMOVED(args)
	local spellId = args.spellId
	if spellId == 326699 then
		SinStacks[args.destName] = nil
		if self.Options.InfoFrame then
			DBM.InfoFrame:UpdateTable(SinStacks, 0.2)
		end
	elseif spellId == 338510 then
		if self.Options.NPAuraOnShield then
			DBM.Nameplate:Hide(true, args.destGUID, spellId)
		end
	elseif spellId == 327039 then
		if args:IsPlayer() then
			yellFeedingTimeFades:Cancel()
		end
	elseif spellId == 327796 then
		if args:IsPlayer() then
			yellNightHunterFades:Cancel()
		end
		if self.Options.SetIconOnNightHunter then
			self:SetIcon(args.destName, 0)
		end
	elseif spellId == 328117 and self:IsInCombat() then--March of the Penitent
		self:SetStage(2)
		self.vb.painCount = 0
		self.vb.DebuffCount = 0
		warnPhase:Show(DBM_CORE_L.AUTO_ANNOUNCE_TEXTS.stage:format(2))
		warnPhase:Play("ptwo")
		if self:IsMythic() then
			--Remornia
			timerImpaleCD:Start(49.5, 1)
			--Denathrius
			timerCrimsonCabalistsCD:Start(9.6, 1)--Actually the horseman, but same emote
			timerWrackingPainCD:Start(21.1, 1)
			timerHandofDestructionCD:Start(44.2, 1)
			timerCommandMassacreCD:Start(63.7, 1)
			timerNextPhase:Start(234.4)
		else
			--Remornia
			timerImpaleCD:Start(27.5, 1)
			--Denathrius
			timerCrimsonCabalistsCD:Start(9.7, 1)
			timerWrackingPainCD:Start(21.1, 1)
			timerHandofDestructionCD:Start(46.6, 1)
			timerCommandMassacreCD:Start(64.9, 1)
			timerNextPhase:Start(219.4)
		end
		if self.Options.InfoFrame then
			DBM.InfoFrame:SetHeader(DBM_COMMON_L.ADDS)
			DBM.InfoFrame:Show(10, "function", updateInfoFrame, false, false)
			DBM.InfoFrame:SetColumns(1)
		end
	elseif spellId == 329951 then
		if args:IsPlayer() then
			yellImpaleFades:Cancel()
		end
		if self.Options.SetIconOnImpale then
			self:SetIcon(args.destName, 0)
		end
	elseif spellId == 332794 then
		if args:IsPlayer() then
			yellFatalfFinesseFades:Cancel()
		end
		if self.Options.SetIconOnFatalFinesse then
			self:SetIcon(args.destName, 0)
		end
	elseif spellId == 338738 then
		if args.destGUID == playerGUID and not UnitIsDeadOrGhost("player") then
			selfInMirror = true
		end
	end
end

function mod:SPELL_AURA_REMOVED_DOSE(args)
	local spellId = args.spellId
	if spellId == 326699 then
		SinStacks[args.destName] = args.amount or 1
		if self.Options.InfoFrame then
			DBM.InfoFrame:UpdateTable(SinStacks, 0.2)
		end
	end
end

function mod:UNIT_DIED(args)
	local cid = self:GetCIDFromGUID(args.destGUID)
	if cid == 169196 or cid == 173163 or cid == 173162 or cid == 173164 or cid == 173161 then--crimson-cabalist and all 4 horseman
		stage2Adds[args.destGUID] = nil
		deadAdds[args.destGUID] = true
		if self:IsHard() and self:AntiSpam(3, 3) then
			if self.Options.SpecWarn336162dodge then
				specWarnCrescendo:Show()
				specWarnCrescendo:Play("watchstep")
			else
				warnCrescendo:Show()
			end
		end
	elseif cid == 169855 then--Remornia
		timerImpaleCD:Stop()
	elseif cid == 175205 or cid == 175528 then--Baleful Shadow
		castsPerGUID[args.destGUID] = nil
	end
end

function mod:SPELL_PERIODIC_DAMAGE(_, _, _, _, destGUID, _, _, _, spellId, spellName)
	if spellId == 327992 and destGUID == UnitGUID("player") and self:AntiSpam(2, 2) then
		specWarnGTFO:Show(spellName)
		specWarnGTFO:Play("watchfeet")
	end
end
mod.SPELL_PERIODIC_MISSED = mod.SPELL_PERIODIC_DAMAGE

function mod:UNIT_SPELLCAST_SUCCEEDED(uId, _, spellId)
	--1 second faster than SPELL_CAST_START
	if spellId == 330613 and self:AntiSpam(10, 10) then--Script Activating to cast Hand of Destruction
		if not P3Transition then--We can't let a cast that slips through during Indignation screw up counts/timers
			self.vb.HandCount = self.vb.HandCount + 1
			local timer = Timers[difficultyName][self.vb.phase][333932][self.vb.HandCount+1]
			if timer then
				timerHandofDestructionCD:Start(timer, self.vb.HandCount+1)
			end
		end
		specWarnHandofDestruction:Show()
		specWarnHandofDestruction:Play("justrun")
	elseif spellId == 332749 and P3Transition then
		P3Transition = false
	end
end
