local Kal = DBM:NewBossMod("Kal", DBM_KAL_NAME, DBM_KAL_DESCRIPTION, DBM_SUNWELL, DBM_SW_TAB, 1)

Kal.Version		= "1.0"
Kal.Author		= "Tandanu"
Kal.MinRevision = 988

Kal:RegisterCombat("YELL", DBM_KAL_YELL_PULL, nil, nil, DBM_KAL_KILL_NAME)

Kal:RegisterEvents(
	"SPELL_CAST_START",
	"SPELL_AURA_APPLIED",
	"SPELL_AURA_APPLIED_DOSE",
	"SPELL_AURA_REMOVED", -- this will fire just after SPELL_AURA_DISPELLED, so there's no need to check for SPELL_AURA_DISPELLED
	"UNIT_DIED",
	"UNIT_HEALTH",
	"CHAT_MSG_ADDON"
)

Kal:AddOption("WarnBreathNew", false, DBM_KAL_OPTION_BREATH)
Kal:AddOption("PreWarnBreathNew", false, DBM_KAL_OPTION_PREBREATH)
Kal:AddOption("RangeCheck", false, DBM_KAL_OPTION_RANGE)
Kal:AddOption("SpecWarnMagic", true, DBM_KAL_OPTION_WM_WARN2)
Kal:AddOption("WhisperMagic", true, DBM_KAL_OPTION_WM_WHISPER)
Kal:AddOption("WarnCoA", true, DBM_KAL_OPTION_COA_WARN)
Kal:AddOption("CoAIcon", false, DBM_KAL_OPTION_COA_ICON)
Kal:AddOption("PreWarnPort", true, DBM_KAL_OPTION_PORT_PREWARN)
Kal:AddOption("WarnPort", true, DBM_KAL_OPTION_PORT_WARN)
Kal:AddOption("ShowFrame", true, DBM_KAL_OPTION_SHOWFRAME)
Kal:AddOption("FrameLocked", false, DBM_KAL_MENU_LOCK)
Kal:AddOption("WarnStrike", false, DBM_KAL_OPTION_STRIKE)
Kal.Options.FramePoint = "CENTER"
Kal.Options.FrameX = 150
Kal.Options.FrameY = -50


Kal:AddOption("FrameClassColor", true, DBM_KAL_FRAME_COLORS, function()
	Kal.Options.FrameClassColor = not Kal.Options.FrameClassColor
	Kal:UpdateColors() 
end)
Kal:AddOption("FrameUpwards", false, DBM_KAL_FRAME_UPWARDS, function()
	Kal.Options.FrameUpwards = not Kal.Options.FrameUpwards
	Kal:ChangeFrameOrientation()
end)

local healthFrame

Kal:AddOption("ShowHPFrame", true, DBM_KAL_OPTION_FRAME, function()
	Kal.Options.ShowHPFrame = not Kal.Options.ShowHPFrame 
	if Kal.Options.ShowHPFrame and Kal.InCombat then
		Kal:CreateHealthFrame()
	end
end)

Kal:AddBarOption("Arcane Buffet")
Kal:AddBarOption("Frost Breath", false)
Kal:AddBarOption("Next Portal #(.*)")
Kal:AddBarOption("Portal #(.*)")
Kal:AddBarOption("Ported")
Kal:AddBarOption("Exhausted")
Kal:AddBarOption("CoA: (.*)")


local noPortWarn = 0
local portCounter = 0
local last_kalec_hp_update = GetTime()
local last_sarth_hp_update = GetTime()


function Kal:OnCombatStart()
	noPortWarn = 0
	portCounter = 0
	if self.Options.ShowFrame then
		self:CreateFrame()
	end
	if self.Options.RangeCheck then
		DBM_Gui_DistanceFrame_Show()
	end
	if self.Options.ShowHPFrame then
		self:CreateHealthFrame()
	end
end

function Kal:OnCombatEnd()
	self:DestroyFrame()
	DBM_Gui_DistanceFrame_Hide()
	self:HideHealthFrame()
end

local function split(inputstr, sep)
	if sep == nil then
		sep = "%s"
	end
	local t={}
	for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
		table.insert(t, str)
	end
	return t
end

