
local detailsFramework = _G ["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
	return
end

local _
--lua locals
local rawset = rawset
local rawget = rawget
local setmetatable = setmetatable
local unpack = unpack ---@diagnostic disable-line
local type = type
local floor = math.floor
local loadstring = loadstring ---@diagnostic disable-line
local CreateFrame = CreateFrame ---@diagnostic disable-line
local UnitIsUnit = UnitIsUnit ---@diagnostic disable-line
local UnitClass = UnitClass ---@diagnostic disable-line
local GetInstanceInfo = GetInstanceInfo ---@diagnostic disable-line
local C_ChallengeMode = C_ChallengeMode ---@diagnostic disable-line
local C_Map = C_Map ---@diagnostic disable-line
local GetTalentInfoByID = GetTalentInfoByID ---@diagnostic disable-line

local IS_WOW_PROJECT_MAINLINE = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE ---@diagnostic disable-line
local IS_WOW_PROJECT_NOT_MAINLINE = WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE ---@diagnostic disable-line
local IS_WOW_PROJECT_CLASSIC_ERA = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC ---@diagnostic disable-line
local IS_WOW_PROJECT_MIDNIGHT = detailsFramework.IsAddonApocalypseWow() ---@diagnostic disable-line

local PixelUtil = PixelUtil or DFPixelUtil  ---@diagnostic disable-line
local UnitGroupRolesAssigned = detailsFramework.UnitGroupRolesAssigned
local loadConditionsFrame

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--load conditions panel

--this is the table prototype to hold load conditions settings
local default_load_conditions = {
	class = {},
	spec = {},
	race = {},
	talent = {},
	pvptalent = {},
	group = {},
	role = {},
	affix = {},
	encounter_ids = {},
	map_ids = {},
}

--[=[
Skittish 135994 2
Volcanic 451169 3
Necrotic 1029009 4
Teeming 136054 5
Raging 132345 6
Bolstering 132333 7
Sanguine 136124 8
Tyrannical 236401 9
Fortified 463829 10
Bursting 1035055 11
Grievous 132090 12
Explosive 2175503 13
Quaking 136025 14
Infested 2032223 16
Reaping 2446016 117
Beguiling 237565 119
Awakened 442737 120
Prideful 3528307 121
Inspiring 135946 122
Spiteful 135945 123
Storming 136018 124
Tormented 3528304 128
Infernal 1394959 129
Encrypted 4038106 130
Shrouded 136177 131
Thundering 1385910 132
[PH] 0 133
Entangling 134412 134
Afflicted 237555 135
Incorporeal 298642 136
Shielding 535593 137
--]=]

local deprecatedAffixes = {
	[1] = true, --Overflowing
	[2] = true, --Skittish
	[3] = true, --Volcanic
	[4] = true, --Necrotic
	[5] = true, --Teeming
	[6] = true, --Raging
	[7] = true, --Bolstering
	[8] = true, --Sanguine
	--[9] = true, --Tyrannical
	--[10] = true, --Fortified
	[11] = true, --Bursting
	[12] = true, --Grievous
	[13] = true, --Explosive
	[14] = true, --Quaking
	[16] = true, --Infested
	[117] = true, --Reaping
	[119] = true, --Beguiling
	[120] = true, --Awakened
	[121] = true, --Prideful
	[122] = true, --Inspiring
	[123] = true, --Spiteful
	[124] = true, --Storming
	[128] = true, --Tormented
	[129] = true, --Infernal
	[130] = true, --Encrypted
	[131] = true, --Shrouded
	[132] = true, --Thundering
	[133] = true, --Focused
	[134] = true, --Entangling
	[135] = true, --Afflicted
	[136] = true, --Incorporeal
	[137] = true, --Shielding
	[144] = true, --Thorned
	[145] = true, --Reckless
	[146] = true, --Attuned
	[147] = true, --Xal'atath's Guile
	[148] = true, --Xal'atath's Bargain: Ascendant
	--[152] = true, --Challenger's Peril
	[153] = true, --Xal'atath's Bargain: Frenzied
	[158] = true, --Xal'atath's Bargain: Voidbound
	[159] = true, --Xal'atath's Bargain: Oblivion
	[160] = true, --Xal'atath's Bargain: Devour
}

local default_load_conditions_frame_options = {
	title = "Details! Framework: Load Conditions",
	name = "Object",
}

function detailsFramework:CreateLoadFilterParser(callback)
	local filterFrame = CreateFrame("frame")

	if IS_WOW_PROJECT_MAINLINE then
		filterFrame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
		filterFrame:RegisterEvent("TRAIT_CONFIG_LIST_UPDATED")
		filterFrame:RegisterEvent("CHALLENGE_MODE_START")
	else
		filterFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
		filterFrame:RegisterEvent("PLAYER_TALENT_UPDATE")
	end

	filterFrame:RegisterEvent("PLAYER_ROLES_ASSIGNED")
	filterFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")

	filterFrame:RegisterEvent("ENCOUNTER_START")
	filterFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
	filterFrame:RegisterEvent("PLAYER_REGEN_DISABLED")

	filterFrame:RegisterEvent("CHAT_MSG_LOOT")

	filterFrame:SetScript("OnEvent", function(self, event, ...)
		if (event == "ENCOUNTER_START") then --triggers before regen_disabled
			local encounterID = ...
			filterFrame.EncounterIDCached = encounterID

		elseif (event == "CHAT_MSG_LOOT") then
			local message = ...
			if IS_WOW_PROJECT_MIDNIGHT and issecretvalue(message) then return end
			local itemId = message:match("|Hitem:(%d+):")
			itemId = tonumber(itemId)

			if (itemId == 191140) then
				xpcall(callback, geterrorhandler(), "RACE_START")
				--monitor the player backpack each second to know when the item is removed from the bag

				C_Timer.After(5, function()
					filterFrame.FindBackpackItem = C_Timer.NewTicker(1, function()
						local bFoundItem = false
						for bagId = 0, 4 do
							for slotId = 1, 32 do
								local bagItemID = C_Container.GetContainerItemID(bagId, slotId)
								if (bagItemID) then
									if (bagItemID == itemId) then
										--bronze timepiece is on the player backpack
										return
									end
								end
							end
						end

						if (not bFoundItem) then
							filterFrame.FindBackpackItem:Cancel()
							xpcall(callback, geterrorhandler(), "RACE_STOP")
							return
						end
					end)
				end)
			end
			return

		elseif (event == "PLAYER_REGEN_DISABLED") then

		elseif (event == "ENCOUNTER_END") then
			filterFrame.EncounterIDCached = nil

		elseif (event == "PLAYER_REGEN_ENABLED") then
			--f.EncounterIDCached = nil
			--when the player dies during an encounter, the game is triggering regen enabled

		elseif (event == "PLAYER_SPECIALIZATION_CHANGED") then
			if (loadConditionsFrame and loadConditionsFrame:IsShown()) then
				loadConditionsFrame:Refresh()
			end

			local unit = ...
			if (not unit or not UnitIsUnit("player", unit)) then
				return
			end

		elseif (event == "PLAYER_ROLES_ASSIGNED") then
			local assignedRole = UnitGroupRolesAssigned("player")
			if (assignedRole == "NONE") then
				local spec = DetailsFramework.GetSpecialization()
				if (spec) then
					assignedRole = DetailsFramework.GetSpecializationRole(spec)
				end
			end

			if (detailsFramework.CurrentPlayerRole == assignedRole) then
				return
			end

			detailsFramework.CurrentPlayerRole = assignedRole
		end

		--problem: this xpcall won't tell where the error happened in the callback code
		xpcall(callback, geterrorhandler(), filterFrame.EncounterIDCached)
	end)
end

function detailsFramework:PassLoadFilters(loadTable, encounterID)
	--class
	local passLoadClass
	if (loadTable.class.Enabled) then
		local _, classFileName = UnitClass("player")
		if (not loadTable.class[classFileName]) then
			return false, _G["CLASS"]
		else
			passLoadClass = true
		end
	end

	--spec
	if (IS_WOW_PROJECT_MAINLINE and loadTable.spec.Enabled) then
		local canCheckTalents = true

		if (passLoadClass) then
			--if is allowed to load on this class, check if the talents isn't from another class
			local _, classFileName = UnitClass("player")
			local specsForThisClass = detailsFramework:GetClassSpecIDs(classFileName)

			canCheckTalents = false

			for _, specID in ipairs(specsForThisClass) do
				if (loadTable.spec[specID] or loadTable.spec[specID..""]) then
					--theres a talent for this class
					canCheckTalents = true
					break
				end
			end
		end

		if (canCheckTalents) then
			local specIndex = DetailsFramework.GetSpecialization()
			if (specIndex) then
				local specID = DetailsFramework.GetSpecializationInfo(specIndex)
				if not specID or(not loadTable.spec[specID] and not loadTable.spec[specID .. ""]) then
					return false, _G["SPECIALIZATION"]
				end
			else
				return false, _G["SPECIALIZATION"]
			end
		end
	end

	--race
	if (loadTable.race.Enabled) then
		local raceName, raceFileName, raceID = UnitRace("player")
		if (not loadTable.race [raceFileName]) then
			return false, _G["RACE"]
		end
	end

	--talents
	if (IS_WOW_PROJECT_MAINLINE and loadTable.talent.Enabled) then
		local bOnlySelected, bUseHashTable = true, true
		local talentsInUse = detailsFramework:GetCharacterTalents(bOnlySelected, bUseHashTable)

		local hasTalent

		for talentId in pairs(talentsInUse) do
			if talentId and(loadTable.talent[talentId] or loadTable.talent[talentId .. ""]) then
				hasTalent =  true
				break
			end
		end

		if (not hasTalent) then
			return false, _G["TALENTS"]
		end
	end

	--pvptalent
	if (IS_WOW_PROJECT_MAINLINE and loadTable.pvptalent.Enabled) then
		local talentsInUse = detailsFramework:GetCharacterPvPTalents(false, true)
		local hasTalent
		for talentID, _ in pairs(talentsInUse) do
			if talentID and(loadTable.pvptalent [talentID] or loadTable.pvptalent [talentID .. ""]) then
				hasTalent =  true
				break
			end
		end
		if (not hasTalent) then
			return false, (_G["PVP"] or "") .. " " .. (_G["TALENTS"] or "")
		end
	end

	--group
	if (loadTable.group.Enabled) then
		local _, zoneType = GetInstanceInfo()
		if (not loadTable.group[zoneType]) then
			return false, _G["GROUP"]
		end
	end

	--role
	if (loadTable.role.Enabled) then
		local assignedRole = UnitGroupRolesAssigned("player")
		if (assignedRole == "NONE") then
			local spec = DetailsFramework.GetSpecialization()
			if (spec) then
				assignedRole = DetailsFramework.GetSpecializationRole(spec)
			end
		end
		if (not loadTable.role [assignedRole]) then
			return false, _G["ROLE"]
		end
	end

	--affix
	if (IS_WOW_PROJECT_MAINLINE and loadTable.affix.Enabled) then
		local isInMythicDungeon = C_ChallengeMode.IsChallengeModeActive()
		if (not isInMythicDungeon) then
			return false, "M+ Affix"
		end

		local GetActiveKeystoneInfo = C_ChallengeMode.GetActiveKeystoneInfo or function() return 0, {}, false end -- ensure all three return values.
		local level, affixes, wasEnergized = GetActiveKeystoneInfo()
		local hasAffix = false
		for _, affixID in ipairs(affixes) do
			if affixID and(loadTable.affix[affixID] or loadTable.affix[affixID .. ""]) then
				hasAffix = true
				break
			end
		end

		if (not hasAffix) then
			return false, "M+ Affix"
		end
	end

	--encounter id
	if (loadTable.encounter_ids.Enabled) then
		if (not encounterID) then
			return
		end

		local bHasEncounter
		for _, userEnteredEncounterId in pairs(loadTable.encounter_ids) do
			if (tonumber(userEnteredEncounterId) == tonumber(encounterID)) then
				bHasEncounter = true
				break
			end
		end

		if (not bHasEncounter) then
			return false, _G["GUILD_NEWS_FILTER3"] --"raid encounters"
		end
	end

	--map id
	if (loadTable.map_ids.Enabled) then
		local _, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
		local uiMapID = C_Map.GetBestMapForUnit("player")
		local bHasMapID = false

		for _, userEnteredMapId in pairs(loadTable.map_ids) do
			if (userEnteredMapId == zoneMapID or userEnteredMapId == uiMapID) then
				bHasMapID = true
				break
			end
		end

		if (not bHasMapID) then
			return false, _G["BATTLEFIELD_MINIMAP"] --"zone map"
		end
	end

	return true
end

--this func will deploy the default values from the prototype into the config table
function detailsFramework:UpdateLoadConditionsTable(configTable)
	configTable = configTable or {}
	detailsFramework.table.deploy(configTable, default_load_conditions)
	return configTable
end

--/run Plater.OpenOptionsPanel()PlaterOptionsPanelContainer:SelectIndex(Plater, 14)

function detailsFramework:OpenLoadConditionsPanel(optionsTable, callback, frameOptions)
	frameOptions = frameOptions or {}
	detailsFramework.table.deploy(frameOptions, default_load_conditions_frame_options)

	detailsFramework:UpdateLoadConditionsTable(optionsTable)

	if (not loadConditionsFrame) then
		loadConditionsFrame = detailsFramework:CreateSimplePanel(UIParent, 1024, 640, "Load Conditions", "loadConditionsFrame")
		loadConditionsFrame:SetBackdropColor(0, 0, 0, 1)
		loadConditionsFrame.AllRadioGroups = {}
		loadConditionsFrame.AllTextEntries = {}
		loadConditionsFrame.OptionsTable = optionsTable

		detailsFramework:ApplyStandardBackdrop(loadConditionsFrame, false, 1.1)

		local xStartAt = 10
		local x2StartAt = 500
		local anchorPositions = {
			class = {xStartAt, -70},
			spec = {xStartAt, -200},
			race = {xStartAt, -250},
			role = {xStartAt, -380},
			talent = {xStartAt, -440},
			pvptalent = {x2StartAt, -70},
			group = {x2StartAt, -170},
			affix = {x2StartAt, -240},
			encounter_ids = {x2StartAt+1, -375},
			map_ids = {x2StartAt + 210, -375},
		}

		local editingLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Load Conditions For:")
		local editingWhatLabel = detailsFramework:CreateLabel(loadConditionsFrame, "")
		editingLabel:SetPoint("topleft", loadConditionsFrame, "topleft", 10, -35)
		editingWhatLabel:SetPoint("left", editingLabel, "right", 2, 0)

		--this label store the name of what is being edited
		loadConditionsFrame.EditingLabel = editingWhatLabel

		--when the user click on an option, run the callback
			loadConditionsFrame.RunCallback = function()
				detailsFramework:Dispatch(loadConditionsFrame.CallbackFunc)
			end

		--when the user click on an option or when the panel is opened
		--check if there's an option enabled and fadein all options, fadeout otherwise
			loadConditionsFrame.OnRadioStateChanged = function(radioGroup, subConfigTable)
				subConfigTable.Enabled = nil
				subConfigTable.Enabled = next(subConfigTable) and true or nil
				radioGroup:SetFadeState(subConfigTable.Enabled)
			end

		--create the radio group for character class
			loadConditionsFrame.OnRadioCheckboxClick = function(self, key, value)
				--hierarchy: DBKey ["class"] key ["HUNTER"] value TRUE
				local DBKey = self:GetParent().DBKey
				loadConditionsFrame.OptionsTable [DBKey] [key and key .. ""] = value and true or nil

				if not value then -- cleanup "number" type values
					loadConditionsFrame.OptionsTable [DBKey] [key] = nil
				end

				loadConditionsFrame.OnRadioStateChanged(self:GetParent(), loadConditionsFrame.OptionsTable [DBKey])
				loadConditionsFrame.RunCallback()
			end

		--create the radio group for classes
			local classes = {}
			for _, classTable in pairs(detailsFramework:GetClassList()) do
				table.insert(classes, {
					name = classTable.Name,
					set = loadConditionsFrame.OnRadioCheckboxClick,
					param = classTable.FileString,
					get = function() return loadConditionsFrame.OptionsTable.class[classTable.FileString] end,
					texture = classTable.Texture,
					texcoord = classTable.TexCoord,
				})
			end

			local classGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, classes, nil, {width = 430, height = 200, title = "Character Class", backdrop_color = {0, 0, 0, 0}}, {offset_x = 130, amount_per_line = 3})
			classGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.class[1], anchorPositions.class[2])
			classGroup.DBKey = "class"
			table.insert(loadConditionsFrame.AllRadioGroups, classGroup)

		--create the radio group for character spec
			if IS_WOW_PROJECT_MAINLINE then
				local specs = {}
				for _, specID in ipairs(detailsFramework:GetClassSpecIDs(select(2, UnitClass("player")))) do
					local specID, specName, specDescription, specIcon, specBackground, specRole, specClass = DetailsFramework.GetSpecializationInfoByID(specID)
					table.insert(specs, {
						name = specName,
						set = loadConditionsFrame.OnRadioCheckboxClick,
						param = specID,
						get = function() return loadConditionsFrame.OptionsTable.spec[specID] or loadConditionsFrame.OptionsTable.spec[specID..""] end,
						texture = specIcon,
					})
				end

				local specGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, specs, nil, {width = 200, height = 200, title = "Character Spec", backdrop_color = {0, 0, 0, 0}}, {offset_x = 120, amount_per_line = 4})
				specGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.spec[1], anchorPositions.spec[2])
				specGroup.DBKey = "spec"
				table.insert(loadConditionsFrame.AllRadioGroups, specGroup)
			end

		--create radio group for character races
			local raceList = {}
			for _, raceTable in ipairs(detailsFramework:GetCharacterRaceList()) do
				table.insert(raceList, {
					name = raceTable.Name:sub(1, 15),
					set = loadConditionsFrame.OnRadioCheckboxClick,
					param = raceTable.FileString,
					get = function() return loadConditionsFrame.OptionsTable.race [raceTable.FileString] end,
				})
			end

			local raceGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, raceList, nil, {width = 200, height = 200, title = "Character Race", backdrop_color = {0, 0, 0, 0}})
			raceGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.race [1], anchorPositions.race [2])
			raceGroup.DBKey = "race"
			table.insert(loadConditionsFrame.AllRadioGroups, raceGroup)

		--create radio group for talents
			if IS_WOW_PROJECT_MAINLINE then
				--[=[ 7.0 to 9.0 talents schema
				local talentList = {}
				for _, talentTable in ipairs(detailsFramework:GetCharacterTalents()) do
					if talentTable.ID then
						table.insert(talentList, {
							name = talentTable.Name:sub(1, 15),
							set = loadConditionsFrame.OnRadioCheckboxClick,
							param = talentTable.ID,
							get = function() return loadConditionsFrame.OptionsTable.talent[talentTable.ID] or loadConditionsFrame.OptionsTable.talent[talentTable.ID .. ""] end,
							texture = talentTable.Texture,
						})
					end
				end
				--]=]

				--10.0 talents schema
				local talentList = {}
				local talentGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, talentList, nil, {width = 200, height = 200, title = "Character Talents", backdrop_color = {0, 0, 0, 0}}, {offset_x = 64, amount_per_line = 16})
				talentGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.talent[1], anchorPositions.talent[2])
				talentGroup.DBKey = "talent"

				table.insert(loadConditionsFrame.AllRadioGroups, talentGroup)
				loadConditionsFrame.TalentGroup = talentGroup

				do
					if (false) then --disabled, isn't in use
						--create a frame to show talents selected in other specs or characters
						local otherTalents = CreateFrame("frame", nil, loadConditionsFrame, "BackdropTemplate")
						otherTalents:SetSize(26, 26)
						otherTalents:SetPoint("left", talentGroup.Title.widget, "right", 10, -2)
						otherTalents.Texture = detailsFramework:CreateImage(otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
						otherTalents.Texture:SetAllPoints()

						local removeTalent = function(_, _, talentID)
							loadConditionsFrame.OptionsTable.talent[talentID] = nil
							GameCooltip2:Hide()
							loadConditionsFrame.OnRadioStateChanged(talentGroup, loadConditionsFrame.OptionsTable[talentGroup.DBKey])
							--loadConditionsFrame.CanShowTalentWarning()
						end

						local buildTalentMenu = function()
							local playerTalents = detailsFramework:GetCharacterTalents()
							local indexedTalents = {}
							for _, talentTable in ipairs(playerTalents) do
								table.insert(indexedTalents, talentTable.ID)
							end

							--talents selected to load
							GameCooltip2:AddLine("select a talent to remove it (added from a different spec or character)", "", 1, "orange", "orange", 9)
							GameCooltip2:AddLine("$div", nil, nil, -1, -1)

							for talentID, _ in pairs(loadConditionsFrame.OptionsTable.talent) do
								if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
									local talentID, name, texture, selected, available = GetTalentInfoByID(talentID)
									if (name) then
										GameCooltip2:AddLine(name)
										GameCooltip2:AddIcon(texture, 1, 1, 16, 16, .1, .9, .1, .9)
										GameCooltip2:AddMenu(1, removeTalent, talentID)
									end
								end
							end
						end

						otherTalents.CoolTip = {
							Type = "menu",
							BuildFunc = buildTalentMenu,
							OnEnterFunc = function(self) end,
							OnLeaveFunc = function(self) end,
							FixedValue = "none",
							ShowSpeed = 0.05,
							Options = function()
								GameCooltip2:SetOption("TextFont", "Friz Quadrata TT")
								GameCooltip2:SetOption("TextColor", "orange")
								GameCooltip2:SetOption("TextSize", 12)
								GameCooltip2:SetOption("FixedWidth", 220)
								GameCooltip2:SetOption("ButtonsYMod", -4)
								GameCooltip2:SetOption("YSpacingMod", -4)
								GameCooltip2:SetOption("IgnoreButtonAutoHeight", true)

								GameCooltip2:SetColor(1, 0.5, 0.5, 0.5, 0)

								local preset2_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
								local gray_table = {0.37, 0.37, 0.37, 0.95}
								local black_table = {0.2, 0.2, 0.2, 1}
								GameCooltip2:SetBackdrop(1, preset2_backdrop, gray_table, black_table)
								GameCooltip2:SetBackdrop(2, preset2_backdrop, gray_table, black_table)
							end,
						}
						GameCooltip2:CoolTipInject(otherTalents)

						--[=[
						function loadConditionsFrame.CanShowTalentWarning() --not in use
							local playerTalents = detailsFramework:GetCharacterTalents()
							local indexedTalents = {}
							for _, talentTable in ipairs(playerTalents) do
								table.insert(indexedTalents, talentTable.ID)
							end
							for talentID, _ in pairs(loadConditionsFrame.OptionsTable.talent) do
								if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
									otherTalents:Show()
									return
								end
							end
							otherTalents:Hide()
						end
						--]=]
					end
				end
			end

		--create radio group for pvp talents
			if IS_WOW_PROJECT_MAINLINE then
				local pvpTalentList = {}
				for _, talentTable in ipairs(detailsFramework:GetCharacterPvPTalents()) do
					table.insert(pvpTalentList, {
						name = talentTable.Name:sub(1, 15),
						set = loadConditionsFrame.OnRadioCheckboxClick,
						param = talentTable.ID,
						get = function() return loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID] or loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID .. ""] end,
						texture = talentTable.Texture,
					})
				end
				local pvpTalentGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, pvpTalentList, nil, {width = 200, height = 200, title = "Characer PvP Talents", backdrop_color = {0, 0, 0, 0}}, {offset_x = 160, amount_per_line = 3})
				pvpTalentGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.pvptalent [1], anchorPositions.pvptalent [2])
				pvpTalentGroup.DBKey = "pvptalent"
				table.insert(loadConditionsFrame.AllRadioGroups, pvpTalentGroup)
				loadConditionsFrame.PvPTalentGroup = pvpTalentGroup

				do
					if (false) then
						--create a frame to show talents selected in other specs or characters
						local otherTalents = CreateFrame("frame", nil, loadConditionsFrame, "BackdropTemplate")
						otherTalents:SetSize(26, 26)
						otherTalents:SetPoint("left", pvpTalentGroup.Title.widget, "right", 10, -2)
						otherTalents.Texture = detailsFramework:CreateImage(otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
						otherTalents.Texture:SetAllPoints()

						local removeTalent = function(_, _, talentID)
							loadConditionsFrame.OptionsTable.pvptalent [talentID] = nil
							GameCooltip2:Hide()
							loadConditionsFrame.OnRadioStateChanged(pvpTalentGroup, loadConditionsFrame.OptionsTable [pvpTalentGroup.DBKey])
							--loadConditionsFrame.CanShowPvPTalentWarning()
						end

						local buildTalentMenu = function()
							local playerTalents = detailsFramework:GetCharacterPvPTalents()
							local indexedTalents = {}
							for _, talentTable in ipairs(playerTalents) do
								table.insert(indexedTalents, talentTable.ID)
							end

							--talents selected to load
							GameCooltip2:AddLine("select a talent to remove it(added from a different spec or character)", "", 1, "orange", "orange", 9)
							GameCooltip2:AddLine("$div", nil, nil, -1, -1)

							for talentID, _ in pairs(loadConditionsFrame.OptionsTable.pvptalent) do
								if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
									local _, name, texture = GetPvpTalentInfoByID(talentID)
									if (name) then
										GameCooltip2:AddLine(name)
										GameCooltip2:AddIcon(texture, 1, 1, 16, 16, .1, .9, .1, .9)
										GameCooltip2:AddMenu(1, removeTalent, talentID)
									end
								end
							end
						end

						otherTalents.CoolTip = {
							Type = "menu",
							BuildFunc = buildTalentMenu,
							OnEnterFunc = function(self) end,
							OnLeaveFunc = function(self) end,
							FixedValue = "none",
							ShowSpeed = 0.05,
							Options = function()
								GameCooltip2:SetOption("TextFont", "Friz Quadrata TT")
								GameCooltip2:SetOption("TextColor", "orange")
								GameCooltip2:SetOption("TextSize", 12)
								GameCooltip2:SetOption("FixedWidth", 220)
								GameCooltip2:SetOption("ButtonsYMod", -4)
								GameCooltip2:SetOption("YSpacingMod", -4)
								GameCooltip2:SetOption("IgnoreButtonAutoHeight", true)

								GameCooltip2:SetColor(1, 0.5, 0.5, 0.5, 0)

								local preset2_backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
								local gray_table = {0.37, 0.37, 0.37, 0.95}
								local black_table = {0.2, 0.2, 0.2, 1}
								GameCooltip2:SetBackdrop(1, preset2_backdrop, gray_table, black_table)
								GameCooltip2:SetBackdrop(2, preset2_backdrop, gray_table, black_table)
							end,
						}
						GameCooltip2:CoolTipInject(otherTalents)

						function loadConditionsFrame.CanShowPvPTalentWarning()
							local playerTalents = detailsFramework:GetCharacterPvPTalents()
							local indexedTalents = {}
							for _, talentTable in ipairs(playerTalents) do
								table.insert(indexedTalents, talentTable.ID)
							end
							for talentID, _ in pairs(loadConditionsFrame.OptionsTable.pvptalent) do
								if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
									otherTalents:Show()
									return
								end
							end
							otherTalents:Hide()
						end
						--]=]
					end
				end
			end

		--create radio for group types
			local groupTypes = {}
			for _, groupTable in ipairs(detailsFramework:GetGroupTypes()) do
				table.insert(groupTypes, {
					name = groupTable.Name,
					set = loadConditionsFrame.OnRadioCheckboxClick,
					param = groupTable.ID,
					get = function() return loadConditionsFrame.OptionsTable.group [groupTable.ID] or loadConditionsFrame.OptionsTable.group [groupTable.ID .. ""] end,
				})
			end
			local groupTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, groupTypes, nil, {width = 200, height = 200, title = "Group Types", backdrop_color = {0, 0, 0, 0}}, {offset_x = 125})
			groupTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.group[1], anchorPositions.group[2])
			groupTypesGroup.DBKey = "group"
			table.insert(loadConditionsFrame.AllRadioGroups, groupTypesGroup)

		--create radio for character roles
			local roleTypes = {}
			for _, roleTable in ipairs(detailsFramework:GetRoleTypes()) do
				local texture, l, r, t, b = detailsFramework:GetRoleIconAndCoords(roleTable.ID)
				table.insert(roleTypes, {
					name = roleTable.Name,
					texture = texture,
					texcoord = {l, r, t, b},
					set = loadConditionsFrame.OnRadioCheckboxClick,
					param = roleTable.ID,
					get = function() return loadConditionsFrame.OptionsTable.role [roleTable.ID] or loadConditionsFrame.OptionsTable.role [roleTable.ID .. ""] end,
				})
			end

			local roleTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, roleTypes, nil, {width = 200, height = 200, title = "Role Types", backdrop_color = {0, 0, 0, 0}})
			roleTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.role[1], anchorPositions.role[2])
			roleTypesGroup.DBKey = "role"
			table.insert(loadConditionsFrame.AllRadioGroups, roleTypesGroup)

		--create radio group for mythic+ affixes
			if IS_WOW_PROJECT_MAINLINE then
				local affixes = {}
				local GetAffixInfo = C_ChallengeMode.GetAffixInfo or function() return nil end
				for i = 2, 1000 do
					local affixName, desc, texture = GetAffixInfo(i)
					if (affixName and affixName ~= "" and not deprecatedAffixes[i]) then
						table.insert(affixes, {
							name = affixName,
							set = loadConditionsFrame.OnRadioCheckboxClick,
							param = i,
							get = function() return loadConditionsFrame.OptionsTable.affix[i] or loadConditionsFrame.OptionsTable.affix[i .. ""] end,
							texture = texture,
						})
					end
				end

				local affixTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, affixes, nil, {width = 200, height = 200, title = "M+ Affixes", backdrop_color = {0, 0, 0, 0}}, {offset_x = 230, amount_per_line = 2})
				affixTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.affix [1], anchorPositions.affix [2])
				affixTypesGroup.DBKey = "affix"
				table.insert(loadConditionsFrame.AllRadioGroups, affixTypesGroup)
			end

		--text entries functions
			local textEntryRefresh = function(self)
				local idList = loadConditionsFrame.OptionsTable [self.DBKey]
				self:SetText("")
				for _, id in pairs(idList) do
					if tonumber(id) then
						self:SetText(self:GetText() .. " " .. id)
					end
				end
				self:SetText(self:GetText():gsub("^ ", ""))
			end

			local textEntryOnEnterPressed = function(_, self)
				table.wipe(loadConditionsFrame.OptionsTable [self.DBKey])
				local text = self:GetText()

				for _, ID in ipairs({strsplit(" ", text)}) do
					ID = detailsFramework:trim(ID)
					ID = tonumber(ID)
					if (ID) then
						table.insert(loadConditionsFrame.OptionsTable [self.DBKey], ID)
						loadConditionsFrame.OptionsTable [self.DBKey].Enabled = true
					end
				end
			end

		--create the text entry to type the encounter ID
			local encounterIDLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Encounter ID", detailsFramework:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
			local encounterIDEditbox = detailsFramework:CreateTextEntry(loadConditionsFrame, function() loadConditionsFrame.RunCallback() end, 200, 20, "EncounterEditbox", _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
			encounterIDLabel:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.encounter_ids[1], anchorPositions.encounter_ids[2])
			encounterIDEditbox:SetPoint("topleft", encounterIDLabel, "bottomleft", 0, -2)
			encounterIDEditbox.DBKey = "encounter_ids"
			encounterIDEditbox.Refresh = textEntryRefresh
			encounterIDEditbox.tooltip = "Enter multiple IDs separating with a whitespace.\nExample: 35 45 95\n\nSanctum of Domination:\n"

			for _, encounterTable in ipairs(detailsFramework:GetCLEncounterIDs()) do
				encounterIDEditbox.tooltip = encounterIDEditbox.tooltip .. encounterTable.ID .. " - " .. encounterTable.Name .. "\n"
			end

			encounterIDEditbox:SetHook("OnEnterPressed", textEntryOnEnterPressed)
			table.insert(loadConditionsFrame.AllTextEntries, encounterIDEditbox)

		--create the text entry for map ID
			local mapIDLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Map ID", detailsFramework:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
			local mapIDEditbox = detailsFramework:CreateTextEntry(loadConditionsFrame, function() loadConditionsFrame.RunCallback() end, 200, 20, "MapEditbox", _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
			mapIDLabel:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.map_ids[1], anchorPositions.map_ids[2])
			mapIDEditbox:SetPoint("topleft", mapIDLabel, "bottomleft", 0, -2)
			mapIDEditbox.DBKey = "map_ids"
			mapIDEditbox.Refresh = textEntryRefresh
			mapIDEditbox.tooltip = "Enter multiple IDs separating with a whitespace\nExample: 35 45 95"
			mapIDEditbox:SetHook("OnEnterPressed", textEntryOnEnterPressed)
			table.insert(loadConditionsFrame.AllTextEntries, mapIDEditbox)

		function loadConditionsFrame.Refresh(self)
			if IS_WOW_PROJECT_MAINLINE then
				---@type {Name: string, ID: number, Texture: any, IsSelected: boolean}[]
				local allTalents = detailsFramework:GetAllTalents()
				local talentList = {}
				for _, talentTable in ipairs(allTalents) do
					if (talentTable.ID) then
						table.insert(talentList, {
							name = "", --talentTable.Name:sub(1, 15),
							set = loadConditionsFrame.OnRadioCheckboxClick,
							param = talentTable.ID,
							get = function() return loadConditionsFrame.OptionsTable.talent[talentTable.ID] or loadConditionsFrame.OptionsTable.talent[talentTable.ID .. ""] end,
							texture = talentTable.Texture,
							tooltip = talentTable.Name,
						})
					end
				end

				--[=[]]
				--update the talents(might have changed if the player changed its specializationid)
				local talentList = {}
				for _, talentTable in ipairs(detailsFramework:GetCharacterTalents()) do
					if talentTable.ID then
						table.insert(talentList, {
							name = talentTable.Name,
							set = loadConditionsFrame.OnRadioCheckboxClick,
							param = talentTable.ID,
							get = function() return loadConditionsFrame.OptionsTable.talent [talentTable.ID] or loadConditionsFrame.OptionsTable.talent [talentTable.ID .. ""] end,
							texture = talentTable.Texture,
						})
					end
				end
				--]=]

				loadConditionsFrame.TalentGroup:SetOptions(talentList)
			end

			if IS_WOW_PROJECT_MAINLINE then
				local pvpTalentList = {}
				for _, talentTable in ipairs(detailsFramework:GetCharacterPvPTalents()) do
					table.insert(pvpTalentList, {
						name = talentTable.Name:sub(1, 15),
						set = loadConditionsFrame.OnRadioCheckboxClick,
						param = talentTable.ID,
						get = function() return loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID] or loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID .. ""] end,
						texture = talentTable.Texture,
					})
				end
				loadConditionsFrame.PvPTalentGroup:SetOptions(pvpTalentList)
			end

			--refresh the radio group
			for _, radioGroup in ipairs(loadConditionsFrame.AllRadioGroups) do
				radioGroup:Refresh()
				loadConditionsFrame.OnRadioStateChanged(radioGroup, loadConditionsFrame.OptionsTable [radioGroup.DBKey])
			end

			--refresh text entries
			for _, textEntry in ipairs(loadConditionsFrame.AllTextEntries) do
				textEntry:Refresh()
			end

			if IS_WOW_PROJECT_MAINLINE then
				--loadConditionsFrame.CanShowTalentWarning()
				--loadConditionsFrame.CanShowPvPTalentWarning()
			end
		end

	end

	--set the options table
	loadConditionsFrame.OptionsTable = optionsTable

	--set the callback func
	loadConditionsFrame.CallbackFunc = callback
	loadConditionsFrame.OptionsTable = optionsTable

	--set title
	loadConditionsFrame.EditingLabel:SetText(frameOptions.name)
	loadConditionsFrame.Title:SetText(frameOptions.title)

	--show the panel to the user
	loadConditionsFrame:Show()

	loadConditionsFrame:Refresh()
end
