local PA = _G.ProjectAzilroka
local AR = PA:NewModule('AuraReminder', 'AceEvent-3.0', 'AceTimer-3.0')

PA.AR = AR

AR.Title = 'Aura Reminder'
AR.Header = '|cFF16C3F2Aura|r |cFFFFFFFFReminder|r'
AR.Description = 'Reminder for Buffs / Debuffs'
AR.Authors = 'Azilroka    NihilisticPandemonium'
AR.isEnabled = false

local _G = _G
local pairs = pairs
local ipairs = ipairs
local tonumber = tonumber
local tostring = tostring
local select = select
local format = format
local strmatch = strmatch
local unpack = unpack
local tinsert = tinsert
local wipe = wipe

local GetSpellCooldown = GetSpellCooldown
local GetSpellInfo = GetSpellInfo
local IsUsableSpell = IsUsableSpell
local IsInInstance = IsInInstance
local UnitAffectingCombat = UnitAffectingCombat
local UnitIsDeadOrGhost = UnitIsDeadOrGhost
local UnitLevel = UnitLevel
local GetInventoryItemID = GetInventoryItemID
local GetWeaponEnchantInfo = GetWeaponEnchantInfo
local GetInventoryItemTexture = GetInventoryItemTexture
local PlaySoundFile = PlaySoundFile
local GetSpecialization = GetSpecialization
local GetSpecializationRole = GetSpecializationRole
local GetSpecializationInfo = GetSpecializationInfo
local GetItemInfoInstant = GetItemInfoInstant

local MAX_PLAYER_LEVEL = MAX_PLAYER_LEVEL

local CreateFrame = CreateFrame
local UIParent = UIParent

_G.AuraReminder = AR

AR.CreatedReminders = {}

local selectedFilter, selectedGroup, filters, spellList, filterTypeList, DefaultFilters = nil, PA.MyClass, {}, {}, {}

do
	local function SpellIDPredicate(spellIDToFind, casterToFind, _, _, _, _, _, _, _, caster, _, _, spellID)
		return (casterToFind and caster == casterToFind and spellIDToFind == spellID) or (spellIDToFind == spellID)
	end

	function AR:FindAuraBySpellID(spellID, unit, filter, caster)
		return _G.AuraUtil.FindAura(SpellIDPredicate, unit, filter, spellID, caster);
	end
end

function AR:FindPlayerAura(db, checkPersonal, filter)
	for spellID, value in pairs(db) do
		if value == true then
			return AR:FindAuraBySpellID(spellID, 'player', filter, checkPersonal and 'player')
		end
	end
end

function AR:IsSpellOnCooldown(id)
	local start, duration = GetSpellCooldown(id)
	if start > 0 and duration > 1.5 then
		return true
	end
end

function AR:IsSpellUsable(id)
	local isUsable = IsUsableSpell(id)
	if isUsable then
		return true
	end
end

function AR:UpdateColors(frame, id)
	local isUsable, notEnoughMana = IsUsableSpell(id)
	if isUsable then
		frame.icon:SetVertexColor(1, 1, 1)
	elseif notEnoughMana then
		frame.icon:SetVertexColor(.5, .5, 1)
	else
		frame.icon:SetVertexColor(.4, .4, .4)
	end
end

function AR:HasOffHandWeapon(itemID)
	if not itemID then return end
	local itemEquipLoc = select(4, GetItemInfoInstant(itemID))
	return (itemEquipLoc == "INVTYPE_WEAPON" or itemEquipLoc == "INVTYPE_2HWEAPON" or itemEquipLoc == "INVTYPE_WEAPONOFFHAND")
end

