--## Author: S1L3NTW0LF74  ## Version: 1.1

local filterType = ALL

-- Create dropdown menu
local dropdown = CreateFrame("Frame", "VendorFilterDropdown", MerchantFrame, "UIDropDownMenuTemplate")
dropdown:SetPoint("TOPLEFT", MerchantFrame, "TOPLEFT", 30, -30)
UIDropDownMenu_SetWidth(dropdown, 90)
UIDropDownMenu_SetText(dropdown, ALL)

local function UpdateDropdownLabel()
    --local icon = "|TInterface\\COMMON\\UI-Searchbox-Icon:16:16:0:0|t"
    local label = filterType or ALL
    --dropdown.Text:SetText(icon .. " " .. label)
    --if label == ITEM_COSMETIC  then label = "Cosmetics" end
    dropdown.Text:SetText(label)
end

local function SetFilter(self, arg1)
    filterType = arg1
    UpdateDropdownLabel()
    MerchantFrame_Update()
end

UIDropDownMenu_Initialize(dropdown, function(self, level)
    local info = UIDropDownMenu_CreateInfo()

    label = ALL
    info.text = label
    info.arg1 = label
    info.func = SetFilter
    info.checked = (filterType == label)
    UIDropDownMenu_AddButton(info)

    --[[ Spacer line between sections
    local info = UIDropDownMenu_CreateInfo()
    info.text = " " -- blank line
    info.notCheckable = true
    info.disabled = true
    UIDropDownMenu_AddButton(info)]]

    -- Section heading (acts like a separator)
    info = UIDropDownMenu_CreateInfo()
    info.text = COLLECTIONS   --"--Collectibles--"
    info.isTitle = true
    info.notCheckable = true
    info.disabled = true
    UIDropDownMenu_AddButton(info)


    info = UIDropDownMenu_CreateInfo()
    for _, label in ipairs({ MOUNTS, PETS, TOY, ITEM_COSMETIC  }) do
        info.text = label
        info.arg1 = label
        info.func = SetFilter
        info.checked = (filterType == label)
        UIDropDownMenu_AddButton(info)
    end

    --[[ Spacer line between sections
    local info = UIDropDownMenu_CreateInfo()
    info.text = " " -- blank line
    info.notCheckable = true
    info.disabled = true
    UIDropDownMenu_AddButton(info)]]

    -- Section heading (acts like a separator)
    info = UIDropDownMenu_CreateInfo()
    info.text = ORDER_HALL_EQUIPMENT_SLOTS    --"--Equipable Slots--"
    info.isTitle = true
    info.notCheckable = true
    info.disabled = true
    UIDropDownMenu_AddButton(info)

    info = UIDropDownMenu_CreateInfo()
    for _, label in ipairs({ HEADSLOT , NECKSLOT, SHOULDERSLOT, CHESTSLOT , WAISTSLOT, LEGSSLOT, FEETSLOT, WRISTSLOT, HANDSSLOT, FINGER0SLOT, TRINKET0SLOT, WEAPON  }) do
        info.text = label
        info.arg1 = label
        info.func = SetFilter
        info.checked = (filterType == label)
        UIDropDownMenu_AddButton(info)
    end

end)



local scanner = CreateFrame("GameTooltip", "VendorFilterScanner", nil, "GameTooltipTemplate")
scanner:SetOwner(WorldFrame, "ANCHOR_NONE")

local function IsAlreadyKnown(itemLink)
    scanner:ClearLines()
    scanner:SetHyperlink(itemLink)

    for i = 1, scanner:NumLines() do
        local line = _G["VendorFilterScannerTextLeft" .. i]
        if line and line:GetText() then
            local text = line:GetText()

            -- Toys, spells, etc.
            if text == ITEM_SPELL_KNOWN then
                return true
            end

            if text == "Already known" then
                return true
            end

            -- Pets: must be at least 1 collected
            local collectedCount = text:match("^Collected %((%d+)/%d+%)$")
            if collectedCount and tonumber(collectedCount) > 0 then
                return true
            end
        end
    end

    return false
end

local function IsEnsemble(itemLink)
    if not itemLink then return false end

    local itemType, itemSubType = select(6, GetItemInfo(itemLink))
    --if itemType ~= "Container" then return false end

    -- Scan tooltip for the word "Ensemble"
    scanner:ClearLines()
    scanner:SetHyperlink(itemLink)

    for i = 1, scanner:NumLines() do
        local line = _G["VendorFilterScannerTextLeft" .. i]
        if line and line:GetText() and line:GetText():find("Ensemble") then
            return true
        end
        if line and line:GetText() and line:GetText():find("Collect the appearances") then
            return true
        end
    end

    return false
end



-- Mount detection
local function IsMount(itemLink)
    local itemType, itemSubType = select(6, GetItemInfo(itemLink))
    return itemType == "Miscellaneous" and itemSubType == "Mount"
end

