-- Natur EnemyCastBar Debuffs LUA


-- initialize renew Buff/Debuff system; prepare patterns:
local patterns = {SPELLIMMUNESELFOTHER, SPELLRESISTSELFOTHER, SPELLPARRIEDSELFOTHER, SPELLREFLECTSELFOTHER,
			SPELLBLOCKEDSELFOTHER, SPELLDEFLECTEDSELFOTHER, SPELLDODGEDSELFOTHER, SPELLEVADEDSELFOTHER,
			SPELLMISSSELFOTHER, IMMUNESPELLSELFOTHER, SPELLLOGABSORBSELFOTHER };

-- generate miss table out of localized global WoW strings
necb_spellmisses = { };
for k,v in pairs (patterns) do
	necb_spellmisses[k] = NECB_ConvertPattern(v);
end

function NECB_Debuffs_Control(mob, spell, special, bcasted, event)

	if (NECB_Debuffs_Module_loaded and CEnemyCastBar.bShowafflict) then

 		-- only 'afflicted', DoTs allowed!
		if (special == "afflicted" or (CEnemyCastBar.bSDoTs and special == "periodicdmg") ) then

			-- initialize locals, since this a separated mod now
			local spelllength = string.len (spell);
			-- Network BC TempBCaster
			local clientlang = GetLocale();	
			-- initialize vars
			local ctype, castime;


 			-- check if spell stacks
			-- now uses strings, too, but won't be cleared on fades!
			local fbracket,_,spellstacks = string.find(spell, "(%(.+%))" );
			if (fbracket) then
				spell = string.sub(spell, 1, fbracket - 2);
				spelllength = string.len (spell);
			end

			-- crop the german aposthrophes from some spells (')
			local spell_de = string.sub(spell, 2, spelllength - 1);
			if (CEnemyCastBar_Afflictions[spell_de]) then spell = spell_de;
			end

			-- database check
			if (CEnemyCastBar_Afflictions[spell] ) then

				-- change name if callspell flag
				if (CEnemyCastBar_Afflictions[spell].callspell) then
					spell = CEnemyCastBar_Afflictions[spell].callspell;
					-- currently only used here for Mage Pet's "Freeze". "Sunder" is changed out of this function!
				end

				if (
							-- raid debuffs disabled?
						(CEnemyCastBar_Afflictions[spell].global and not CEnemyCastBar.bBossDebuff)
							-- check if previously disabled with shift + leftclick
					or	(CEnemyCastBar_Afflictions[spell].disabled)
							-- break if 'mage cold debuff' but disabled
					or	(CEnemyCastBar_Afflictions[spell].magecold and not CEnemyCastBar.bMageC)
							-- periodic dmg spells shall only be triggered if they do damage, otherwise the affliction might be from another player!
					or	(special == "afflicted" and CEnemyCastBar_Afflictions[spell].periodicdmg)
					or 	(CEnemyCastBar_Afflictions[spell].aZone and GetRealZoneText() ~= CEnemyCastBar_Afflictions[spell].aZone)
					or	(CEnemyCastBar_Afflictions[spell].blockZone and GetRealZoneText() == CEnemyCastBar_Afflictions[spell].blockZone)
							-- don't trigger castbars for your own debuffs if other than boss debuffs
					or	(mob == UnitName("player") and not CEnemyCastBar_Afflictions[spell].global)

					) then
					return;
				end

				alreadyshowing = 0;
				local icontex = CEnemyCastBar_Afflictions[spell].icontex; -- > get icon texture
				local globalspell = CEnemyCastBar_Afflictions[spell].global; -- > castbars without a target check (Raidencounter)!
				local fragile = CEnemyCastBar_Afflictions[spell].fragile; -- > for option to show "fragiles" without a target!

				if (UnitName("target") == mob or (UnitName("focus") == mob and CEnemyCastBar.bFocusDebuffs) or globalspell or (fragile and CEnemyCastBar.bGlobalFrag) or special == "periodicdmg") then

					-- new with NECB 6.9.x, to update focus bars
					local necb_unit = "target";
					if (UnitName("focus") == mob) then
						necb_unit = "focus";
					end

					-- prevent an update by update feature if this is called earlier anyway
					if (special == "afflicted" and CECBFauxFrameButton:IsShown() and necb_fauxtimer[2] == spell) then --uhm no mob check, crazy me^^ (should work without it)
						CEnemyCastBar_FauxUpdater("clear");
					end

					castime = CEnemyCastBar_Afflictions[spell].t;

					local _, playersclass = UnitClass("player");

					-- Consider player level to modify duration
					if (CEnemyCastBar_Afflictions[spell].plevel) then
						local lcounter = 2;
						while (CEnemyCastBar_Afflictions[spell].plevel[lcounter] > UnitLevel("player") ) do
							lcounter = lcounter + 1;
						end
						castime = castime - (lcounter - 2)*CEnemyCastBar_Afflictions[spell].plevel[1];
					end

					-- Consider talent points to modify duration
					if (CEnemyCastBar_Afflictions[spell].tskill and not CEnemyCastBar_Afflictions[spell].callspell) then -- .tskll + .callspell only used by 'scorch' and must not be processed here
						local _, _, _, _, currRank = GetTalentInfo(CEnemyCastBar_Afflictions[spell].tskill[1], CEnemyCastBar_Afflictions[spell].tskill[2]);
						if (currRank and currRank > 0 and playersclass == CEnemyCastBar_Afflictions[spell].tskill[4]) then
							if (CEnemyCastBar_Afflictions[spell].tskill[3] ~= 0) then
								castime = castime + currRank*CEnemyCastBar_Afflictions[spell].tskill[3];
							else
								castime = castime * (1 + currRank*CEnemyCastBar_Afflictions[spell].tskill[6] );
							end

							castime = castime + CEnemyCastBar_Afflictions[spell].tskill[5];
						end
					end

					-- Consider Combo points for duration; wait 1 sec for 'Rupture's first DoT damage! (old system was 3 secs)
					if (CEnemyCastBar_Afflictions[spell].cpinterval and playersclass == CEnemyCastBar_Afflictions[spell].cpclass and CECBownCPsHitTime and (GetTime() - CECBownCPsHitTime) < 1) then
						castime = castime - (CEnemyCastBar_Afflictions[spell].cpinterval * (5 - CECBownCPsHit));
						--DEFAULT_CHAT_FRAME:AddMessage("|cffaaaaaaNECB:|r Debug, castime="..castime.." -CECBownCPsHit="..CECBownCPsHit.." -cpinterval="..CEnemyCastBar_Afflictions[spell].cpinterval.." -timediff="..GetTime() - CECBownCPsHitTime) 

					end

					if (special == "periodicdmg") then
						ctype = "dots";
					elseif (CEnemyCastBar_Afflictions[spell].stun or CEnemyCastBar_Afflictions[spell].stuntype) then
						ctype = "stuns";
					else
						ctype = "afflict";
					end

					-- DR START
					local DRTimer = 0;

					-- PvP event check
					local function CEnemyCastBar_PvPCheck()
						if (	event
							and string.match("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE", event)
							and not (UnitName(necb_unit) == mob and not UnitIsPlayer(necb_unit)) -- done for mindcontrol always beeing a player event :/
							and not (CEnemyCastBar_Afflictions[spell].sclass == "PRIEST" and IsInInstance() and not (GetNumBattlefieldStats() > 1 or IsActiveBattlefieldArena() ) ) -- done for mindcontrol always beeing a player event :/
						) then
							return true;
						else
							return false;
						end
					end

					-- crowd controlling spells are limited to a 12 sec duration with WoW 2.0
					if (CEnemyCastBar_Afflictions[spell].spellDR
						and CEnemyCastBar_PvPCheck()
						and castime > 12
						) then
						castime = 12;
					end

					--DR subfunction for DR Timer; CASTIME will be modified in Uni function (if DRText transmitted to function = last flag and label found -> after ELSE)
					local function CEnemyCastBar_DRBar(drspell)

						if (string.match(drspell, "DR: ") ) then -- update DR DB
							_, DRTimer = CEnemyCastBar_DR_DBCheck(mob, drspell, castime, nil, spell);
						end
						if (CEnemyCastBar_UniqueCheck(drspell, castime, mob, "true",nil,nil,"cooldown") == 0) then
							if (drspell == CECB_SPELL_STUN_DR) then
								CEnemyCastBar_Show(mob, drspell, 15 + castime, "cooldown", nil, "Spell_Frost_Stun", nil, "(|cffff00001/2|r)");
							elseif (UnitName(necb_unit) == mob and playersclass == CEnemyCastBar_Afflictions[spell].sclass and CEnemyCastBar_UniqueCheck(drspell, castime, mob,nil,nil,nil,"cooldown") == 0) then
								CEnemyCastBar_Show(mob, drspell, 15 + castime, "cooldown", nil, icontex, nil, "(|cffff00001/2|r)");
							end
						elseif (drspell == CECB_SPELL_STUN_DR or (UnitName(necb_unit) == mob and playersclass == CEnemyCastBar_Afflictions[spell].sclass) ) then
							_, DRTimer = CEnemyCastBar_UniqueCheck(drspell, castime, mob, nil, "trigger label check in uni function",nil,"cooldown");
						end
					end

					-- stun diminishing returns bar
					if (CEnemyCastBar.bDRTimer and mob ~= UnitName("player") and CEnemyCastBar_Afflictions[spell].stun) then

						CEnemyCastBar_DRBar(CECB_SPELL_STUN_DR);
					end

					-- pvp diminishing returns bar
					-- playersclass already defined above
					if (CEnemyCastBar.bClassDR and CEnemyCastBar_Afflictions[spell].spellDR and (UnitIsPlayer(necb_unit) or CEnemyCastBar_PvPCheck() or CEnemyCastBar_Afflictions[spell].affmob) and mob ~= UnitName("player")) then
						local drshare = CEnemyCastBar_Afflictions[spell].drshare;
						if (drshare) then
							CEnemyCastBar_DRBar("DR: "..drshare);
						else
							CEnemyCastBar_DRBar("DR: "..spell);
						end
					end

					if (DRTimer == 4 or DRTimer == 6) then
						castime = castime / (DRTimer - 2);
					end
					-- DR END

					if (
							-- only show this spell for specified class
							(CEnemyCastBar_Afflictions[spell].checkclass and playersclass ~= CEnemyCastBar_Afflictions[spell].checkclass)
							-- break if 'solo spell' but disabled
						or	(CEnemyCastBar_Afflictions[spell].solo and not CEnemyCastBar.bSoloD)
						) then
						return;
					end

					if (CEnemyCastBar_Afflictions[spell].m) then
					
						mob = CEnemyCastBar_Afflictions[spell].m
					
					end

					-- unique check; Raidspells (globalspell) won't be updated; Fragiles will be updated and multiple bars allowed
					if (fragile) then
						alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,"trueupdate",nil,nil,"afflictions");
					elseif (spellstacks) then
						if (globalspell) then
							alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,"trueupdate",spellstacks,"turnit","afflictions");
						else
							alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,nil,spellstacks,nil,"afflictions");
						end
					elseif (special == "periodicdmg") then
						alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,"trueupdate",nil,nil,"afflictions");

					elseif (CEnemyCastBar_Afflictions[spell].multi) then	-- same debuff on target counter
						alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,"trueupdate","HoT", nil, "afflictions");
						if (alreadyshowing == 0) then
							alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,globalspell,nil,nil,"afflictions"); -- maybe on other mob, update bar for this one then
						end
					else
						alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,globalspell,nil,nil,"afflictions");
					end

					-- to detect if CPs are cleared AFTER a skill has been used, to update with correct duration afterwards if event "PLAYER_COMBO_POINTS" is fired
					if (CEnemyCastBar_Afflictions[spell].cpinterval and playersclass == CEnemyCastBar_Afflictions[spell].cpclass) then
						CECBownCPsHitBuffer = {mob, spell, GetTime(), DRTimer };
					end
	
					if (globalspell or (fragile and not CEnemyCastBar_PvPCheck()) ) then
						-- Network BCasting
						BCPacket = {mob, spell, special};
						local freetosend, latency = CEnemyCastBar_BCast_Control(bcasted);
						if ( freetosend ) then
							local modspell = spell;
							if (spellstacks) then
								modspell = spell.." "..spellstacks;
							end
							NECB_SendMessage(".cecbspell "..mob..", "..modspell..", "..special..", "..clientlang..", "..latency);
							LastSentBCPacket = {mob, modspell, special, GetTime()};
							LastGotBCPacket = {mob, modspell, special, GetTime()};
							necb_numspellcast = 0;
						end
					end

					if (alreadyshowing == 0) then

						-- turnaroundlabel through "globalspell" (turnlabel), because the name is more important then
						CEnemyCastBar_Show(mob, spell, castime, ctype, globalspell, icontex, nil, spellstacks);
					end
				end

			end -- is spell in database?
	 	end -- check for afflicted/ DoTs option + periodicdmg

	end -- clear on mob fades/dies, elseif check option, afflictions set on?
	------ block end (afflictions+)

