---@class aura_env
---@field messageQueue Message[]
---@field separator string
---@field addonprefix string
---@field config table<string, any>
---@field stinkies Stinky[]
---@field raceFactions table<string, string>
---@field localStinkies table<string, Stinky>
---@field soundNotifyTimer table<string, number>
---@field GetZone fun(): string
---@field RegisterKill fun(source: string, destination: string, spellName: string, overkill: number)
---@field StinkyDetected fun(name: string)

aura_env.soundNotifyTimer = {}
aura_env.messageQueue = {}
aura_env.separator = "ž"
aura_env.addonprefix = "STINKY_DETECTOR"
RegisterAddonMessagePrefix(aura_env.addonprefix)

---@param input string
---@param deliminer string
---@return string[], string|nil
local function StrSplit(input, deliminer)
	if not deliminer then return {}, "deliminer is nil" end
	if not input then return {}, "input is nil" end
	local parts = {}
	for part in string.gmatch(input, "([^" .. deliminer .. "]+)") do
		table.insert(parts, strtrim(part))
	end
	return parts, nil
end

---@type string[]
local toNotify = StrSplit(aura_env.config.notify, ",")
for i, part in ipairs(toNotify) do
	toNotify[i] = strtrim(part)
end
WeakAurasSaved.Cyka.stinkies = {}
if not WeakAurasSaved.Cyka.PlayerFactionCache then WeakAurasSaved.Cyka.PlayerFactionCache = {} end


---@class Message
---@field message string
---@field to string
---@field channel string
---@field addon boolean
Message = {
	message = "",
	to = "",
	channel = "",
	addon = false,

	---@param message string
	---@param to string
	---@param channel string
	---@param addon? boolean
	---@return Message
	new = function(message, to, channel, addon)
		local self = setmetatable({}, {
			__index = Message
		})
		self.message = message
		self.to = to
		self.channel = channel
		self.addon = addon or false
		return self
	end,

	---@param stinky Stinky
	QueueNotifyGuild = function(stinky)
		if not aura_env.config.stinkyNotifyGuild then return end
		if aura_env.config.debug then print("Queueing notify guild:") end
		local message = Message.new(stinky:FormMessage(), nil, "GUILD")
		if aura_env.config.debug then DevTools_Dump(message) end
		table.insert(aura_env.messageQueue, message)
	end,
	---@param stinky Stinky
	QueueNotifyWhisper = function(stinky)
		if not aura_env.config.stinkyNotifyWhisper then return end
		if aura_env.config.debug then print("Queueing notify whisper:") end
		local text = stinky:FormMessage()
		for _, to in ipairs(toNotify) do
			local message = Message.new(text, to, "WHISPER")
			if aura_env.config.debug then DevTools_Dump(message) end
			table.insert(aura_env.messageQueue, message)
		end
	end,

	---@param stinky Stinky
	QueueNotifyAddonGuild = function(stinky)
		if not aura_env.config.stinkyNotifyAddonGuild then return end
		if aura_env.config.debug then print("Queueing notify addon guild:") end
		local message = Message.new(stinky:FormAddonMessage(), nil, "GUILD", true)
		if aura_env.config.debug then DevTools_Dump(message) end
		table.insert(aura_env.messageQueue, message)
	end,
	---@param stinky Stinky
	QueueNotifyAddonWhisper = function(stinky)
		if not aura_env.config.stinkyNotifyAddonWhisper then return end
		if aura_env.config.debug then print("Queueing notify addon whisper:") end
		local text = stinky:FormAddonMessage()
		for _, to in ipairs(toNotify) do
			local message = Message.new(text, to, "WHISPER", true)
			if aura_env.config.debug then DevTools_Dump(message) end
			table.insert(aura_env.messageQueue, message)
		end
	end,

	---@param faction string
	---@param source string
	---@param destination string
	---@param spellName string
	QueueNotifyKilledAddonGuild = function(faction, source, destination, spellName)
		if not aura_env.config.killNotifyAddonGuild then return end
		if aura_env.config.debug then print("Queueing notify addon guild:") end
		local text = table.concat({ faction, source, spellName }, aura_env.separator)
		local message = Message.new(text, nil, "GUILD", true)
		if aura_env.config.debug then DevTools_Dump(message) end
		table.insert(aura_env.messageQueue, message)
	end,
	---@param faction string
	---@param source string
	---@param destination string
	---@param spellName string
	QueueNotifyKilledAddonWhisper = function(faction, source, destination, spellName)
		if not aura_env.config.killNotifyAddonWhisper then return end
		if aura_env.config.debug then print("Queueing notify addon whisper:") end
		local text = table.concat({ faction, source, destination, spellName }, aura_env.separator)
		for _, to in ipairs(toNotify) do
			local message = Message.new(text, to, "WHISPER", true)
			if aura_env.config.debug then DevTools_Dump(message) end
			table.insert(aura_env.messageQueue, message)
		end
	end,

	---@param faction string
	---@param source string
	---@param destination string
	---@param spellName string
	QueueNotifyKilledGuild = function(faction, source, destination, spellName)
		if not aura_env.config.killNotifyGuild then return end
		if aura_env.config.debug then print("Queueing notify guild:") end
		local text = string.format("%s %s убил %s с помощью %s", faction, source, destination, spellName)
		local message = Message.new(text, nil, "GUILD")
		if aura_env.config.debug then DevTools_Dump(message) end
		table.insert(aura_env.messageQueue, message)
	end,
	---@param faction string
	---@param source string
	---@param destination string
	---@param spellName string
	QueueNotifyKilledWhisper = function(faction, source, destination, spellName)
		if not aura_env.config.killNotifyWhisper then return end
		if aura_env.config.debug then print("Queueing notify whisper:") end
		local text = string.format("%s %s убил %s с помощью %s", faction, source, destination, spellName)
		for _, to in ipairs(toNotify) do
			local message = Message.new(text, to, "WHISPER")
			if aura_env.config.debug then DevTools_Dump(message) end
			table.insert(aura_env.messageQueue, message)
		end
	end
}