-- Pet detection
local function IsPet(itemLink)
    local itemID = GetItemInfoInstant(itemLink)
    if itemID then
        local speciesID = C_PetJournal.GetPetInfoByItemID(itemID)
        return speciesID ~= nil
    end
    return false
end

-- Toy detection
local function IsToy(itemLink)
    local itemID = GetItemInfoInstant(itemLink)
    if itemID then
        local toyName = C_ToyBox.GetToyInfo(itemID)
        return toyName ~= nil
    end
    return false
end

-- Cosmetic detection
local function IsCosmetic(itemLink)
    local itemType, itemSubType = select(6, GetItemInfo(itemLink))
    return itemType == "Armor" and itemSubType == "Cosmetic"
end

-- Ensemble detection
local function IsEnsembleItem(itemLink)
    return IsEnsemble(itemLink)
end

-- Head gear detection
local function IsHead(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_HEAD"
end

-- Neck gear detection
local function IsNeck(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_NECK"
end

-- Chest gear detection
local function IsChest(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_CHEST"
end

-- Shoulder gear detection
local function IsShoulder(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_SHOULDER"
end

-- Legs gear detection
local function IsLegs(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_LEGS"
end

-- Feet gear detection
local function IsFeet(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_FEET"
end

-- Hands gear detection
local function IsHands(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_HAND"
end

-- Waist gear detection
local function IsWaist(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_WAIST"
end

-- Wrist gear detection
local function IsWrist(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_WRIST"
end

-- Finger gear detection
local function IsFinger(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_FINGER"
end

-- Trinket gear detection
local function IsTrinket(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    return equipLoc == "INVTYPE_TRINKET"
end

-- Any cosmetic detection (either cosmetic armor or ensemble)
local function IsAnyCosmetic(itemLink)
    return IsCosmetic(itemLink) or IsEnsemble(itemLink)
end

-- Weapon detection (1H, 2H, Ranged, Offhand, Shield, Holdable)
local function IsWeapon(itemLink)
    local equipLoc = select(9, GetItemInfo(itemLink))
    local weaponTypes = {
        INVTYPE_WEAPON = true,
        INVTYPE_2HWEAPON = true,
        INVTYPE_WEAPONMAINHAND = true,
        INVTYPE_WEAPONOFFHAND = true,
        INVTYPE_RANGED = true,
        INVTYPE_SHIELD = true,
        INVTYPE_HOLDABLE = true,
    }
    return weaponTypes[equipLoc] or false
end

-- Hook vendor update
hooksecurefunc("MerchantFrame_Update", function()
    C_Timer.After(0.05, function()

        for i = 1, MERCHANT_ITEMS_PER_PAGE do
            local button = _G["MerchantItem" .. i]
            local index = i + (MerchantFrame.page - 1) * MERCHANT_ITEMS_PER_PAGE
            local itemLink = GetMerchantItemLink(index)

            if button and itemLink then

                local matches = true
                if filterType == MOUNTS then
                    matches = IsMount(itemLink)
                elseif filterType == PETS then
                    matches = IsPet(itemLink)
                elseif filterType == TOY then
                    matches = IsToy(itemLink)
                elseif filterType == ITEM_COSMETIC then
                    matches = IsAnyCosmetic(itemLink)
                elseif filterType == HEADSLOT then
                    matches = IsHead(itemLink)
                elseif filterType == CHESTSLOT then
                    matches = IsChest(itemLink)
                elseif filterType == SHOULDERSLOT then
                    matches = IsShoulder(itemLink)			
                elseif filterType == WAISTSLOT then
                    matches = IsWaist(itemLink)			
                elseif filterType == HANDSSLOT then
                    matches = IsHands(itemLink)			
                elseif filterType == LEGSSLOT then
                    matches = IsLegs(itemLink)			
                elseif filterType == FEETSLOT then
                    matches = IsFeet(itemLink)		
                elseif filterType == NECKSLOT then
                    matches = IsNeck(itemLink)
                elseif filterType == WRISTSLOT then
                    matches = IsWrist(itemLink)
                elseif filterType == FINGER0SLOT then
                    matches = IsFinger(itemLink)  
                elseif filterType == TRINKET0SLOT then
                    matches = IsTrinket(itemLink)  
                elseif filterType == WEAPON then
                    matches = IsWeapon(itemLink)
                end

                button:Show()

                -- Icon and button alpha
                if matches then
                    local known = IsAlreadyKnown(itemLink)

                    if (known) then
                        button:SetAlpha(0.1)
                    else
                        button:SetAlpha(1.0)
                    end

                    if button.icon then
                        button.icon:SetDesaturated(known)
                    end

                else
                    button:SetAlpha(0.1)
                    if button.icon then
                        button.icon:SetDesaturated(true)
                    end
                end
            end
        end
    end)
end)


local f = CreateFrame("Frame")
f:RegisterEvent("GOSSIP_CLOSED")
f:SetScript("OnEvent", function()
    if MerchantFrame:IsShown() then
        MerchantFrame_Update()
    end
end)