function AR:FilterCheck(db, isReverse)
	local _, instanceType = IsInInstance()
	local roleCheck, treeCheck, combatCheck, instanceCheck, PVPCheck = true, true, true, true, true

	if PA.Retail then
		local spec = GetSpecialization()

		if db.role and (db.role ~= 'ANY' and db.role ~= GetSpecializationRole(spec)) then
			roleCheck = false
		end

		if not isReverse and db.tree and (db.tree ~= 'ANY' and db.tree ~= spec) then
			treeCheck = false
		end

		if isReverse and db.talentTreeException and db.talentTreeException == spec then
			treeCheck = false
		end
	end

	if db.combat and not UnitAffectingCombat('player') then
		combatCheck = false
	end

	if db.instance and (instanceType ~= 'party' and instanceType ~= 'raid') then
		instanceCheck = false
	end

	if db.pvp and (instanceType ~= 'arena' and instanceType ~= 'pvp') then
		PVPCheck = false
	end

	if (isReverse or roleCheck and treeCheck) and combatCheck and instanceCheck and PVPCheck then
		return true
	else
		return false
	end
end

function AR:Reminder_Update()
	if UnitIsDeadOrGhost('player') then return end

	for _, button in ipairs(AR.CreatedReminders) do
		button:Hide()
		button:SetAlpha(1)
	end

	local Position = 1
	for _, filter in pairs({PA.MyClass, 'Global'}) do
		for _, db in pairs(AR.db.Filters[filter]) do
			if db.enable and (not db.level or db.level and UnitLevel('player') > db.level) then
				local Button = AR.CreatedReminders[Position]
				if (not Button) or (Button:IsVisible()) then
					Button = AR:CreateReminder(Position)
					Position = Position + 1
				end

				AR:SetIconPosition(Button, db)

				local filterCheck, reverseCheck = AR:FilterCheck(db), AR:FilterCheck(db, true)

				if db.filterType == 'COOLDOWN' and db.cooldownSpellID and filterCheck then
					local start, duration = GetSpellCooldown(db.cooldownSpellID)
					if (duration and duration > 1.5) then
						Button.cooldown:SetCooldown(start, duration)
					end

					Button.cooldown:SetShown((duration and duration > 0))
					Button.icon:SetTexture(select(3, GetSpellInfo(db.cooldownSpellID)))
					Button:SetShown((duration and duration == 0) or db.onCooldown)

					AR:UpdateColors(Button, db.cooldownSpellID)

					if (duration and duration > 1.5) and filterCheck and db.onCooldown then
						Button:SetAlpha(db.cooldownAlpha or .5)
					end
				elseif (db.filterType == 'WEAPON' or (db.filterType == 'SPELL' and db.spellGroup and PA:CountTable(db.spellGroup) > 0)) and filterCheck then
					if db.filterType == 'SPELL' then
						local hasBuff, hasDebuff = AR:FindPlayerAura(db.spellGroup, db.personal), AR:FindPlayerAura(db.spellGroup, nil, 'HARMFUL')
						local negate = AR:FindPlayerAura(db.negateGroup, db.personal)

						if not (negate or hasBuff or hasDebuff) then
							for buff, value in pairs(db.spellGroup) do
								if value then
									local usable = IsUsableSpell(buff);
									if usable and AR:IsSpellOnCooldown(buff) then
										break
									end

									if usable or not db.strictFilter then
										Button.icon:SetTexture(select(3, GetSpellInfo(buff)))
										AR:UpdateColors(Button, buff)
										break
									end
								end
							end

							Button:SetShown((((not hasBuff) and (not hasDebuff)) and not db.reverseCheck) or (reverseCheck and db.reverseCheck and ((hasBuff or hasDebuff) or ((not hasBuff) and (not hasDebuff)))))
						end
					end

					if db.filterType == 'WEAPON' then
						local hasOffhandWeapon = AR:HasOffHandWeapon(GetInventoryItemID('player', 17))
						local hasMainHandEnchant, _, _, hasOffHandEnchant = GetWeaponEnchantInfo()

						if (not hasMainHandEnchant) then
							Button.icon:SetTexture(GetInventoryItemTexture('player', 16))
						elseif (hasOffhandWeapon and not hasOffHandEnchant) then
							Button.icon:SetTexture(GetInventoryItemTexture('player', 17))
						end

						Button:SetShown(not (hasMainHandEnchant or hasOffHandEnchant))
						Button.icon:SetVertexColor(1, 1, 1)
					end

					if Button:IsShown() and not db.disableSound then
						AR:PlaySoundFile()
					end
				end
			end
		end
	end
