-----------------------------------------------------------------------
-- AddOn namespace.
-----------------------------------------------------------------------
local ADDON_NAME, private = ...

local RSLoot = private.NewLib("RareScannerLoot")

-- RareScanner database libraries
local RSConfigDB = private.ImportLib("RareScannerConfigDB")
local RSLootDB = private.ImportLib("RareScannerLootDB")
local RSCollectionsDB = private.ImportLib("RareScannerCollectionsDB")

-- RareScanner general libraries
local RSLogger = private.ImportLib("RareScannerLogger")
local RSConstants = private.ImportLib("RareScannerConstants")
local RSUtils = private.ImportLib("RareScannerUtils")
local RSTooltipScanners = private.ImportLib("RareScannerTooltipScanners")

---============================================================================
-- Filters to apply to the loot displayed under the main button and the worldmap
---============================================================================

local conduits = {}
local function IsConduitAlreadyCollected(itemID)
	if (not itemID) then
		return false;
	end
	
	-- load collected conduits the first time
	if (next(conduits) == nil) then
		for conduitType = 0, 3 do
			for _, collectionData in pairs(C_Soulbinds.GetConduitCollection(conduitType)) do
		        if (collectionData) then
					conduits[collectionData.conduitItemID] = true
				end
		    end
	    end
	elseif (conduits[itemID]) then
		return true
	end
	
	return false;
end

local function IsEquipable(itemClassID, itemSubClassID, itemEquipLoc)
	local _, _, classIndex = UnitClass("player");
	local isEquipable = false
	for categoryID, subcategories in pairs(private.CLASS_PROFICIENCIES[classIndex]) do
		if (categoryID == itemClassID and RSUtils.Contains(subcategories, itemSubClassID)) then
			isEquipable = true
			break
		end
	end
	-- check if cloth and not cloak
	if (not isEquipable and itemClassID == Enum.ItemClass.Armor and itemSubClassID == Enum.ItemArmorSubclass.Cloth and itemEquipLoc == "INVTYPE_CLOAK") then --check if its cloth and not cloak
		return true
	end

	return isEquipable
end

local function IsToy(itemLink, itemID)
	if (RSLootDB.IsToy(itemID)) then
		return true
	elseif (RSTooltipScanners.ScanLoot(itemLink, TOY)) then
		RSLootDB.SetItemAsToy(itemID)
		return true
	end
end

local function IsFilteredByCategory(itemLink, itemID, itemClassID, itemSubClassID)
	-- If filtered by category
	if (RSConfigDB.GetLootFilterByCategory(itemClassID, itemSubClassID) == false) then
		-- We ignore toys from this filter because they are scattered all around
		if (IsToy(itemLink, itemID)) then
			return false
		end
		
		return true
	end
	
	return false
end