function Kal:OnEvent(event, args, ...)
	if event == "SPELL_CAST_START" then
		if args.spellId == DBM_KAL_SPELLID_BREATH then
			self:SendSync("Breath")
		end
	elseif event == "SPELL_AURA_APPLIED" then
		if args.spellId and DBM_KAL_SPELLIDS_WM[args.spellId] then
			self:SendSync("WM"..tostring(args.spellId)..tostring(args.destName))
		elseif args.spellId == DBM_KAL_SPELLID_COA1 or args.spellId == DBM_KAL_SPELLID_COA2 then
			self:SendSync("CoA"..tostring(args.destName))
		elseif args.spellId == DBM_KAL_SPELLID_PORT1 then
			self:SendSync("Port"..tostring(args.destName))
		elseif args.spellId == DBM_KAL_SPELLID_BUFFET then
			self:SendSync("Buffet")
		elseif args.spellId == 45029 then
			self:SendSync("Strike"..tostring(args.destName))
		end
	elseif event == "SPELL_AURA_APPLIED_DOSE" then
		if args.spellId == DBM_KAL_SPELLID_BUFFET then
			self:SendSync("Buffet")
		end
	elseif event == "SPELL_AURA_REMOVED" then
		if args.spellId == DBM_KAL_SPELLID_COA1 or args.spellId == DBM_KAL_SPELLID_COA2 then
			self:SendSync("ECoA"..tostring(args.destName))
		end
	elseif event == "UNIT_DIED" then
		if bit.band(args.destFlags, COMBATLOG_OBJECT_TYPE_PLAYER) ~= 0 then
			self:SendSync("Down"..tostring(args.destName))
		end
	elseif event == "UNIT_HEALTH" and UnitIsEnemy(arg1, "player") then
		if UnitName(arg1) == DBM_KAL_NAME then
			self:SendSync("HPDragon"..tostring(UnitHealth(arg1)))
		elseif UnitName(arg1) == DBM_KAL_KILL_NAME then
			self:SendSync("HPDemon"..tostring(UnitHealth(arg1)))
		end
	elseif event == "CHAT_MSG_ADDON" then
        if arg1 ~= "DBM_KALEC" then return end
        local msgTxt = arg2

        local boss_name = split(msgTxt, "~")[1]
        local prct_hp = split(msgTxt, "~")[2]
		
		if healthFrame ~= nil then
			if boss_name == "Kalec" then
				healthFrame.bar1:SetValue(prct_hp)
				getglobal(healthFrame.bar1:GetObject():GetName().."RightText"):SetText(tostring(prct_hp).."%")
				--healthFrame.bar1:GetObject():SetStatusBarColor(1 - (prct_hp/100), prct_hp/100, 0)
				last_kalec_hp_update = GetTime()
			elseif boss_name == "Sath" then
				healthFrame.bar2:SetValue(prct_hp)
				getglobal(healthFrame.bar2:GetObject():GetName().."RightText"):SetText(tostring(prct_hp).."%")
				--healthFrame.bar2:GetObject():SetStatusBarColor(1 - (prct_hp/100), prct_hp/100, 0)
				last_sarth_hp_update = GetTime()
			end
		end
    end
end

local function getUnitId(name)
	for i = 1, GetNumRaidMembers() do
		if UnitName("raid"..i) == name then
			return "raid"..i
		end
	end	
	return "raid41" -- to avoid nil error messages
end

