local _, ns = ...
local SlickUI = ns.SlickUI

local ClassAnnouncements = { LastCastGUID = nil }
SlickUI.ClassAnnouncements = ClassAnnouncements

-- Player-cast group utility and crowd-control abilities. Learned-spell checks
-- keep talent-specific entries hidden unless the current character can use them.
local ABILITIES = {
	DEATHKNIGHT = { 207167, 108199 }, -- Blinding Sleet, Gorefiend's Grasp
	DEMONHUNTER = { 179057, 202137, 207684 }, -- Chaos Nova, Sigil of Silence, Sigil of Misery
	DRUID = { 99, 102793, 102359, 132469 }, -- Incapacitating Roar, Ursol's Vortex, Mass Entanglement, Typhoon
	EVOKER = { 358385, 368970, 357214, 372048 }, -- Landslide, Tail Swipe, Wing Buffet, Oppressing Roar
	HUNTER = { 109248, 186387, 236776 }, -- Binding Shot, Bursting Shot, High Explosive Trap
	MAGE = { 31661, 157981, 113724, 383121 }, -- Dragon's Breath, Blast Wave, Ring of Frost, Mass Polymorph
	MONK = { 119381, 116844 }, -- Leg Sweep, Ring of Peace
	PALADIN = { 115750 }, -- Blinding Light
	PRIEST = { 8122, 108920 }, -- Psychic Scream, Void Tendrils
	ROGUE = { 2094 }, -- Blind
	SHAMAN = { 192058, 51490 }, -- Capacitor Totem, Thunderstorm
	WARLOCK = { 30283, 5484 }, -- Shadowfury, Howl of Terror
	WARRIOR = { 46968, 5246 }, -- Shockwave, Intimidating Shout
}

local function IsKnown(spellID)
	return SlickUI.Alerts and SlickUI.Alerts:IsKnownSpell(spellID)
end

local function SpellDisplay(spellID)
	local info = C_Spell and C_Spell.GetSpellInfo and C_Spell.GetSpellInfo(spellID)
	return info and info.name, info and info.iconID
end

function ClassAnnouncements:GetAvailableAbilities()
	local _, classToken = UnitClass("player")
	local result = {}
	for _, spellID in ipairs(ABILITIES[classToken] or {}) do
		if IsKnown(spellID) then
			local name, icon = SpellDisplay(spellID)
			if type(name) == "string" then result[#result + 1] = { spellID = spellID, name = name, icon = icon } end
		end
	end
	return result
end

function ClassAnnouncements:IsAbilityEnabled(spellID)
	local settings = SlickUI.DB and SlickUI.DB.classAnnouncements
	if not settings then return false end
	settings.abilities = settings.abilities or {}
	return settings.abilities[tostring(spellID)] ~= false
end

function ClassAnnouncements:SetAbilityEnabled(spellID, enabled)
	local settings = SlickUI.DB and SlickUI.DB.classAnnouncements
	if not settings then return end
	settings.abilities = settings.abilities or {}
	settings.abilities[tostring(spellID)] = enabled == true
end

function ClassAnnouncements:GetChannel()
	if IsInGroup and LE_PARTY_CATEGORY_INSTANCE and IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then return "INSTANCE_CHAT" end
	if IsInRaid and IsInRaid() then return "RAID" end
	if IsInGroup and IsInGroup() then return "PARTY" end
end

function ClassAnnouncements:Announce(spellID, castGUID)
	local settings = SlickUI.DB and SlickUI.DB.classAnnouncements
	if not settings or settings.enabled ~= true or not self:IsAbilityEnabled(spellID) then return end
	if castGUID and castGUID == self.LastCastGUID then return end
	local channel = self:GetChannel()
	if not channel then return end
	local name = SpellDisplay(spellID)
	if not name then return end
	self.LastCastGUID = castGUID
	SendChatMessage("[SlickUI] " .. name .. " used.", channel)
end

function ClassAnnouncements:Initialize()
	local frame = CreateFrame("Frame")
	frame:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", "player")
	frame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
	frame:RegisterEvent("TRAIT_CONFIG_UPDATED")
	frame:SetScript("OnEvent", function(_, event, unit, castGUID, spellID)
		if event == "UNIT_SPELLCAST_SUCCEEDED" and unit == "player" and type(spellID) == "number" then
			ClassAnnouncements:Announce(spellID, castGUID)
		elseif SlickUI.Options then
			SlickUI.Options:RefreshClassBuffControls()
		end
	end)
	self.EventFrame = frame
end

SlickUI:RegisterModule("ClassAnnouncements", ClassAnnouncements)