end

function AR:ResetSoundPlayback()
	AR.IsPlaying = false
end

function AR:PlaySoundFile()
	if AR.IsPlaying then return end

	AR.IsPlaying = true

	PlaySoundFile(PA.LSM:Fetch('sound', AR.db.Sound))

	AR:ScheduleTimer('ResetSoundPlayback', 10)
end

function AR:SetIconPosition(button, db)
	if not (button or db) then return end

	local xOffset = db.xOffset or 0
	local yOffset = db.yOffset or 0
	local size = db.size or 40

	button:ClearAllPoints()
	button:SetPoint('CENTER', UIParent, 'CENTER', 0 + xOffset, 200 + yOffset);
	button:SetSize(size, size)
end

function AR:CreateReminder(index)
	local frame = CreateFrame('Frame', 'AuraReminder'..index, UIParent)
	frame:Hide()
	frame.icon = frame:CreateTexture(nil, 'OVERLAY')
	frame.icon:SetTexCoord(unpack(PA.TexCoords))
	frame.cooldown = CreateFrame('Cooldown', nil, frame, 'CooldownFrameTemplate')
	frame.cooldown:SetAllPoints(frame.icon)

	PA:SetTemplate(frame)
	PA:SetInside(frame.icon)

	tinsert(AR.CreatedReminders, frame)
	return frame
end

function AR:UpdateFilterGroup(group)
	for option, optionTable in pairs(PA.Options.args.AuraReminder.args.filterGroup.args[group].args) do
		if strmatch(option, "^AR") then
			optionTable.hidden = true
		end
	end

	if AR.db.Filters[selectedGroup][selectedFilter] and AR.db.Filters[selectedGroup][selectedFilter][group] then
		local i = 1
		for spell in pairs(AR.db.Filters[selectedGroup][selectedFilter][group]) do
			if spell and GetSpellInfo(spell) then
				local name = format('AR%s', i + 2)
				local optionName = PA.Options.args.AuraReminder.args.filterGroup.args[group].args[name]
				if not optionName then
					PA.Options.args.AuraReminder.args.filterGroup.args[group].args[name] = { type = 'toggle', width = 'double' }
					optionName = PA.Options.args.AuraReminder.args.filterGroup.args[group].args[name]
				end

				optionName.name = function() return format('%s (%s)', GetSpellInfo(spell), spell) end
				optionName.get = function(info) return spell and AR.db.Filters[selectedGroup][selectedFilter][group][spell] end
				optionName.set = function(info, value) AR.db.Filters[selectedGroup][selectedFilter][group][spell] = value end
				optionName.hidden = false

				i = i + 1
			end
		end
	end
end

function AR:CleanDB()
	-- Cleanup DB
	for _, filter in pairs({PA.MyClass, 'Global'}) do
		if AR.db.Filters and AR.db.Filters[filter] then
			for _, db in pairs(AR.db.Filters[filter]) do
				if db.role == 'ANY' then db.role = nil end
				if db.tree == 'ANY' then db.tree = nil end
				if db.talentTreeException == 'NONE' then db.talentTreeException = nil end
				if (db.level and db.level == 0) then db.level = nil end
				if not db.combat then db.combat = nil end
				if not db.instance then db.instance = nil end
				if not db.pvp then db.pvp = nil end
				if not db.onCooldown then db.onCooldown = nil end
				if not db.disableSound then db.disableSound = nil end
			end
		end
	end
end

local addGroupTemplate = { name = '', template = ''}