function Kal:OnSync(msg, sender)
	if msg == "Breath" then
		self:StartStatusBarTimer(15.5, "Frost Breath", "Interface\\Icons\\Spell_Frost_FrostBlast")
		if self.Options.WarnBreathNew then
			self:Announce(DBM_KAL_WARN_BREATH, 3)
		end		
		if self.Options.PreWarnBreathNew then
			self:ScheduleAnnounce(12.5, DBM_KAL_WARN_BREATH_SOON, 1)
		end
	elseif msg:sub(0, 2) == "WM" then
		msg = msg:sub(3)
		local _, _, spellId, name = msg:find("(%d+)(.+)")
		if spellId then
			spellId = tonumber(spellId)
			local spellType = DBM_KAL_SPELLIDS_WM[spellId]
		
			if spellType == "Cast" then 	-- Casting time increased by 100%.
				if UnitPowerType(getUnitId(name)) == 0 then
					if self.Options.SpecWarnMagic and name == UnitName("player") then
						self:AddSpecialWarning(DBM_KAL_WARN_CASTTIME)
					end
					if self.Options.WhisperMagic then
						self:SendHiddenWhisper(DBM_KAL_WHISPER_WM:format(DBM_KAL_WARN_CASTTIME), name)
					end
				end
			elseif spellType == "Hit" then	-- Chance to hit with melee and ranged attacks reduced by 50%.
				local _, class = UnitClass(getUnitId(name))
				if class == "WARRIOR"
				or class == "ROGUE"
				or class == "HUNTER"
				or (class == "DRUID" and (UnitPowerType(getUnitId(name)) == 1 or UnitPowerType(getUnitId(name)) == 3))
				or (class == "SHAMAN" and (UnitManaMax(getUnitId(name)) or 0) < 10000) then
					if self.Options.SpecWarnMagic and name == UnitName("player") then
						self:AddSpecialWarning(DBM_KAL_WARN_HIT)
					end
					if self.Options.WhisperMagic then
						self:SendHiddenWhisper(DBM_KAL_WHISPER_WM:format(DBM_KAL_WARN_HIT), name)
					end
				end
			elseif spellType == "Crit" then	-- Damage done by critical hits increased by 100%.
				local _, class = UnitClass(getUnitId(name))
				if class == "WARRIOR"
				or class == "ROGUE"
				or class == "HUNTER"
				or (class == "DRUID" and (UnitPowerType(getUnitId(name)) == 1 or UnitPowerType(getUnitId(name)) == 3))
				or (class == "SHAMAN" and (UnitManaMax(getUnitId(name)) or 0) < 10000) then
					if self.Options.SpecWarnMagic and name == UnitName("player") then
						self:AddSpecialWarning(DBM_KAL_WARN_CRIT)
					end
					if self.Options.WhisperMagic then
						self:SendHiddenWhisper(DBM_KAL_WHISPER_WM:format(DBM_KAL_WARN_CRIT), name)
					end
				end
			elseif spellType == "Aggro" then -- Increases threat generated by 100%.
				if self.Options.SpecWarnMagic and name == UnitName("player") then
					self:AddSpecialWarning(DBM_KAL_WARN_AGGRO)
				end
				if self.Options.WhisperMagic then
					self:SendHiddenWhisper(DBM_KAL_WHISPER_WM:format(DBM_KAL_WARN_AGGRO), name)
				end
			elseif spellType == "Heal" then -- Healing done by spells and effects increased by 100%.
				local _, class = UnitClass(getUnitId(name))
				if (class == "PRIEST" and not DBM.GetBuff(getUnitId(name), GetSpellInfo(15473)))
				or class == "PALADIN"
				or (class == "DRUID" and UnitPowerType(getUnitId(name)) == 0)
				or (class == "SHAMAN" and (UnitManaMax(getUnitId(name)) or 0) > 10000) then
					if self.Options.SpecWarnMagic and name == UnitName("player") then
						self:AddSpecialWarning(DBM_KAL_WARN_HEAL)
					end
					if self.Options.WhisperMagic then
						self:SendHiddenWhisper(DBM_KAL_WHISPER_WM:format(DBM_KAL_WARN_HEAL), name)
					end
				end				
			elseif spellType == "Cost" then	-- Spell and ability costs reduced by 50%.
				if self.Options.SpecWarnMagic and name == UnitName("player") then
					self:AddSpecialWarning(DBM_KAL_WARN_COST)
				end
				if self.Options.WhisperMagic then
					self:SendHiddenWhisper(DBM_KAL_WHISPER_WM:format(DBM_KAL_WARN_COST), name)
				end
			end

		end
	elseif msg:sub(0, 3) == "CoA" then
		msg = msg:sub(4)
		if self.Options.WarnCoA then
			self:Announce(DBM_KAL_WARN_COA:format(msg), 4)
		end
		if self.Options.CoAIcon then
			self:SetIcon(msg, 30)
		end
		self:StartStatusBarTimer(30, "CoA: "..msg, "Interface\\Icons\\Spell_Shadow_CurseOfSargeras")
	elseif msg:sub(0, 4) == "ECoA" then
		msg = msg:sub(5)
		if self.Options.CoAIcon then
			self:RemoveIcon(msg)
		end
		self:EndStatusBarTimer("CoA: "..msg)
	elseif msg:sub(0, 4) == "Port" then
		msg = msg:sub(5)
		local grp, class
		for i = 1, GetNumRaidMembers() do
			local name, _, subgroup, _, _, fileName = GetRaidRosterInfo(i)
			if name == msg then
				grp = subgroup
				class = fileName
				break
			end
		end
		
		if (GetTime() - noPortWarn) > 20 then
			noPortWarn = GetTime()
			portCounter = portCounter + 1
			if self.Options.WarnPort then
				self:Announce(DBM_KAL_WARN_PORT:format(portCounter, msg, (grp or 0)), 2)
			end
			if self.Options.PreWarnPort then
				self:ScheduleAnnounce(22, DBM_KAL_WARN_PORT_SOON:format(portCounter + 1), 1)
			end
			self:StartStatusBarTimer(25, "Next Portal #"..(portCounter + 1), "Interface\\Icons\\Spell_Arcane_PortalUnderCity")
			self:StartStatusBarTimer(15, "Portal #"..portCounter, "Interface\\Icons\\Spell_Arcane_PortalUnderCity")
		end
		
		if msg == UnitName("player") then
			self:StartStatusBarTimer(60, "Ported", "Interface\\Icons\\Spell_Arcane_PortalUnderCity", true)
			self:ScheduleMethod(60, "StartStatusBarTimer", 60, "Exhausted", "Interface\\Icons\\Spell_Shadow_Teleport", true)
		end		
		self:AddEntry(("%s (%d)"):format(msg, grp or 0), class)
		
	elseif msg:sub(0, 4) == "Down" then
		msg = msg:sub(5)
		self:RemoveIcon(msg)
		self:EndStatusBarTimer("CoA: "..msg)
		local grp
		for i = 1, GetNumRaidMembers() do
			local name, _, subgroup = GetRaidRosterInfo(i)
			if name == msg then
				grp = subgroup
				break
			end
		end
		self:RemoveEntry(("%s (%d)"):format(msg, grp or 0))
	elseif msg == "Buffet" then
		self:StartStatusBarTimer(8, "Arcane Buffet", DBM_KAL_SPELLID_BUFFET)
	elseif msg:sub(0, 6) == "Strike" and self.InCombat then
		msg = msg:sub(7)
		if self.Options.WarnStrike then
			self:Announce(DBM_KAL_WARN_STRIKE:format(msg), 1)
		end
	end
