---@diagnostic disable: undefined-global
local Muru = DBM:NewBossMod("Muru", DBM_MURU_NAME, DBM_MURU_DESCRIPTION, DBM_SUNWELL, DBM_SW_TAB, 5)

Muru.Version	= "1.0"
Muru.Author		= "Tandanu, Loid, Mart"
Muru.MinRevision = 1040

Muru.wavecount= 0

Muru:RegisterCombat("COMBAT", nil, nil, nil, DBM_MURU_ENTROPIUS)

Muru:AddOption("VoidWarn", true, DBM_MURU_OPTION_VOID)
Muru:AddOption("HumWarn", true, DBM_MURU_OPTION_HUM)
Muru:AddOption("WarnBlackHole", true, DBM_MURU_OPTION_HOLE_WARN)
Muru:AddOption("WarnFiend", true, DBM_MURU_OPTION_WARN_FIEND)
Muru:AddOption("DarknessCountdown", true, "Show 5 sec countdown before darkness")
Muru:AddOption("FlameBurstTooClose", true, "Show list of players too close for Flame Burst")
Muru:AddOption("WarnHealthstone", true, "Warn to healthstone 3 sec before Flame Burst if below 10k hp")

--Muru:AddBarOption("Enrage")
Muru:AddBarOption("Humanoids #(.*)")
Muru:AddBarOption("Void Sentinel")
Muru:AddBarOption("Next Darkness")
Muru:AddBarOption("Darkness active", false)
Muru:AddBarOption("Next Black Hole")
Muru:AddBarOption("Next Shadow Bomb")
Muru:AddBarOption("Next Flame Burst")

local p2 = false
local timeSinceLastUpdate = 0
local too_close_players = {}
local raid_member_versions = {}
local mec_version = "1.0"

Muru:RegisterEvents(
	"SPELL_AURA_APPLIED",
	"SPELL_SUMMON",
	"SPELL_CAST_SUCCESS"
)

local scale = GetCVar("uiScale")
local muruDBM = CreateFrame("Frame",nil,UIParent)

--darkness countdown
muruDBM.darknessCountdown = muruDBM:CreateFontString(nil, "ARTWORK")
muruDBM.darknessCountdown:SetHeight(40 / scale)
muruDBM.darknessCountdown:SetWidth(200 / scale)
muruDBM.darknessCountdown:SetFont("Fonts\\ARIALN.ttf", 30 / scale, "OUTLINE")
muruDBM.darknessCountdown:SetPoint("CENTER", UIParent, "CENTER")
muruDBM.darknessCountdown:SetJustifyH("CENTER")
muruDBM.darknessCountdown:SetTextColor(1,1,1,1)
muruDBM.darknessCountdown:SetShadowColor(0, 0, 0, 1)
muruDBM.darknessCountdown:SetShadowOffset(1, -1)
muruDBM.nextDarknessTime = 0
muruDBM.nextFlameBurstTime = 0
muruDBM:Hide()
muruDBM.darknessCountdown:Hide()

--too close frame
muruDBM.too_close_frame = CreateFrame("Frame",nil,UIParent)
muruDBM.too_close_frame:SetWidth(170)
muruDBM.too_close_frame:SetHeight(60)
muruDBM.too_close_frame:SetAlpha(.90)
muruDBM.too_close_frame:SetPoint("CENTER", -100 / scale, 0 / scale)
muruDBM.too_close_frame.text = muruDBM.too_close_frame:CreateFontString(nil,"ARTWORK") 
muruDBM.too_close_frame.text:SetFont("Fonts\\ARIALN.ttf", 15 / scale, "OUTLINE")
muruDBM.too_close_frame.text:SetPoint("TOP",0,0)
muruDBM.too_close_frame.text:SetText("")
muruDBM.too_close_frame:Hide()

--healthstone popup
muruDBM.healthstone = CreateFrame("Frame",nil,UIParent)
muruDBM.healthstone:SetHeight(65)
muruDBM.healthstone:SetWidth(65)
muruDBM.healthstone:SetPoint("CENTER", 0, 100 / scale)
muruDBM.healthstone.icon = muruDBM.healthstone:CreateTexture(nil, "ARTWORK")
muruDBM.healthstone.icon:SetAllPoints(true)
local _,_,dsIcon = GetSpellInfo(27236)
muruDBM.healthstone.icon:SetTexture(dsIcon)
muruDBM.healthstoneCount = 0
muruDBM.healthstone:Hide()

function muruDBM:update_Countdown()
    if not p2 and muruDBM.nextDarknessTime - GetTime() < 6 and muruDBM.nextDarknessTime - GetTime() > 0 then
        muruDBM.darknessCountdown:SetText("Darkness in "..math.floor(muruDBM.nextDarknessTime - GetTime()).."...")
        muruDBM.darknessCountdown:Show()
    else
        muruDBM.darknessCountdown:Hide()
    end
end