function RSLoot.IsFiltered(itemID, itemLink, itemRarity, itemEquipLoc, itemClassID, itemSubClassID)
	-- Quality filter
	if (itemRarity < tonumber(RSConfigDB.GetLootFilterMinQuality())) then
		RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por su calidad.", itemID))
		return true
	end

	-- Category filter
	if (IsFilteredByCategory(itemLink, itemID, itemClassID, itemSubClassID)) then
		RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por su categoria.", itemID))
		return true
	end
	
	-- Individual filter
	if (RSConfigDB.IsItemFiltered(itemID)) then
		RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado individualmente.", itemID))
		return true
	end

	-- Completed quests
	if (RSConfigDB.IsFilteringLootByCompletedQuest() and (itemClassID == Enum.ItemClass.Questitem or (itemClassID == Enum.ItemClass.Consumable and itemSubClassID == 8))) then --quest item
		local questIDs = RSLootDB.GetAssociatedQuestIDs(itemID)
		if (questIDs) then
			local filtered = false
			for i, questID in ipairs(questIDs) do
				if (C_QuestLog.IsQuestFlaggedCompleted(questID) or not C_TaskQuest.IsActive(questID)) then
					filtered = true
				else
					filtered = false
					break
				end
			end

			if (filtered) then
				RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por su mision asociada.", itemID))
				return true;
			end
		end
	end

	-- Equipable filter
	if (RSConfigDB.IsFilteringLootByNotEquipableItems() and (itemClassID == Enum.ItemClass.Weapon or itemClassID == Enum.ItemClass.Armor)) then --weapons or armor
		if (not IsEquipable(itemClassID, itemSubClassID, itemEquipLoc)) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por no ser equipable.", itemID))
			return true;
		end
	end

	-- Character class filter
	if (RSConfigDB.IsFilteringLootByNotMatchingClass() and RSTooltipScanners.ScanLoot(itemLink, string.gsub(ITEM_CLASSES_ALLOWED, ": %%s", ""))) then
		local localizedClass, _, _ = UnitClass("player")
		if (not RSTooltipScanners.ScanLoot(itemLink, localizedClass)) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por clase.", itemID))
			return true;
		end
	end

	-- Character faction filter
	if (RSConfigDB.IsFilteringLootByNotMatchingFaction()) then
		local _, localizedFaction = UnitFactionGroup("player")
		if ((RSTooltipScanners.ScanLoot(itemLink, ITEM_REQ_ALLIANCE) and localizedFaction ~= FACTION_ALLIANCE) or (RSTooltipScanners.ScanLoot(itemLink, ITEM_REQ_HORDE) and localizedFaction ~= FACTION_HORDE)) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por facción.", itemID))
			return true;
		end
	end

	-- Transmog filter
	if (RSConfigDB.IsFilteringLootByTransmog() and (itemClassID == Enum.ItemClass.Weapon or (itemClassID == Enum.ItemClass.Armor and itemSubClassID ~= Enum.ItemArmorSubclass.Generic))) then --weapons or armor (not rings, necks, etc.)
		-- First check in the internal collections database
		local isNotcollectedAppearance = RSCollectionsDB.IsNotcollectedAppearance(itemID)
		if (isNotcollectedAppearance ~= nil and isNotcollectedAppearance == false) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por no ser transfigurable (Collections check).", itemID))
			return true
		-- Otherwise use other methods
		elseif (not isNotcollectedAppearance) then
			if (not IsEquipable(itemClassID, itemSubClassID, itemEquipLoc)) then
				RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por no ser equipable (Transmog check).", itemID))
				return true
			elseif (C_TransmogCollection.PlayerHasTransmog(itemID)) then
				RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por ya tenerlo (Transmog check).", itemID))
				return true
			elseif (not RSTooltipScanners.ScanLoot(itemLink, TRANSMOGRIFY_TOOLTIP_APPEARANCE_UNKNOWN)) then
				RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por no ser transfigurable (Transmog check).", itemID))
				return true
			end
		end
	end

	-- Collection mount filter
	if (RSConfigDB.IsFilteringByCollected() and itemClassID == Enum.ItemClass.Miscellaneous and itemSubClassID == Enum.ItemMiscellaneousSubclass.Mount) then --mount
		if (RSTooltipScanners.ScanLoot(itemLink, ITEM_SPELL_KNOWN)) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por haberlo conseguido ya (montura).", itemID))
			return true
		end
	end

	-- Collection pet filter
	-- Unique pets
	if (RSConfigDB.IsFilteringByCollected() and itemClassID == Enum.ItemClass.Miscellaneous and itemSubClassID == Enum.ItemMiscellaneousSubclass.CompanionPet) then --pets
		if (RSTooltipScanners.ScanLoot(itemLink, format(ITEM_PET_KNOWN, "1", "1")) or RSTooltipScanners.ScanLoot(itemLink, format(ITEM_PET_KNOWN, "3", "3"))) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por haberlo conseguido ya (mascota).", itemID))
			return true
		end
	end

	-- Collection toy filter
	-- Toys have different categories under miscelanious
	if (RSConfigDB.IsFilteringByCollected()) then
		if (IsToy(itemLink, itemID) and RSTooltipScanners.ScanLoot(itemLink, ITEM_SPELL_KNOWN)) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por haberlo conseguido ya (juguete).", itemID))
			return true
		end
	end
	
	-- Anima items filter
	if (RSConfigDB.IsFilteringAnimaItems()) then
		if (RSTooltipScanners.ScanLoot(itemLink, WORLD_QUEST_REWARD_FILTERS_ANIMA)) then
			RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por ser un objeto que da ánima.", itemID))
			return true
		end
	end
	
	-- Conduits filter
	if (RSConfigDB.IsFilteringConduitItems()) then
		if (C_Soulbinds.IsItemConduitByItemInfo(itemLink)) then
			-- First check if collected already
			if (IsConduitAlreadyCollected(itemID)) then
				RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por haberlo conseguido ya (conducto).", itemID))
				return true
			-- Check if usable
			else
				local conduitInfo = RSLootDB.GetConduitInfo(itemID)
				if (conduitInfo and not C_SpecializationInfo.MatchesCurrentSpecSet(conduitInfo.specSetID)) then
					RSLogger:PrintDebugMessageItemID(itemID, string.format("Item [%s]. Filtrado por no poder usarlo por ser de otra clase (conducto).", itemID))
					return true
				end
			end
		end
	end
	
	return false
end
