local ADDON_NAME, Obituary = ...
local module = Obituary:NewModule("Config", "AceEvent-3.0")

local L = LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME)

local Stack = Obituary.Stack
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0")

local format, match, trim = string.format, string.match, string.trim

local defaultChannels = {
	["SAY"] = CHAT_MSG_SAY,
	["PARTY"] = CHAT_MSG_PARTY,
	["RAID"] = CHAT_MSG_RAID,
	["GUILD"] = CHAT_MSG_GUILD,
	["OFFICER"] = CHAT_MSG_OFFICER,
}
Obituary.defaultChannels = defaultChannels

Obituary.defaultDB = {
	profile = {
		eventTTL = 30,
		announceDeath = false,

		enableForPlayer = true,
		enableForPlayersInGroup = true,
		enableForPlayersNotInGroup = false,
		enableForPets = false,
		enableForNPCs = false,
		enableForBattleground = false,
		enableForArena = true,
		enableForPartyInstance = true,
		enableForRaidInstance = true,

		summary = true,
		summaryOutput = "ChatFrame",
		summaryChatFrame = 1,
		summaryReportEvents = 3,

		throttle = true,

		filterHeal = -1,
		filterDamage = -1,
		showBuff = false,
		showDebuff = true,

		detailed = true,
		detailedOutput = "RAID",
		detailedChatFrame = 1,
		detailedReportEvents = 10,
		detailedReportEventsChat = 5,
		detailedReportsPerPlayer = 4,

		tooltipX = nil,
		tooltipY = nil,
	},
}