end

function CEnemyCastBar_DR_DBCheck(mob, spell, castime, msg, realspell) --DR Check

	local i = 1;

	-- update on spellfade
	if (msg) then -- "fadeupdate"
		while i <= #NECB_DR_DB do
	
			if ( NECB_DR_DB[i][1] == mob and NECB_DR_DB[i][2] == spell ) then
	
				NECB_DR_DB[i][3] = GetTime();
				NECB_DR_DB[i][4] = castime;
				--DEFAULT_CHAT_FRAME:AddMessage("FadeUpdate Mob: "..mob.." |Spell: "..spell);
			end
			i = i + 1;
		end
		return;
	end

	local ashowing, drstate = 0, 0;
	local DRText;
	local DRDBUpdated = false;
	-- add DR to database
	while i <= #NECB_DR_DB do
		if ( GetTime() > ( NECB_DR_DB[i][3] + NECB_DR_DB[i][4] ) ) then
			table.remove(NECB_DR_DB, i);
			i = i - 1;
			--DEFAULT_CHAT_FRAME:AddMessage("Removed Mob: "..mob.." |Spell: "..spell);

		elseif ( NECB_DR_DB[i][1] == mob and NECB_DR_DB[i][2] == spell ) then

			DRText = NECB_DR_DB[i][5];
			if (string.match(DRText, "1/2")) then
				drstate = 4; DRText = "(|cffff00001/4|r)"; castime = castime/2 + 15;
			elseif (string.match(DRText, "1/4")) then
				drstate = 6; DRText = "(|cffff0000"..CECB_MISC_IMMUNE.."|r)"; castime = castime/4 + 15;
			elseif (string.match(DRText, CECB_MISC_IMMUNE)) then
				drstate = 2; DRText = "(|cffff00001/2|r)"; castime = castime + 15;
			end

			NECB_DR_DB[i][3] = GetTime();
			NECB_DR_DB[i][4] = castime;
			NECB_DR_DB[i][5] = DRText;
			DRDBUpdated = true;
			--DEFAULT_CHAT_FRAME:AddMessage("Updated Mob: "..mob.." |Spell: "..spell.." dr: "..drstate);
		end
		i = i + 1;
	end

	if ( not DRDBUpdated and #NECB_DR_DB < 15) then
		drstate = 2; DRText = "(|cffff00001/2|r)"; castime = castime + 15;
		table.insert(NECB_DR_DB, { mob, spell, GetTime(), castime, DRText, realspell } );
		--DEFAULT_CHAT_FRAME:AddMessage("Added Mob: "..mob.." |Spell: "..spell.." Nr.:"..#NECB_DR_DB);
	end
	return DRDBUpdated, drstate;

end


--[[

SPELLIMMUNESELFOTHER = "%1$s war ein Fehlschlag. %2$s ist immun.";
SPELLRESISTSELFOTHER = "Ihr habt es mit %1$s versucht, aber %2$s hat widerstanden.";

SPELLPARRIEDSELFOTHER = "%1$s wurde von %2$s pariert.";
SPELLREFLECTSELFOTHER = "%1$s wurde von %2$s reflektiert.";
SPELLBLOCKEDSELFOTHER = "%1$s wurde von %2$s geblockt.";
SPELLDEFLECTEDSELFOTHER = "%1$s wurde von %2$s abgewehrt.";

SPELLDODGEDSELFOTHER = "%2$s ist %1$s ausgewichen.";
SPELLEVADEDSELFOTHER = "%2$s ist %1$s entkommen.";

SPELLMISSSELFOTHER = "%1$s hat %2$s verfehlt.";

IMMUNESPELLSELFOTHER = "%1$s ist immun gegen %2$s von Euch.";
SPELLLOGABSORBSELFOTHER = "Euer Zauber %1$s wurde von %2$s absorbiert.";
--
PROCRESISTSELFOTHER = "%1$s widersteht %2$s.";

VSABSORBSELFOTHER = "Ihr greift an. %s absorbiert allen Schaden.";
VSBLOCKSELFOTHER = "Ihr greift an. %s blockt ab.";
VSDEFLECTSELFOTHER = "Ihr greift an. %s wehrt ab.";
VSDODGESELFOTHER = "Ihr greift an. %s weicht aus.";
VSEVADESELFOTHER = "Ihr greift an. %s entkommt.";
VSIMMUNESELFOTHER = "Ihr greift an, aber %s ist immun.";
VSPARRYSELFOTHER = "Ihr greift an. %s pariert.";,
VSRESISTSELFOTHER = "Ihr greift an. %s widersteht dem gesamten Schaden.";
IMMUNEDAMAGECLASSSELFOTHER = "%1$s ist immun gegen Euren %2$sschaden.";
]]--just to have a look later


NECB_Debuffs_Module_loaded = true;
--NECB_InfoFrame:AddMessage("|cffaaaaaaNECB:|r Debuffs Module loaded into memory!", 1, 0.5, 0, 1, UIERRORS_HOLD_TIME);