--[[ ---------------------------------------------------------------------------
Created:		8/2/2010 6:54:28 AM
Last Modified:	2011-04-29T08:44:39Z
Author:			orgevo
Version:		v1.3a

Options:	Contains all static options data for the addon.

AtlasLootAdvancedSearch is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

AtlasLootAdvancedSearch is distributed WITHOUT ANY WARRANTY; without even the 
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with AtlasLootAdvancedSearch.	If not, see <http://www.gnu.org/licenses/>.

----------------------------------------------------------------------------- ]]

local ADDON_TAG					= "AtlasLootAdvancedSearch"
local AtlasLootAdvancedSearch	= LibStub("AceAddon-3.0"):GetAddon(ADDON_TAG);
local alas_addon				= AtlasLootAdvancedSearch;
local al_addon					= AtlasLoot;
local FILTER_DEBUG				= false
local ENABLE_LOGGING			= alas_addon.ENABLE_LOGGING and FILTER_DEBUG

-- localization
local L							= LibStub("AceLocale-3.0"):GetLocale(ADDON_TAG, true)
local AL						= LibStub("AceLocale-3.0"):GetLocale("AtlasLoot");
local ADDON_NAME				= L["ADDON_NAME"]
local BabbleInventory			= AtlasLoot_GetLocaleLibBabble("LibBabble-Inventory-3.0")

local GREY = al_addon.GREY;
local RED = al_addon.RED;
local WHITE = al_addon.WHITE;
local GREEN = al_addon.GREEN;
local PURPLE = al_addon.PURPLE;
local BLUE = al_addon.BLUE;
local ORANGE = al_addon.ORANGE;

local tinsert, tremove, tconcat, tsort, twipe = table.insert, table.remove, table.concat, table.sort, table.wipe
local strlen, strmatch, strfind, strsub, strformat, strlower, strupper = string.len, string.match, string.find, string.sub, string.format, string.lower, string.upper
local pairs, next, type = pairs, next, type
local tostring = tostring

-- print wrappers
-- t_print (testing): what I use while developing....most of these will be commented out in the repository versions
-- dev_print (development): outputs only when AtlasLootAdvancedSearch.dev_mode is true
local function r_print(str) alas_addon:Print(str); end
local function r_printf(str,...) alas_addon:Print(strformat(str,...)); end

local dbgProxy = alas_addon.DebugProxy;
local function isDevMode()			return dbgProxy and dbgProxy:isDevMode() end
local function isInternal()			return dbgProxy and dbgProxy:isInternal() end
local function t_print(str)			if dbgProxy and ENABLE_LOGGING then dbgProxy:t_print(str) end end
local function t_printf(str,...)	if dbgProxy and ENABLE_LOGGING then dbgProxy:t_printf(str, ...) end end
local function dev_print(str)		if dbgProxy and ENABLE_LOGGING then dbgProxy:dev_print(str) end end
local function dev_printf(str, ...)	if dbgProxy and ENABLE_LOGGING then dbgProxy:dev_printf(str,...) end end
local function d_print(str)			if dbgProxy and ENABLE_LOGGING then dbgProxy:d_print(str) end end
local function d_printf(str,...)	if dbgProxy and ENABLE_LOGGING then dbgProxy:d_printf(str,...) end end
local function funcEnter(obj, funcName, formatStr, ...)
	if alas_addon.DebugProxy.isEnabled and ENABLE_LOGGING then
		if formatStr then alas_addon.DebugProxy:TraceEnter(obj,funcName,strformat(formatStr,...));
		else alas_addon.DebugProxy:TraceEnter(obj,funcName); end
	end
end
local function funcExit(obj, funcName, formatStr, ...)
	if alas_addon.DebugProxy.isEnabled and ENABLE_LOGGING then
		if formatStr then alas_addon.DebugProxy:TraceExit(obj,funcName,strformat(formatStr,...));
		else alas_addon.DebugProxy:TraceExit(obj,funcName); end
	end