local GetOptions
do
	local function outputChannels()
		local channels = { ["ChatFrame"] = L["Chat Frame"] }

		for key, value in pairs(defaultChannels) do
			channels[key] = value
		end

		for i = 1, GetNumDisplayChannels() do
			local name, _, _, index, _, _, category = GetChannelDisplayInfo(i)
			if category == "CHANNEL_CATEGORY_CUSTOM" then
				channels[tostring(index)] = format("%d. %s", index, name)
			end
		end

		return channels
	end

	local function outputFrames()
		local frames = {}
		for i = 1, NUM_CHAT_WINDOWS do
			local frame = _G["ChatFrame"..i]
			if frame and frame ~= COMBATLOG then
				frames[i] = frame.name
			end
		end

		return frames
	end

	function GetOptions()
		local db = Obituary.db.profile
		local options = {
			type = "group",
			name = "Obituary",
			get = function(info) return db[info[#info]] end,
			set = function(info, value) db[info[#info]] = value end,
			handler = Obituary,
			args = {
				Enable = {
					order = 1,
					type = "group",
					name = L["General"],
					--desc = "",
					args = {
						intro = {
							order = 1,
							type = "description",
							name = L["Quickly and easily see how something was killed."].."\n",
						},
						EnableForZones = {
							order = 20,
							type = "group",
							inline = true,
							name = L["Enable for Zones"],
							desc = L["Select the type of zones that have death tracking enabled."],
							set = function(info, value)
								db[info[#info]] = value
								Obituary:CheckEnable()
							end,
							args = {
								intro = {
									order = 1,
									type = "description",
									name = L["Select the type of zones that have death tracking enabled."],
								},
								enableForWorld = {
									order = 2,
									type = "toggle",
									name = L["World"],
									desc = L["Enable tracking while in the open world."],
								},
								enableForBattleground = {
									order = 3,
									type = "toggle",
									name = L["Battlegrounds"],
									desc = L["Enable tracking while in a battleground."],
								},
								enableForArena = {
									order = 4,
									type = "toggle",
									name = L["Arena"],
									desc = L["Enable tracking while in an arena."],
								},
								enableForPartyInstance = {
									order = 5,
									type = "toggle",
									name = L["Party Instance"],
									desc = L["Enable tracking while in a party instance."],
								},
								enableForRaidInstance = {
									order = 6,
									type = "toggle",
									name = L["Raid Instance"],
									desc = L["Enable tracking while in a raid instance."],
								},
							},
						}, --EnableForZones
						EnableForUnits = {
							order = 30,
							type = "group",
							inline = true,
							name = L["Enable for Units"],
							desc = L["Select which units should have their deaths tracked."],
							set = function(info, value)
								db[info[#info]] = value
								Obituary:CheckEnable()
							end,
							args = {
								intro = {
									order = 1,
									type = "description",
									name = L["Select which units should have their deaths tracked."],
								},
								enableForPlayersInGroup = {
									order = 2,
									type = "toggle",
									name = L["Players in group"],
									desc = L["Enable tracking deaths for players that you are grouped with.\n\nYou need this option enabled if you wish to track deaths for yourself!"],
									set = function(info, value)
										db[info[#info]] = value
										if not db.enableForPlayersInGroup and not db.enableForPlayersNotInGroup then
											db.enableForPets = false
										end
										Obituary:CheckEnable()
									end,
								},
								enableForPlayersNotInGroup = {
									order = 3,
									type = "toggle",
									name = L["Players not in group"],
									desc = L["Enable tracking deaths for players that you are not currently grouped with."],
									set = function(info, value)
										db[info[#info]] = value
										if not db.enableForPlayersInGroup and not db.enableForPlayersNotInGroup then
											db.enableForPets = false
										end
										Obituary:CheckEnable()
									end,
								},
								enableForPets = {
									order = 4,
									type = "toggle",
									name = L["Pets"],
									desc = L["Enable tracking pet deaths.\n\nPets deaths are only reported if their owner is also being tracked."],
									disabled = function() return not db.enableForPlayersInGroup and not db.enableForPlayersNotInGroup end,
								},
								enableForNPCs = {
									order = 5,
									type = "toggle",
									name = L["NPCs"],
									desc = L["Enable tracking NPC deaths."],
								},
							},
						}, --EnableForUnits
						FilterEvents = {
							order = 40,
							type = "group",
							inline = true,
							name = L["Filtering"],
							--desc = L["Filtering"],
							args = {
								intro = {
									order = 1,
									type = "description",
									name = L["Set thresholds for ignoring combat log events. Use -1 to record everything."],
								},
								filterDamage = {
									order = 2,
									type = "range",
									min = -1, softMax = 20000, step = 1,
									name = L["Damage"],
									--desc = L["Damage"],
								},
								filterHeal = {
									order = 3,
									type = "range",
									min = -1, softMax = 20000, step = 1,
									name = L["Healing"],
									--desc = L["Healing"],
								},
								spacer = {
									order = 4,
									type = "description",
									name = "",
									width = "full",
								},
								showBuff = {
									order = 5,
									type = "toggle",
									name = L["Show Buffs"],
									desc = L["Show short duration buff gains and loses for the player."],
								},
								showDebuff = {
									order = 6,
									type = "toggle",
									name = L["Show Debuffs"],
									desc = L["Show all debuff gains and loses for the player."],
								},
							},
						}, --FilterEvents
					},
				},
				Reporting = {
					order = 4,
					type = "group",
					name = L["Reporting"],
					--desc = "",
					args = {
						intro = {
							order = 1,
							type = "description",
							name = L["Reporting options"].."\n",
						},
						eventTTL = {
							order = 2,
							type = "range",
							name = L["History Duration"],
							desc = L["Events older than this many seconds won't be reported as a cause of death."],
							min = 10, max = 60, step = 5,
							set = function(info, value)
								db[info[#info]] = value
								self:PurgeDeathEventHistories()
							end,
							width = "full",
						},
						--[[
						purgeFunc = {
							order = 3,
							type = "execute",
							name = L["Purge History"],
							desc = L["Clear events not saved to a report."],
							func = "PurgeDeathEventHistories",
						},
						sep = {
							order = 4,
							type = "description",
							name = "",
							width = "full",
						},
						--]]
						announceDeath = {
							order = 11,
							type = "toggle",
							name = L["Death Announce Sound"],
							desc = L["Audio announcer for casualties."],
							set = function(info, value)
								db[info[#info]] = value
								if value then
									Obituary:EnableModule("Announcer")
									local n = math.random(1, 3)
									if n == 3 then
										PlaySoundFile([[Interface\AddOns\ObituaryN\Sounds\massivecasualties.ogg]], "Master")
									elseif n == 2 then
										PlaySoundFile([[Interface\AddOns\ObituaryN\Sounds\casualties.ogg]], "Master")
									else
										PlaySoundFile([[Interface\AddOns\ObituaryN\Sounds\casualty.ogg]], "Master")
									end
								else
									Obituary:DisableModule("Announcer")
								end
							end,
						},
						Summary = {
							order = 20,
							type = "group",
							name = L["Summary Report"],
							--desc = "",
							disabled = function() return not db.summary end,
							guiInline = true,
							args = {
								intro = {
									order = 0,
									type = "description",
									name = L["Display a brief summary of the last few damaging events that led to a unit's death."],
								},
								summary = {
									order = 1,
									type = "toggle",
									name = L["Enable"],
									--desc = "",
									disabled = false,
								},
								throttle = {
									order = 2,
									type = "toggle",
									name = L["Throttle"],
									desc = L["Reduce chat spam when wiping by temporarily stopping output after several deaths occur within a short time."],
									disabled = function() return not db.summary end,
								},
								summaryReportEvents = {
									order = 3,
									type = "range",
									name = L["Events to Output"],
									desc = L["Number of events to output to chat."] .."\n\n" ..L["Changing this value will clear all stored events."],
									min = 1, max = 6, step = 1,
									set = function(info, value)
										db[info[#info]] = value
										Obituary:PurgeDeathEventHistories()
									end,
								},
								summaryOutput = {
									order = 4,
									type = "select",
									name = L["Output"],
									desc = L["Select which channel this report will be output to."],
									values = outputChannels,
								},
								summaryChatFrame = {
									order = 5,
									type = "select",
									name = L["Chat Frame"],
									desc = L["Select which chat frame this report will be printed to."],
									disabled = function() return not db.summary or db.summaryOutput ~= "ChatFrame" end,
									values = outputFrames,
								},
							},
						},
						Detailed = {
							order = 30,
							type = "group",
							name = L["Detailed Report"],
							--desc = "",
							disabled = function() return not db.detailed end,
							guiInline = true,
							args = {
								intro = {
									order = 0,
									type = "description",
									name = L["Display a chat link which will open to show a detailed breakdown of the events that led to a unit's death in a tooltip.\n\nThe chat link will be shown in all chat frames set to show \"System Messages\".\n\nShift-clicking the link will output that detailed breakdown to the channel that you have selected here."],
								},
								detailed = {
									order = 0.5,
									type = "toggle",
									name = L["Enable"],
									--desc = "",
									disabled = false,
								},
								detailedReportsPerPlayer = {
									order = 1,
									type = "range",
									name = L["Reports per Player"],
									desc = L["Number of detailed death reports to keep for each player."],
									min = 1, max = 10, step = 1,
									set = function(info, value)
										db[info[#info]] = value
										Obituary:PurgeDeathEventHistories()
									end,
								},
								detailedReportEvents = {
									order = 2,
									type = "range",
									name = L["Events to Display"],
									desc = L["Number of events to keep recorded for display."] .."\n\n" ..L["Changing this value will clear all stored events."],
									min = 1, max = 100, softMax = 50, step = 1,
									set = function(info, value)
										db[info[#info]] = value
										Obituary:PurgeDeathEventHistories()
									end,
								},
								detailedReportEventsChat = {
									order = 2,
									type = "range",
									name = L["Events to Output"],
									desc = L["Number of events to output to chat."],
									min = 1, max = 10, step = 1,
								},
								detailedOutput = {
									order = 3,
									type = "select",
									name = L["Output"],
									desc = L["Select which channel this report will be output to."],
									values = outputChannels,
								},
								detailedChatFrame = {
									order = 4,
									type = "select",
									name = L["Chat Frame"],
									desc = L["Select which chat frame this report will be printed to."],
									disabled = function() return db.detailedOutput ~= "ChatFrame" end,
									values = outputFrames,
								},
							},
						}, --Detailed
					},
				}, --Reporting
			},
		}
		return options
	end
end

function module:RefreshOptions()
	LibStub("AceConfigRegistry-3.0"):NotifyChange("Obituary")
end

local optionsFrames = {}
function module:OpenOptions()
	InterfaceOptionsFrame_OpenToCategory(optionsFrames.Reporting) -- Expand the group
	InterfaceOptionsFrame_OpenToCategory(optionsFrames.Obituary)
end

function module:OnInitialize()
	AceConfigRegistry:RegisterOptionsTable("Obituary", GetOptions)
	optionsFrames.Obituary = AceConfigDialog:AddToBlizOptions("Obituary", "Obituary", nil, "Enable")
	optionsFrames.Reporting = AceConfigDialog:AddToBlizOptions("Obituary", L["Reporting"], "Obituary", "Reporting")

	AceConfigRegistry:RegisterOptionsTable("Obituary Profile", LibStub("AceDBOptions-3.0"):GetOptionsTable(Obituary.db))
	AceConfigDialog:AddToBlizOptions("Obituary Profile", "Profiles", "Obituary")
end

function module:OnEnable()
	self:RegisterEvent("CHANNEL_UI_UPDATE", "RefreshOptions")
end

local function Print(...)
	print("|cff33ff99Obituary|r:", ...)
end

_G["SLASH_OBITUARY1"] = "/obituary"
_G["SLASH_OBITUARY2"] = "/obit"
SlashCmdList["OBITUARY"] = function(input)
	local cmd, rest = match(input, "^(%S*)%s*(.-)$")

	if cmd == "purge" then
		Obituary:PurgeDeathEventHistories()
		Obituary:PurgeDeathReports()
		Print("Purged all stored information.")

	elseif cmd == "list" then
		if not Obituary.db.profile.detailed then
			Print("Detailed death reports are disabled. Nothing to list.")
			return
		end

		if not rest then
			Print("usage: /obit list <name>")
			return
		end

		local name = Ambiguate(string.gsub(string.lower(rest), "^%l", string.upper), "none")
		local guid = Obituary.nameToGUID[name]
		local deaths = Obituary:GetDeathReports(guid) or {}

		-- Order reports by time
		local temp = {}
		for timestamp in pairs(deaths) do
			temp[#temp+1] = tonumber(timestamp)
		end
		sort(temp)

		if #temp == 0 then
			Print(format("There are no recorded deaths for %q", name))
			return
		end

		local links = ""
		for i, timestamp in ipairs(temp) do
			links = links .. format("|cffffff00|Hobituary:%s:%s:%s:%s:%s|h[%s]|h|r ", timestamp, guid, name, 0x512, 0, date("%X", timestamp))
		end
		Print(format("Deaths for %s: %s", name, links))

	else
		module:OpenOptions()

	end
end