function AR:GetOptions()
	PA.Options.args.AuraReminder = {
		type = 'group',
		name = 'Aura Reminder',
		get = function(info) return AR.db[info[#info]] end,
		set = function(info, value) AR.db[info[#info]] = value end,
		args = {
			Header = {
				order = 0,
				type = 'header',
				name = AR.Header,
			},
			Enable = {
				order = 1,
				type = 'toggle',
				name = PA.ACL['Enable'],
				set = function(info, value)
					AR.db[info[#info]] = value
					if (not AR.isEnabled) then
						AR:Initialize()
					else
						_G.StaticPopup_Show('PROJECTAZILROKA_RL')
					end
				end,
			},
			Sound = {
				order = 2,
				type = 'select', dialogControl = 'LSM30_Sound',
				name = PA.ACL['Sound'],
				desc = PA.ACL['Sound that will play when you have a warning icon displayed.'],
				values = PA.LSM:HashTable('sound'),
			},
			selectGroup = {
				order = 3,
				type = 'select',
				name = PA.ACL['Select Group'],
				get = function(info)
					if selectedGroup == 'Global' then
						return selectedGroup
					else
						return 'Class'
					end
				end,
				set = function(info, value)
					if value == 'Class' then
						selectedGroup = PA.MyClass
					else
						selectedGroup = value
					end
				end,
				values = { Class = 'Class', Global = 'Global'},
			},
			selectFilter = {
				order = 4,
				type = 'select',
				name = PA.ACL['Select Filter'],
				get = function(info) return selectedFilter ~= '' and selectedFilter or '' end,
				set = function(info, value)
					selectedFilter = value ~= '' and value or nil
					AR:UpdateFilterGroup('spellGroup')
					AR:UpdateFilterGroup('negateGroup')
				end,
				values = function()
					wipe(filters)
					for filter in pairs(AR.db.Filters[selectedGroup]) do
						filters[filter] = filter
					end
					if not next(filters) then
						filters[''] = PA.ACL['None']
					end
					return filters
				end,
			},
			filterControl = {
				order = 5,
				type = 'group',
				name = PA.ACL['Filter Control'],
				guiInline = true,
				args = {
					addFilter = {
						order = 1,
						type = 'input',
						name = PA.ACL['New Filter Name'],
						get = function(info) return addGroupTemplate.name end,
						set = function(info, value)
							if AR.db.Filters[selectedGroup][value] then
								return
							end
							addGroupTemplate.name = value
						end,
					},
					addFilterTemplate = {
						order = 2,
						type = 'select',
						name = PA.ACL['New Filter Type'],
						get = function(info) return addGroupTemplate.template end,
						set = function(info, value)
							if AR.db.Filters[selectedGroup][value] then
								return
							end
							addGroupTemplate.template = value
						end,
						values = function()
							wipe(filterTypeList)
							filterTypeList.SPELL = PA.ACL['Spell']
							if selectedGroup ~= 'Global' then
								filterTypeList.WEAPON = PA.ACL['Weapon']
								filterTypeList.COOLDOWN = PA.ACL['Cooldown']
							end
							return filterTypeList
						end,
					},
					addFilterButton = {
						type = 'execute',
						order = 3,
						name = PA.ACL['Add Filter'],
						hidden = function(info)
							return addGroupTemplate.name == '' or addGroupTemplate.template == ''
						end,
						func = function(info)
							AR.db.Filters[selectedGroup][addGroupTemplate.name] = { enable = true, size = 50, filterType = addGroupTemplate.template }
							if addGroupTemplate.template == 'COOLDOWN' then
								AR.db.Filters[selectedGroup][addGroupTemplate.name].cooldownAlpha = .5
							elseif addGroupTemplate.template == 'WEAPON' then
							else
								AR.db.Filters[selectedGroup][addGroupTemplate.name].spellGroup = {}
								AR.db.Filters[selectedGroup][addGroupTemplate.name].negateGroup = {}
							end

							selectedFilter = addGroupTemplate.name

							addGroupTemplate.name = ''
							addGroupTemplate.template = ''
						end,
					},
					deleteGroup = {
						order = 5,
						type = 'select',
						name = PA.ACL['Remove Filter'],
						get = function(info) return '' end,
						set = function(info, value)
							selectedFilter = nil
							if DefaultFilters[selectedGroup][value] then
								AR.db.Filters[selectedGroup][value].enable = false;
							else
								AR.db.Filters[selectedGroup][value] = nil;
							end
						end,
						values = function()
							wipe(filters)
							for filter in pairs(AR.db.Filters[selectedGroup]) do
								filters[filter] = filter
							end
							if not next(filters) then
								filters[''] = PA.ACL['None']
							end
							return filters
						end,
					},
				},
			},
			filterGroup = {
				order = 8,
				type = 'group',
				name = function() return selectedFilter end,
				guiInline = true,
				get = function(info) return AR.db.Filters[selectedGroup][selectedFilter][info[#info]] end,
				set = function(info, value) AR.db.Filters[selectedGroup][selectedFilter][info[#info]] = value end,
				hidden = function() return not selectedFilter end,
				args = {
					enable = {
						order = 1,
						type = 'toggle',
						name = PA.ACL['Enable'],
					},
					filterType = {
						order = 2,
						type = 'select',
						name = PA.ACL['Filter Type'],
						desc = PA.ACL['Change this if you want the Reminder module to check for weapon enchants, setting this will cause it to ignore any spells listed.'],
						values = function()
							wipe(filterTypeList)
							filterTypeList.SPELL = PA.ACL['Spell']
							if selectedGroup == 'Class' then
								filterTypeList.WEAPON = PA.ACL['Weapon']
								filterTypeList.COOLDOWN = PA.ACL['Cooldown']
							end
							return filterTypeList
						end,
					},
					xOffset = {
						order = 3,
						type = 'range',
						name = PA.ACL['X Offset'],
						min = -250, max = 250, step = 1,
					},
					yOffset = {
						order = 4,
						type = 'range',
						name = PA.ACL['Y Offset'],
						min = -250, max = 250, step = 1,
					},
					size = {
						order = 5,
						type = 'range',
						name = PA.ACL['Size'],
						min = 0, max = 64, step = 1,
					},
					conditions = {
						order = 10,
						type = 'group',
						name = PA.ACL['Conditions'],
						guiInline = true,
						args = {
							instance = {
								order = 1,
								type = 'toggle',
								name = PA.ACL['Inside Raid/Party'],
								desc = PA.ACL['Only run checks inside raid/party instances.'],
							},
							pvp = {
								order = 2,
								type = 'toggle',
								name = PA.ACL['Inside BG/Arena'],
								desc = PA.ACL['Only run checks inside BG/Arena instances.'],
							},
							combat = {
								order = 3,
								type = 'toggle',
								name = PA.ACL['Combat'],
								desc = PA.ACL['Only run checks during combat.'],
							},
						},
					},
					filterConditions = {
						order = 11,
						type = 'group',
						name = PA.ACL['Filter Conditions'],
						guiInline = true,
						args = {
							level = {
								order = 4,
								type = 'range',
								name = PA.ACL['Level Requirement'],
								desc = PA.ACL['Level requirement for the icon to be able to display. 0 for disabled.'],
								min = 0, max = MAX_PLAYER_LEVEL, step = 1,
							},
							personal = {
								order = 5,
								type = 'toggle',
								name = PA.ACL['Personal Buffs'],
								desc = PA.ACL['Only check if the buff is coming from you.'],
								hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType ~= 'SPELL' end,
							},
							reverseCheck = {
								order = 6,
								type = 'toggle',
								name = PA.ACL['Reverse Check'],
								desc = PA.ACL['Instead of hiding the frame when you have the buff, show the frame when you have the buff.'],
								hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType ~= 'SPELL' end,
							},
							strictFilter = {
								order = 7,
								type = 'toggle',
								name = PA.ACL['Strict Filter'],
								desc = PA.ACL['This ensures you can only see spells that you actually know. You may want to uncheck this option if you are trying to monitor a spell that is not directly clickable out of your spellbook.'],
								hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType == 'COOLDOWN' end,
							},
							disableSound = {
								order = 8,
								type = 'toggle',
								name = PA.ACL['Disable Sound'],
								hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType == 'COOLDOWN' end,
							},
						},
					},
					cooldownConditions = {
						order = 12,
						type = 'group',
						name = PA.ACL['Cooldown Conditions'],
						guiInline = true,
						hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType ~= 'COOLDOWN' or selectedGroup == 'Global' end,
						args = {
							dscription = {
								order = 0,
								type = 'description',
								fontSize = 'medium',
								name = function()
									local spellID = AR.db.Filters[selectedGroup][selectedFilter].cooldownSpellID
									if not spellID or spellID == '' then return end
									return format('%s (%s)', GetSpellInfo(spellID), spellID)
								end,
								hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].cooldownSpellID == '' end,
							},
							cooldownSpellID = {
								order = 1,
								type = 'input',
								name = PA.ACL['Spell ID'],
								get = function(info) return tostring(AR.db.Filters[selectedGroup][selectedFilter][info[#info]] or '') end,
								set = function(info, value)
									value = tonumber(value)
									if not value then return end

									AR.db.Filters[selectedGroup][selectedFilter][info[#info]] = value
								end,
							},
							onCooldown = {
								order = 2,
								type = 'toggle',
								name = PA.ACL['Show On Cooldown'],
							},
							cooldownAlpha = {
								order = 3,
								type = 'range',
								name = PA.ACL['Cooldown Alpha'],
								min = 0, max = 1, step = 0.1,
								hidden = function() return not AR.db.Filters[selectedGroup][selectedFilter].onCooldown end,
							},
						},
					},
					spellGroup = {
						order = 13,
						type = 'group',
						name = PA.ACL['Spells'],
						guiInline = true,
						get = function(info) return '' end,
						hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType ~= 'SPELL' end,
						args = {
							AddSpell = {
								order = 0,
								type = 'input',
								name = PA.ACL['New ID'],
								set = function(info, value)
									value = tonumber(value)
									if not value then return end

									AR.db.Filters[selectedGroup][selectedFilter].spellGroup[value] = true
									AR:UpdateFilterGroup('spellGroup')
								end,
							},
							RemoveSpell = {
								order = 1,
								type = 'select',
								name = PA.ACL['Remove ID'],
								get = function() return '' end,
								set = function(info, value)
									AR.db.Filters[selectedGroup][selectedFilter].spellGroup[value] = nil;
									AR:UpdateFilterGroup('spellGroup')
								end,
								values = function()
									wipe(spellList)
									for spellID in pairs(AR.db.Filters[selectedGroup][selectedFilter].spellGroup) do
										local name = GetSpellInfo(spellID)
										spellList[spellID] = name and format('%s (%s)', name, spellID) or spellID
									end
									return spellList
								end,
							},
							spacer = {
								order = 2,
								type = 'description',
								name = ' ',
							}
						},
					},
					negateGroup = {
						order = 14,
						type = 'group',
						name = PA.ACL['Negate Spells'],
						guiInline = true,
						get = function(info) return '' end,
						hidden = function() return AR.db.Filters[selectedGroup][selectedFilter].filterType ~= 'SPELL' end,
						args = {
							AddSpell = {
								order = 0,
								type = 'input',
								name = PA.ACL['New ID'],
								set = function(info, value)
									value = tonumber(value)
									if not value then return end

									AR.db.Filters[selectedGroup][selectedFilter].negateGroup[value] = true
									AR:UpdateFilterGroup('negateGroup')
								end,
							},
							RemoveSpell = {
								order = 1,
								type = 'select',
								name = PA.ACL['Remove ID'],
								get = function() return '' end,
								set = function(info, value)
									AR.db.Filters[selectedGroup][selectedFilter].negateGroup[value] = nil;
									AR:UpdateFilterGroup('spellGroup')
								end,
								values = function()
									wipe(spellList)
									for spellID in pairs(AR.db.Filters[selectedGroup][selectedFilter].negateGroup) do
										local name = GetSpellInfo(spellID)
										spellList[spellID] = name and format('%s (%s)', name, spellID) or spellID
									end
									return spellList
								end,
							},
							spacer = {
								order = 2,
								type = 'description',
								name = ' ',
							}
						},
					},
				},
			},
			AuthorHeader = {
				order = -4,
				type = 'header',
				name = PA.ACL['Authors:'],
			},
			Authors = {
				order = -3,
				type = 'description',
				name = AR.Authors,
				fontSize = 'large',
			},
		},
	}

	if PA.Retail then
		local optionGroup = PA.Options.args.AuraReminder.args.filterGroup.args.filterConditions.args

		local Specializations = {
			['1'] = select(2, GetSpecializationInfo(1)),
			['2'] = select(2, GetSpecializationInfo(2)),
			['3'] = select(2, GetSpecializationInfo(3)),
			['ANY'] = PA.ACL['Any'],
		}

		if PA.MyClass == 'DRUID' then
			Specializations['4'] = select(2, GetSpecializationInfo(4))
		end

		optionGroup.role = {
			order = 1,
			type = 'select',
			name = PA.ACL['Role'],
			desc = PA.ACL['You must be a certain role for the icon to appear.'],
			hidden = function() return selectedGroup == 'Global' end,
			values = {
				TANK = PA.ACL['Tank'],
				DAMAGER = PA.ACL['Damage'],
				HEALER = PA.ACL['Healer'],
				ANY = PA.ACL['Any'],
			},
		}

		optionGroup.tree = {
			order = 2,
			type = 'select',
			name = PA.ACL['Talent Tree'],
			desc = PA.ACL['You must be using a certain talent tree for the icon to show.'],
			hidden = function() return AR.db.Filters[PA.MyClass][selectedFilter].reverseCheck or selectedGroup == 'Global' end,
			get = function(info, value) return tostring(AR.db.Filters[PA.MyClass][selectedFilter].tree) end,
			set = function(info, value)
				if value == 'ANY' then
					AR.db.Filters[PA.MyClass][selectedFilter].tree = 'ANY'
				else
					AR.db.Filters[PA.MyClass][selectedFilter].tree = tonumber(value)
				end
			end,
			values = Specializations,
		}

		optionGroup.talentTreeException = {
			order = 2,
			type = 'select',
			name = PA.ACL['Tree Exception'],
			desc = PA.ACL['Set a talent tree to not follow the reverse check.'],
			get = function(info) return tostring(AR.db.Filters[PA.MyClass][selectedFilter]['talentTreeException'] or 'NONE') end,
			set = function(info, value) if value == 'NONE' then AR.db.Filters[PA.MyClass][selectedFilter].talentTreeException = nil else AR.db.Filters[PA.MyClass][selectedFilter]['talentTreeException'] = tonumber(value) end; end,
			hidden = function() return not AR.db.Filters[PA.MyClass][selectedFilter].reverseCheck or selectedGroup == 'Global' end,
			values = CopyTable(Specializations),
		}

		optionGroup.talentTreeException.values.NONE = PA.ACL['None']
	end
end

function AR:BuildProfile()
	PA.Defaults.profile.AuraReminder = {
		Enable = true,
		Sound = 'Warning',
		Filters = { Global = {} },
	}

	for k in pairs(LOCALIZED_CLASS_NAMES_MALE) do PA.Defaults.profile.AuraReminder.Filters[k] = {} end

	DefaultFilters = CopyTable(PA.Defaults.profile.AuraReminder.Filters)
end

function AR:Initialize()
	AR.db = PA.db.AuraReminder

	if AR.db.Enable ~= true then
		return
	end

	AR.isEnabled = true

	AR:ScheduleRepeatingTimer('Reminder_Update', .5)

	AR:CleanDB()
	AR:RegisterEvent("PLAYER_LOGOUT", 'CleanDB')
end