end
local function t_printSlow(str)			if alas_addon.ALLOW_SLOW_LOGS then t_print(str)		end end
local function t_printfSlow(str,...)	if alas_addon.ALLOW_SLOW_LOGS then t_printf(str,...)	end end

function toggledebug_filter()
	FILTER_DEBUG = not FILTER_DEBUG;
end

-- the following tables duplicated from AtlasLoot.Filters.lua, as they are declared local
-- this table is used to indicate the order in which the categories should occur (since tables with non-integer indices
-- are iterated in arbitrary order by next()
local FilterSort = {"Armor", "Other", "ItemSlot", "WeaponsMeele", "WeaponsMeeleTwoHand", "WeaponsRanged"}

-- holds the localized names for the categories.  the display name isn't used by us atm, but perhaps down the
-- road we'll need to display these somewhere, so no reason to not just include them here now.
local FilterTableNames = {
	["Armor"] = BabbleInventory["Armor"],
	["WeaponsMeele"] = AL["Melee weapons"],
	["WeaponsMeeleTwoHand"] = BabbleInventory["Two-Hand"],--.." "..AL["Melee weapons:"],
	["WeaponsRanged"] = AL["Ranged weapons"],
	["Other"] = AL["Other"],
	["ItemSlot"] = AL["Itemslot"],
}

-- holds the loot types should fall under which categories
local FilterTable = {
	["Armor"] = {
		"#a1#",				-- Cloth
		"#a2#",				-- Leather
		"#a3#",				-- Mail
		"#a4#",				-- Plate
	--[[
		"Cloth",		--1
		"Leather",		--2
		"Mail",			--3
		"Plate",		--4
	--]]
	},
		
	["WeaponsMeele"] = {
		"#s15#",			-- Held in Off-Hand
		"#w4#",				-- Dagger
		"#w6#",				-- Mace
		"#w9#",				-- Staff	
		"#w1#",				-- Axe
		"#w7#",				-- Polearm
		"#w8#",				-- Shield
		"#w10#",			-- Sword
		"#w13#",			-- Fist Weapon
		--[[
		"Held in Off-Hand",	--1
		"Dagger",			--2
		"Mace",				--3
		"Staff",			--4		
		"Axe",				--5
		"Polearm",			--6
		"Shield",			--7
		"Sword",			--8
		"Fist Weapon",		--9
		--]]
	},
		
	["WeaponsMeeleTwoHand"] = {
		"#w6#",				-- Mace
		"#w1#",				-- Axe
		"#w10#",			-- Sword
		--[[
		"Mace",				--1
		"Axe",				--2
		"Sword",			--3	
		--]]
	},
		
	["WeaponsRanged"] = {
		"#w12#",			-- Wand
		"#w2#",				-- Bow
		"#w3#",				-- Crossbow
		"#w5#",				-- Gun
		--[[
		"Wand",			--1
		"Bow",			--2
		"Crossbow",		--3
		"Gun",			--4
		"Thrown",		--5
		--]]
	},
	--[[
	["Relics"] = {
		"Idol",			--1
		"Totem",		--2
		"Libram",		--3
		"Sigils",		--4
	},
	--]]
	["Other"] = {
	--[[
		"#s13#",			-- Ring
		"#s14#",			-- Trinket
		"#s2#",				-- Neck
		"#s4#",				-- Back
		"#s16#",			-- Relic
	--]]
		"Ring",			--1
		"Trinket",		--2
		"Neck",			--3
		"Back",			--4
	}
}
-- used for quick lookup by the code that scans the loot item metadata
local tokenTable = {
	["#a1#"]	= "Cloth",
	["#a2#"]	= "Leather",
 	["#a3#"]	= "Mail",
 	["#a4#"]	= "Plate",

	["#s15#"]	= "Held in Off-Hand",
	["#w4#"]	= "Dagger",
	["#w6#"]	= "Mace",
	["#w9#"]	= "Staff",		
	["#w1#"]	= "Axe",
	["#w7#"]	= "Polearm",
	["#w8#"]	= "Shield",
	["#w10#"]	= "Sword",
	["#w13#"]	= "Fist Weapon",

	["#w6#"]	= "Mace",
	["#w1#"]	= "Axe",
--	"Sword"		= "##",	

	["#w12#"]	= "Wand",
	["#w2#"]	= "Bow",
	["#w3#"]	= "Crossbow",
	["#w5#"]	= "Gun",
	["#w11#"]	= "Thrown",

	["#w14#"]	= "Idol",
	["#w15#"]	= "Totem",
	["#w16#"]	= "Libram",
	["#w21#"]	= "Sigils",

	["#s13#"]	= "Ring",
	["#s14#"]	= "Trinket",
	["#s2#"]	= "Neck",
	["#s4#"]	= "Back",
}
local reverseTokenTable = {
	["Cloth"]			= "#a1#",
	["Leather"]			= "#a2#",
 	["Mail"]			= "#a3#",
 	["Plate"]			= "#a4#",

	["Held in Off-Hand"]=	"#s15#",
	["Dagger"]			=	"#w4#",
	["Mace"]			=	"#w6#",
	["Staff"]			=	"#w9#",		
	["Axe"]				=	"#w1#",
	["Polearm"]			=	"#w7#",
	["Shield"]			=	"#w8#",
	["Sword"]			=	"#w10#",
	["Fist Weapon"]		=	"#w13#",

	["Mace"]			=	"#w6#",
	["Axe"]				=	"#w1#",
--	"Sword"				=	"##",	

	["Wand"]			=	"#w12#",
	["Bow"]				=	"#w2#",
	["Crossbow"]		=	"#w3#",
	["Gun"]				=	"#w5#",
	["Thrown"]			=	"#w11#",

	["Idol"]			=	"#w14#",
	["Totem"]			=	"#w15#",
	["Libram"]			=	"#w16#",
	["Sigils"]			=	"#w21#",

	["Ring"]			=	"#s13#",
	["Trinket"]			= 	"#s14#",
	["Neck"]			=	"#s2#",
	["Back"]			=	"#s4#",
}

-- not used atm, but I would like to add a {class} token/filter to the search options so that you can set an option to globally indicate
-- that only items which the current character's class can actually use should show up in searches
-- So, I'm leaving this here - these tables show which armor types are usable by which classes.
local ClassHides = {
	["DRUID"] = {["Armor"] = {false,true,false,false},["WeaponsMeele"] = {true,true,true,true,false,true,false,false,false},["WeaponsMeeleTwoHand"] = {true,false,false},["WeaponsRanged"] = {false,false,false,false,false},["Other"] = {true,true,true,true,true}},
	["MAGE"] = {["Armor"] = {true,false,false,false},["WeaponsMeele"] = {true,true,false,true,false,false,false,true,false},["WeaponsMeeleTwoHand"] = {false,false,false},["WeaponsRanged"] = {true,false,false,false,false},["Other"] = {true,true,true,true,false}},
	["PALADIN"] = {["Armor"] = {false,false,false,true},["WeaponsMeele"] = {true,false,true,false,true,true,true,true,false},["WeaponsMeeleTwoHand"] = {true,false,true},["WeaponsRanged"] = {false,false,false,false,false},["Other"] = {true,true,true,true,true}},
	["PRIEST"] = {["Armor"] = {true,false,false,false},["WeaponsMeele"] = {true,true,true,true,false,false,false,false,false},["WeaponsMeeleTwoHand"] = {false,false,false},["WeaponsRanged"] = {true,false,false,false,false},["Other"] = {true,true,true,true,false}},
	["ROGUE"] = {["Armor"] = {false,true,false,false},["WeaponsMeele"] = {true,true,true,false,true,false,false,true,true},["WeaponsMeeleTwoHand"] = {false,false,false},["WeaponsRanged"] = {false,true,true,true,true},["Other"] = {true,true,true,true,false}},
	["HUNTER"] = {["Armor"] = {false,false,true,false},["WeaponsMeele"] = {false,true,false,true,true,true,false,true,true},["WeaponsMeeleTwoHand"] = {false,true,true},["WeaponsRanged"] = {false,true,true,true,false},["Other"] = {true,true,true,true,false}},
	["SHAMAN"] = {["Armor"] = {false,false,true,false},["WeaponsMeele"] = {true,true,true,true,true,false,true,false,true},["WeaponsMeeleTwoHand"] = {true,true,false},["WeaponsRanged"] = {false,false,false,false,false},["Other"] = {true,true,true,true,true}},
	["WARLOCK"] = {["Armor"] = {true,false,false,false},["WeaponsMeele"] = {true,true,false,true,false,false,false,true,false},["WeaponsMeeleTwoHand"] = {false,false,false},["WeaponsRanged"] = {true,false,false,false,false},["Other"] = {true,true,true,true,false}},
	["WARRIOR"] = {["Armor"] = {false,false,false,true},["WeaponsMeele"] = {true,true,true,true,true,true,true,true,true},["WeaponsMeeleTwoHand"] = {true,true,true},["WeaponsRanged"] = {false,true,true,true,true},["Other"] = {true,true,true,true,false}},
	["DEATHKNIGHT"] = {["Armor"] = {false,false,false,true},["WeaponsMeele"] = {true,false,true,false,true,true,false,true,false},["WeaponsMeeleTwoHand"] = {true,false,true},["WeaponsRanged"] = {false,false,false,false,false},["Other"] = {true,true,true,true,false}}
}








--[[==============================================================================
	Our filter class declarations.
==========================================================================--]]
FilterBase = newclass("FilterBase");
	AdvancedFilter = newclass("AdvancedFilter", FilterBase);
	FilterCategory = newclass("FilterCategory", FilterBase);
	Filter = newclass("Filter", FilterBase);

--[[==============================================================================
	FilterBase
==========================================================================--]]
function FilterBase:init()
	self.super:init();
end

--[[==============================================================================
	AdvancedFilter
==========================================================================--]]
function AdvancedFilter:init()
	self.super:init();
	self.Categories = {}
end

function AdvancedFilter:Populate()
	for idx = 1, #FilterSort do
		local categoryID = FilterSort[idx];
		if FilterTableNames[categoryID] then
			self:AddCategory(categoryID, FilterTableNames[categoryID]);
		end
	end
	
	for categoryIdx = 1, #self.Categories do
		local category = self.Categories[categoryIdx];
		category:Populate();
	end
end

function AdvancedFilter:AddCategory(categoryID, categoryName)
	assert(categoryID);
	assert(type(categoryID)=="string");
	assert(categoryID ~= "");
	assert(categoryName);
	assert(type(categoryName)=="string");
	assert(categoryName~="");
	
	local newCategory = FilterCategory:new(categoryID,categoryName);
	self.Categories[#self.Categories + 1] = newCategory;
end

-- returns TRUE if the item corresponding to the encodedMetadataString should be included in the search results
-- encodedMetadataString would be the field from the item info tables that are used all over AltasLoot that has the weapon/armor type/class, etc. info encoded.
function AdvancedFilter:IsItemAllowed(encodedMetadataString)
	-- in order for the item to be considered relevant at all, it must be relevant to at least one filter; otherwise, all of the
	-- filters will indicate that the the item is allowed to be displayed, but that information is meaningless.
	local result, hasRelevantFilter = true, false;
	
	-- this is one way to do it, probably not quite as fast as iterating down into the tables and returning as soon as we hit a match
	local flatFilterTable = self:GetFilters();
	if flatFilterTable then
		for filterIndex = 1, #flatFilterTable do
			local filter = flatFilterTable[filterIndex];
			
			local meetsFilterConditions, isRelevantToFilter = filter:IsItemAllowed(encodedMetadataString);
			hasRelevantFilter = hasRelevantFilter or isRelevantToFilter;
			
			if not meetsFilterConditions then
				-- filter determined that this item did not satisfy that filter's conditions.
				result = false;
				break;
			end
		end
	end
	
	return result, hasRelevantFilter;
end

-- retrieves the list of filters (each filter corresponds to a single checkbox in the filter options panel)
function AdvancedFilter:GetFilters( resultTbl )
	if not resultTbl then resultTbl = {} end;
	
	for idx = 1, #self.Categories do
		local category = self.Categories[idx];
		category:GetFilters(resultTbl);
	end
	
	return resultTbl;
end

--[[==============================================================================
	FilterCategory
==========================================================================--]]
function FilterCategory:init(categoryID, categoryName)
	self.super:init();
	
	self.CategoryID = categoryID;
	self.CategoryName = categoryName;
	self.Filters = {};
end

function FilterCategory:GetID()
	return self.CategoryID;
end

function FilterCategory:Populate()
	if FilterTable[self.CategoryID] then
		for idx, filterID in pairs(FilterTable[self.CategoryID]) do
			self:AddFilter(filterID);
		end
	end
end

-- subCategoryID would be something like Mail, Mace, etc.
function FilterCategory:AddFilter(filterID)
	assert(filterID);
	assert(type(filterID)=="string");
	assert(filterID~="");
	
	if not self:FindFilterIndex(filterID) then
		local newFilter = Filter:new(self,filterID);
		self.Filters[#self.Filters + 1] = newFilter;
	
		newFilter:LoadSavedValue();
	end
end

-- returns a list of the filters contained in this category
function FilterCategory:GetFilters( resultTbl )
	if not resultTbl then resultTbl = {} end
	
	for idx = 1, #self.Filters do
		local filter = self.Filters[idx];
		
		tinsert(resultTbl, filter);
	end
	
	return resultTbl;
end

-- returns the index for the filter with the specified ID, or nil if no filter was found with that ID
function FilterCategory:FindFilterIndex(filterID)
	assert(filterID);
	assert(type(filterID)=="string");
	assert(filterID~="");
	
	local result;
	for idx = 1, #self.Filters do
		if self.Filters[idx]:GetID() == filterID then
			result = idx;
			break;
		end
	end
	
	return result;
end

--[[==============================================================================
	Filter
==========================================================================--]]

function Filter:init(parentCategory, filterID)
	self.super:init();
	assert(filterID);
	assert(type(filterID)=="string");
	assert(filterID~="");
	
	self.CategoryID = parentCategory:GetID();
	self.FilterID = filterID;
	self.FilterCode = reverseTokenTable[self.FilterID];
	self.enabled = false;
end

function Filter:GetID()
	return self.FilterID;
end

function Filter:IsEnabled()
	return self.enabled;
end

function Filter:SetEnabled( value )
	if value ~= nil and type(value) == "boolean" then
		self.enabled = value;
	end
end

function Filter:GetFilterCode()
	return self.FilterCode;
end

-- applies the value from SavedVariables to the filter objects that will be mapped onto the checkbox states.
function Filter:LoadSavedValue()
	local savedValue = false;
	if self.CategoryID and self.FilterID then
		if AtlasLootFilterDB and AtlasLootFilterDB[self.CategoryID] and AtlasLootFilterDB[self.CategoryID][self.FilterID] ~= nil then
			savedValue = AtlasLootFilterDB[self.CategoryID][self.FilterID];
		end
	end
	
	self:SetEnabled(savedValue);
end

function Filter:IsItemAllowed(encodedMetadataString)
	-- if the filter doesn't apply to this category of item, then we don't care whether it's shown
	local result, isItemRelevant = true, false;
	
	if encodedMetadataString and type(encodedMetadataString) == "string" then
		isItemRelevant = strfind(encodedMetadataString, self:GetFilterCode()) ~= nil;
		result = (not isItemRelevant) or self:IsEnabled();
	end
	
	return result, isItemRelevant;
end
--[[==============================================================================
	Interface
==========================================================================--]]
local SEARCHRESULT_TAG			= "SearchResult";
local FILTERED_SEARCHRESULT_TAG = "FilteredSearchResult";


function AtlasLootAdvancedSearch:PresentSearchResults( refreshBrowserParms, dataSource, debugTimingTable )
--r_printf("AtlasLootAdvancedSearch:ApplyFilter  dataSource:%s   filter enabled:%s   refreshOri - 1:%s   2:%s   3:%s    4:%s", 
--	tostring(dataSource), tostring(ATLASLOOT_FILTER_ENABLE), 
--	tostring(AtlasLootItemsFrame.refreshOri[1]), tostring(AtlasLootItemsFrame.refreshOri[2]), tostring(AtlasLootItemsFrame.refreshOri[3]), tostring(AtlasLootItemsFrame.refreshOri[4]));

	-- first, figure out which page we're on
	--@TODO: hmm, this no longer seems to getting used in this function; what was I planning to use it for, hmmm?
	if AtlasLootItemsFrame.refresh then
		if not dataSource then 
			--(for now, let's use 1)
			dataSource = AtlasLootItemsFrame.refresh[1] .. "1";
		end
		if not refreshBrowserParms then
			refreshBrowserParms = AtlasLootItemsFrame.refresh;
		end
	else
		--BOO....hard-coded references are simply asking to be broken...
		local anchorFrame = { "TOPLEFT", "AtlasLootDefaultFrame_LootBackground", "TOPLEFT", "2", "-2" };
		local searchPageRefreshParameters = {
			SEARCHRESULT_TAG,				-- dataID
			SEARCHRESULT_TAG .. "Page1",	-- dataSource
			strformat(AL["Search Result: %s"], AtlasLootCharDB.LastSearchedText or ""),	-- bossID
			anchorFrame,					-- frame
		};
	end
	
	-- next, get the list of categorized items from that page
	local sourceDatabase = AtlasLootCharDB[SEARCHRESULT_TAG]
	
	if ATLASLOOT_FILTER_ENABLE then
		-- copy only the items which satisfy the filter from the search results list over to our filtered search results list
		AtlasLootCharDB[FILTERED_SEARCHRESULT_TAG] = self:GenerateFilteredLootTable(sourceDatabase);
		
		-- from here on out, we're going to be populating everything from our filtered list of search results, instead of the
		-- unfiltered search results.
		sourceDatabase = AtlasLootCharDB[FILTERED_SEARCHRESULT_TAG];
		
	else
		if AtlasLootCharDB[FILTERED_SEARCHRESULT_TAG] then
			wipe(AtlasLootCharDB[FILTERED_SEARCHRESULT_TAG]);
		end
	end

	-- at this point, the filtered search results list is simply a raw list of tables containing the items' data, so we'll
	-- need to reorganize those items into categories again so that we don't need to deal with the button-remapping headache
	-- that the original AtlasLoot filter code used.
	if debugTimingTable then debugprofilestart(); end
	alas_addon.CategorizedSearchResults = AtlasLoot_CategorizeWishList(sourceDatabase);
	if debugTimingTable then debugTimingTable["Categorization"] = debugprofilestop(); end
				
	-- notify searchers that we've finished sorting
	local searchers = self:GetSearchModulesForLootQuery();
	
	for idx, searcher in pairs(searchers) do
		if searcher and searcher.PostSortFunc then
			if type(searcher.PostSortFunc) == "function" then
				searcher:PostSortFunc();
			elseif type(searcher.PostSortFunc) == "string" and searcher.PostSortFunc ~= "" then
				local func = searcher[searcher.PostSortFunc];
				if func and type(func) == "function" then
					func(searcher);
				end
			end
		end
	end
	
	local refresh = AtlasLootItemsFrame.refresh;
	AtlasLoot_ShowItemsFrame(
		refreshBrowserParms[1],	-- dataID
		refreshBrowserParms[2],	-- dataSource
		refreshBrowserParms[3],	-- bossID
		refreshBrowserParms[4]	-- frame
	);

	if ATLASLOOT_FILTER_ENABLE then
		-- several places in the AtlasLoot code will check this value to see if we're currently viewing search results, so make
		-- sure the value is what that code expects.
		AtlasLootItemsFrame.refreshOri[1] = SEARCHRESULT_TAG;
	end
				
	-- AtlasLoot_ShowItemsFrame always hides the checkbox if we're viewing search results, so make it visible again
	AtlasLootFilterCheck:Show();
end

-- Given an array of loot item tables, create a copy of that array containing only the loot item tables which satisfy whatever
-- filters we currently have in place.
function AtlasLootAdvancedSearch:GenerateFilteredLootTable( lootTbl )
	local filteredLootTbl = {}

	if lootTbl then
		for itemIdx, itemTbl in pairs(lootTbl) do
			if type(itemTbl) == "table" then
				local hasRelevantFilter, passesFilters = false, true;
				
				-- determine which field in the item data has the encoded metadata (for search results, they're added as the sixth element,
				-- otherwise it's the fifth...there could be other special cases, too.....have to keep my eyes open
				local firstPotentialFieldIndex, lastPotentialFieldIndex = 5, 6;
				for currentFieldIndex = firstPotentialFieldIndex, lastPotentialFieldIndex do
					if	currentFieldIndex <= #itemTbl
					and	itemTbl[currentFieldIndex]
					and	type(itemTbl[currentFieldIndex]) == "string" then
						for nextCodedToken in string.gmatch(itemTbl[currentFieldIndex], "(%b##)") do
							local encodedMetadata = itemTbl[currentFieldIndex];

							local isAllowed, isRelevant = AtlasLootAdvancedFilter:IsItemAllowed(encodedMetadata);
							if isRelevant then
								hasRelevantFilter = true;
								passesFilters = passesFilters and isAllowed;
								
								if not passesFilters then
									break;
								end
							end
						end
						
						if not passesFilters then
							break;
						end
					end
				end
				
				if passesFilters and hasRelevantFilter then
					tinsert(filteredLootTbl, itemTbl);
					
					--[===[@debug@
					if not hasRelevantFilter then
						t_printf("!!!!!  NO RELEVANT FILTER TYPES FOUND FOR item %i....item probably isn't being scanned properly", itemIdx);
					end
					--@end-debug@]===]
				end
			end
		end
	else
		r_printf("FilterLootTable - no value specified for lootTbl.");
	end
	return filteredLootTbl;
end

function AtlasLootAdvancedSearch:ALAS_FilterEnableButton()
	-- make sure that we only execute our special logic if the user is viewing the search results page
	if AtlasLootItemsFrame.refresh and AtlasLootItemsFrame.refresh[1] == SEARCHRESULT_TAG then
		local dataID = AtlasLootItemsFrame.refreshOri[1];
		if ATLASLOOT_FILTER_ENABLE == true then
			ATLASLOOT_FILTER_ENABLE = false;
			
			self:PresentSearchResults(AtlasLootItemsFrame.refreshOri);
		else
			ATLASLOOT_FILTER_ENABLE = true
			self:PresentSearchResults(nil, AtlasLootItemsFrame.refreshOri[2]);
		end
	else
		-- otherwise, the user clicked the Filter button while looking at search results at some point in the past, but at this point
		-- he has clicked the Filter button while looking at some random loot page; just pass through to the default func
		self.hooks.AtlasLoot_FilterEnableButton();
	end
end


do
	AtlasLootAdvancedFilter = AdvancedFilter:new();
	AtlasLootAdvancedFilter:Populate();
end