---@class Stinky
---@field name string
---@field threat number 1-10 10 being maxima threat
---@field note string|nil
Stinky = {
	name = "",
	threat = 0,
	note = "",

	---@param name string
	---@param threat number
	---@param note string|nil
	---@return Stinky
	new = function(name, threat, note)
		local self = setmetatable({}, {
			__index = Stinky
		})
		self.name = name
		self.threat = threat
		self.note = note
		return self
	end,

	---@param self Stinky
	---@return string
	FormMessage = function(self)
		return string.format("%s in %s!", self.name, aura_env.GetZone())
	end,
	---@param self Stinky
	---@return string
	FormAddonMessage = function(self)
		return table.concat({ self.name, self.threat, aura_env.GetZone() }, aura_env.separator)
	end,
}

aura_env.raceFactions = {
	["Orc"] = "Horde",
	["Undead"] = "Horde",
	["Tauren"] = "Horde",
	["Troll"] = "Horde",
	["BloodElf"] = "Horde",
	["Goblin"] = "Horde",
	["Human"] = "Alliance",
	["Dwarf"] = "Alliance",
	["NightElf"] = "Alliance",
	["Gnome"] = "Alliance",
	["Draenei"] = "Alliance",
	["Worgen"] = "Alliance",
}

aura_env.GetZone = function()
	return string.format("%s (%s)", GetZoneText(), GetSubZoneText())
end

local stinkies = StrSplit(aura_env.config.stinkies, ",")
for i, part in ipairs(stinkies) do
	local datum = StrSplit(part, ":")
	local name = strtrim(datum[1])
	if name then
		local threat = tonumber(strtrim(datum[2] or "5"))
		WeakAurasSaved.Cyka.stinkies[name] = Stinky.new(name, threat)
	end
end

local killSpamTime = 10
local recentlyKilled = {}
aura_env.RegisterKill = function(source, destination, spellName, overkill)
	if recentlyKilled[source] and recentlyKilled[source] > GetTime() - killSpamTime then
		print("Death already reported")
		return
	end
	if overkill <= 0 then return end

	local faction = "Неизвестная фракция"
	if WeakAurasSaved.Cyka.PlayerFactionCache[source] then
		faction = WeakAurasSaved.Cyka.PlayerFactionCache[source]
	end

	Message.QueueNotifyKilledGuild(faction, source, destination, spellName)
	Message.QueueNotifyKilledWhisper(faction, source, destination, spellName)
	Message.QueueNotifyKilledAddonGuild(faction, source, destination, spellName)
	Message.QueueNotifyKilledAddonWhisper(faction, source, destination, spellName)

	recentlyKilled[source] = GetTime()
end

aura_env.localStinkies = {}

---@param name string
aura_env.StinkyDetected = function(name)
	if aura_env.config.debug then print(string.format("StinkyDetected (%s)", name)) end
	local stinky = WeakAurasSaved.Cyka.stinkies[name]
	if not aura_env.localStinkies[name] or aura_env.localStinkies[name] <
		GetTime() - aura_env.config.messageThrottle then
		Message.QueueNotifyGuild(stinky)
		Message.QueueNotifyWhisper(stinky)
	end
	if not aura_env.localStinkies[name] or aura_env.localStinkies[name] <
		GetTime() - aura_env.config.messageThrottleAddon then
		Message.QueueNotifyAddonGuild(stinky)
		Message.QueueNotifyAddonWhisper(stinky)
	end
	WeakAuras.ScanEvents("CHAT_MSG_ADDON", aura_env.addonprefix, stinky:FormAddonMessage())
	aura_env.localStinkies[name] = GetTime()
end

if aura_env.config.addFriends and not aura_env.config.addFriends2 then
	local friends = {}
	local numfriends = GetNumFriends()
	for i = 1, numfriends do
		local name = GetFriendInfo(i)
		friends[name] = true
	end
	for k, v in pairs(WeakAurasSaved.Cyka.stinkies) do
		if not friends[k] then
			AddFriend(k)
		end
	end
	C_Timer.After(1, function()
		local numfriends = GetNumFriends()
		for i = 1, numfriends do
			local name = GetFriendInfo(i)
			if WeakAurasSaved.Cyka.stinkies[name] then
				C_Timer.After(1, function()
					-- print(name .. " " .. i .. " Stinky!")
					SetFriendNotes(i, "STINKY")
				end)
			else
				C_Timer.After(1, function()
					-- print(name .. " " .. i .. " Not stinky")
					SetFriendNotes(i, "Not stinky?")
				end)
			end
		end
	end)
end

--/run WeakAurasSaved.Cyka.Stinkies["Totleta"] = true
-- /dump WeakAurasSaved.Cyka.Stinkies