end

function Kal:CreateHealthFrame()
	if healthFrame then
		healthFrame:Show()
		healthFrame.bar1:SetValue(100)
		getglobal(healthFrame.bar1:GetObject():GetName().."RightText"):SetText("100%")
		healthFrame.bar1:GetObject():SetStatusBarColor(0, 1, 0)
		healthFrame.bar2:SetValue(100)
		getglobal(healthFrame.bar2:GetObject():GetName().."RightText"):SetText("100%")
		healthFrame.bar2:GetObject():SetStatusBarColor(0, 1, 0)
	else
		healthFrame = DBMGui:CreateInfoFrame(DBM_KAL_HEALTHFRAME_TITLE)
		
		local scale = GetCVar("uiScale")
		local borderWidth = 2 / scale
		local borderColor = {1, 1, 1}
		local backdrop = {
			bgFile = "Interface/Tooltips/UI-Tooltip-Background",
			--bgFile = "Interface\\AddOns\\DBM_API\\Textures\\Smoothv2",
			edgeFile = "Interface\\Buttons\\WHITE8x8",
			tileEdge = false,
			edgeSize = borderWidth,
			insets = {left = borderWidth, right = borderWidth, top = borderWidth, bottom = borderWidth},
		}
		healthFrame["Frame"]:SetBackdrop(backdrop)
		healthFrame["Frame"]:SetBackdropBorderColor(borderColor[1], borderColor[2], borderColor[3], 1)
		healthFrame.bar1 = healthFrame:CreateStatusBar(0, 100, 100, nil, DBM_KAL_NAME, "100%")
		healthFrame.bar1:GetObject():SetStatusBarTexture("Interface\\AddOns\\DBM_API\\Textures\\Smoothv2")
		healthFrame.bar2 = healthFrame:CreateStatusBar(0, 100, 100, nil, DBM_KAL_DEMON_SHORT, "100%")
		healthFrame.bar2:GetObject():SetStatusBarTexture("Interface\\AddOns\\DBM_API\\Textures\\Smoothv2")
	end
end

function Kal:HideHealthFrame()
	if healthFrame then
		healthFrame:Hide()
	end
end


Kal.UpdateInterval = 0.2;
local maxhp, hp, prct_hp;
function Kal:OnUpdate(elapsed)
	if healthFrame ~= nil then
		if (GetTime() - last_kalec_hp_update < 0.25) and (GetTime() - last_sarth_hp_update < 0.25) then return end;
		for i = 1, GetNumRaidMembers() do
			if UnitName("raid"..i.."target") then
				if UnitName("raid"..i.."target") == "Kalecgos" and UnitIsEnemy("raid"..i, "raid"..i.."target") then
					maxhp = UnitHealthMax("raid"..i.."target")
					hp = UnitHealth("raid"..i.."target")
					prct_hp = math.floor(hp / maxhp * 100)
					SendAddonMessage("DBM_KALEC", "Kalec~"..prct_hp, "RAID")
				elseif UnitName("raid"..i.."target") == "Sathrovarr the Corruptor" then
					maxhp = UnitHealthMax("raid"..i.."target")
					hp = UnitHealth("raid"..i.."target")
					prct_hp = math.floor(hp / maxhp * 100)
					SendAddonMessage("DBM_KALEC", "Sath~"..prct_hp, "RAID")
				end
			end
		end
	end
end