function muruDBM:updateTooClosePlayers()
	if p2 or muruDBM.nextFlameBurstTime - GetTime() >= 10 or muruDBM.nextFlameBurstTime - GetTime() <= -2 then
		muruDBM.too_close_frame:Hide()
		return
	end

	muruDBM.too_close_frame:Show()
	too_close_players = {}
	for i=1, GetNumRaidMembers(), 1 do
		if not UnitIsDeadOrGhost("raid"..i) and UnitName("raid"..i) ~= UnitName("player") then
			if CheckInteractDistance("raid"..i, 3) then too_close_players[#too_close_players+1] = UnitName("raid"..i) end
		end
	end

	local too_close_text = "|cffFF3990Too close to:|r\n"
	for i=1, #too_close_players do
		too_close_text = too_close_text .. too_close_players[i] .. '\n'
	end
	muruDBM.too_close_frame.text:SetText(too_close_text)
	too_close_players = {}
end

function muruDBM:updateHealthstone()
	if p2 or muruDBM.nextFlameBurstTime - GetTime() >= 3 or muruDBM.nextFlameBurstTime - GetTime() <= -2 then
		muruDBM.healthstone:Hide()
		return
	end

	if not (GetItemCount(22103) > 0 or GetItemCount(22104) > 0 or GetItemCount(22105) > 0) then
		muruDBM.healthstone:Hide()
		return
	end

	if GetItemCooldown(22103) ~= 0 then
		muruDBM.healthstone:Hide()
		return
	end

	if UnitHealth("player") >= 10000 then
		muruDBM.healthstone:Hide()
		return
	end

	muruDBM.healthstone:Show()
end

function Muru:OnCombatStart(delay)
	self.wavecount = 1
	p2 = false
	--self:StartStatusBarTimer(600 - delay, "Enrage", "Interface\\Icons\\Spell_Shadow_UnholyFrenzy")

	self:StartStatusBarTimer(8 - delay, "Humanoids #1", "Interface\\Icons\\Spell_Holy_PrayerOfHealing")
	self:ScheduleMethod(8 - delay, "HumanoidSpawn")

	self:ScheduleMethod(30 - delay, "VoidSpawn")
	self:StartStatusBarTimer(30 - delay, "Void Sentinel", "Interface\\Icons\\Spell_Shadow_SummonVoidWalker")

	self:StartStatusBarTimer(48 - delay, "Next Darkness", 45996)
	self:ScheduleMethod(48 - delay, "DarknessSpawn")
	muruDBM.darknessCountdown:Hide()
	muruDBM.nextDarknessTime = GetTime() + 48 - delay
	muruDBM:Show()

	muruDBM.too_close_frame:Hide()
	muruDBM.healthstone:Hide()

	muruDBM.healthstoneCount = GetItemCount(22103) + GetItemCount(22104) + GetItemCount(22105)
end

function Muru:OnCombatEnd()
	muruDBM.darknessCountdown:Hide()
	muruDBM.too_close_frame:Hide()
	muruDBM.healthstone:Hide()
	muruDBM:Hide()
	self.wavecount = 0;
end

function Muru:OnEvent(event, args)
	if event == "SPELL_AURA_APPLIED" then
		if args.spellId == 46102 then
			if args.auraType == "BUFF" then
				if self.Options.WarnSpellFury then
					self:Announce("Spell Fury", 2)
				end
			end
		end
	elseif event == "SPELL_SUMMON" then
		if args.spellId == 46268 then
			self:SendSync("Fiend")
		elseif args.spellId == 46282 then
			self:SendSync("BlackHole")
		end
	elseif event == "SPELL_CAST_SUCCESS" then
		--Black Hole
		if args.spellId == 46282 then
			self:SetIcon(args.destName, 15, 6)
		end

		if args.spellId == 46269 and tostring(args.destName) == UnitName("player") then
			SendChatMessage("Void Zone under me soon!", "SAY")
		end
		if args.spellId == 46282 and tostring(args.destName) == UnitName("player") then
			SendChatMessage("Orb spawning here soon!", "SAY")
		end
	end
end

function Muru:OnSync(msg)
	if msg == "Fiend" then
		if self.Options.WarnFiend then
			self:Announce(DBM_MURU_WARN_FIEND, 3)
		end
	elseif msg == "BlackHole" then
		if self.Options.WarnBlackHole then
			self:Announce(DBM_MURU_WARN_BLACKHOLE, 2)
		end
		self:StartStatusBarTimer(15, "Next Black Hole", "Interface\\Icons\\Ability_Hunter_Resourcefulness")
	elseif msg == "Phase2" then
		p2 = true
		self:Announce(DBM_MURU_WARN_P2, 1)
		self:UnScheduleMethod("HumanoidSpawn")
		self:UnScheduleMethod("VoidSpawn")
		self:UnScheduleMethod("DarknessSpawn")
		self:EndStatusBarTimer("Humanoids" .. " #" .. self.wavecount)
		self:EndStatusBarTimer("Void Sentinel")
		self:EndStatusBarTimer("Next Darkness")
		self:EndStatusBarTimer("Next Shadow Bomb")
		self:EndStatusBarTimer("Next Flame Burst")
		muruDBM.darknessCountdown:Hide()
		muruDBM.too_close_frame:Hide()
		muruDBM.healthstone:Hide()
	end
end

function Muru:HumanoidSpawn()
	if self.wavecount % 2 == 1 then 
		self:StartStatusBarTimer(39, "Next Shadow Bomb", "Interface\\Icons\\spell_arcane_arcane02")
	else
		self:StartStatusBarTimer(38, "Next Flame Burst", "Interface\\Icons\\spell_fire_bluerainoffire")
		muruDBM.nextFlameBurstTime = GetTime() + 38
	end

	self.wavecount = self.wavecount + 1
	if self.Options.HumWarn then
		self:Announce(DBM_MURU_WARN_HUMANOIDS_NOW, 2)
	end
	self:StartStatusBarTimer(60, "Humanoids" .. " #" .. self.wavecount, "Interface\\Icons\\Spell_Holy_PrayerOfHealing", true)
	self:ScheduleMethod(60, "HumanoidSpawn")
end

function Muru:VoidSpawn()
	if self.Options.VoidWarn then
		self:Announce(DBM_MURU_WARN_VOID_NOW, 3)
	end
	self:ScheduleMethod(30, "VoidSpawn")
	self:StartStatusBarTimer(30, "Void Sentinel", "Interface\\Icons\\Spell_Shadow_SummonVoidWalker")
end

function Muru:DarknessSpawn()
	if self.Options.WarnDarkness then
		self:Announce(DBM_MURU_DARKNESS_INC, 4)
	end
	--30910 for curse of doom symbol instead
	self:StartStatusBarTimer(20, "Darkness active", 45996)
	self:StartStatusBarTimer(45, "Next Darkness", 45996)
	self:ScheduleMethod(45, "DarknessSpawn")
	muruDBM.nextDarknessTime = GetTime() + 45
end

function Muru:OnUpdate(elapsed)
	timeSinceLastUpdate = timeSinceLastUpdate + elapsed
	if timeSinceLastUpdate < 0.25 then return end
	timeSinceLastUpdate = 0
	if self.Options.DarknessCountdown then
		muruDBM:update_Countdown()
	end

	if self.Options.FlameBurstTooClose then
		muruDBM:updateTooClosePlayers()
	end

	if self.Options.WarnHealthstone then
		muruDBM:updateHealthstone()
	end

	if p2 or not self.InCombat then return end
	for i = 1, GetNumRaidMembers() do
		if UnitName("raid"..i.."target") == DBM_MURU_ENTROPIUS and not UnitIsPlayer("raid"..i.."target") then
			self:SendSync("Phase2")
		end
	end
end

function Muru:GetBossHP()
	if p2 then
		return DBM_MURU_ENTROPIUS..": "..DBM.GetHPByName(DBM_MURU_ENTROPIUS)
	else
		return DBM.GetHPByName(DBM_MURU_NAME)
	end
end

function muruDBM:OnEvent(event, ...)
    if event == "CHAT_MSG_ADDON" then
		if arg1 == "MURU_VERSION" then
			local _, msgTxt, _, unitName = ...
			if msgTxt == "TELL" then
				SendAddonMessage("MURU_VERSION", mec_version, "WHISPER", unitName)
			elseif msgTxt ~= "TELL" then
				raid_member_versions[unitName] = msgTxt
			end
		end
	end
end
muruDBM:RegisterEvent("CHAT_MSG_ADDON")
muruDBM:SetScript("OnEvent", muruDBM.OnEvent)

local function setTimer(duration, func)
    local timer = CreateFrame("FRAME");
    local endTime = GetTime() + duration;

    timer:SetScript("OnUpdate", function()
        if(endTime < GetTime()) then
            func();
            timer:SetScript("OnUpdate", nil);
        end
    end);
end

local function print(msg)
	DEFAULT_CHAT_FRAME:AddMessage(msg)
end

local function printVersions()
	for i=1, GetNumRaidMembers(), 1 do
		if raid_member_versions[UnitName("raid"..i)] ~= nil then
			print(UnitName("raid"..i) ..": ".. raid_member_versions[UnitName("raid"..i)])
		else
			print(UnitName("raid"..i) ..": no response")
		end
	end
end

_G.SLASH_DBMMURU1 = '/muru'
function SlashCmdList.DBMMURU(command)
	if not command then return end
	if GetNumRaidMembers() ~= 0 then
		SendAddonMessage("MURU_VERSION", "TELL", "RAID")
		print("~~~~~~~~~~~~~~~~~~~~~~~~")
		print("Waiting on responses from raiders...")

		setTimer(2, function() printVersions() end)
	end
end
