local SousChef = SousChef
local u = SousChef.Utility
local m = SousChef.Media

function SousChef:UpdateProvisioningTable()
    self.qualityCheckBox = SousChef_ControllerOnlyQuality

    local function OnFilterChanged()
        self.settings.qualityChecked = ZO_CheckButton_IsChecked(self.qualityCheckBox)
        PROVISIONER:DirtyRecipeTree()
    end
    self.qualityCheckBox:SetParent(ZO_ProvisionerTopLevel)
    ZO_CheckButton_SetLabelText(self.qualityCheckBox, "Quality")
    ZO_CheckButton_SetToggleFunction(self.qualityCheckBox, OnFilterChanged)
    ZO_CraftingUtils_ConnectCheckBoxToCraftingProcess(self.qualityCheckBox)
    ZO_CheckButton_SetCheckState(self.qualityCheckBox, self.settings.qualityChecked)

    -- Nudge to the left
    ZO_ProvisionerTopLevelHaveSkills:ClearAnchors()
    ZO_ProvisionerTopLevelHaveSkills:SetAnchor( LEFT, ZO_ProvisionerTopLevelHaveIngredients, RIGHT, 180 )

    SousChef.filter = PROVISIONER.DoesRecipePassFilter

    PROVISIONER.DoesRecipePassFilter =
        function(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq)
            if ZO_CheckButton_IsChecked(self.qualityCheckBox) and qualityReq < 2 then return false end
            return SousChef.filter(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq)
        end
end


SousChef.ProvisioningButton=
{{
    name = "Mark Recipe", -- or function that returns a name
    keybind = "SC_MARK_RECIPE",
    control = self,
    callback = function(descriptor) SousChef:MarkRecipe() end,
    visible = function(descriptor) return PROVISIONER:GetSelectedRecipeIndex() ~= nil end,
    alignment = KEYBIND_STRIP_ALIGN_RIGHT,
}}

local bGroup = SousChef.ProvisioningButton

function SousChef:HookRecipeTreeFunction()
    if not KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then
        KEYBIND_STRIP:AddKeybindButtonGroup(bGroup)
    else
        KEYBIND_STRIP:UpdateKeybindButtonGroup(bGroup)
    end

    -- Hook the provisioning panel
    if not SousChef.hookedProvisioningFunction then
        local ref = PROVISIONER.recipeTree.templateInfo.ZO_ProvisionerNavigationEntry
        if ref then
            SousChef.hookedProvisioningFunction = ref.setupFunction
            ref.setupFunction =
            function(...)
                local node, control, data, open, userRequested, enabled = ...
                SousChef.hookedProvisioningFunction(...)
                local link = GetRecipeResultItemLink(data.recipeListIndex, SousChef.recipeLookup[data.recipeListIndex][data.recipeIndex], LINK_STYLE_BRACKETS)
                if link then
                    SousChef:AddNotifier(control, SousChef.settings.shoppingList[zo_strformat(SI_TOOLTIP_ITEM_NAME, link)])
                end
            end
        end
    end
    PROVISIONER:DirtyRecipeTree()
end

function SousChef:getMarkedIcon(row)
    local rankIcon = SousChef.slotLines[row:GetName()]
    if(not rankIcon) then
        rankIcon =  WINDOW_MANAGER:CreateControl(row:GetName() .. "SousChef", row, CT_TEXTURE)
        SousChef.slotLines[row:GetName()] = rankIcon
        rankIcon:SetTexture(m.CANLEARN)
        rankIcon:SetDimensions(20, 20)
        rankIcon:SetAnchor(RIGHT, row, LEFT, -10)
        rankIcon:SetMouseEnabled(true)
        rankIcon:SetHandler("OnMouseEnter", function()
                                                InitializeTooltip(InformationTooltip, rankIcon, RIGHT, -15, 0)
                                                InformationTooltip:AddLine("Shopping List")
                                            end)
        rankIcon:SetHandler("OnMouseExit", function()
                                                ClearTooltip(InformationTooltip)
                                            end)
    end
    return rankIcon
end

function SousChef:AddNotifier(control, marked)
    local icon = self:getMarkedIcon(control)
    if marked then
        icon:SetHidden(false)
    else
        icon:SetHidden(true)
    end
end

function SousChef:IsOnShoppingList(id)
    for i,v in ipairs(SousChef.settings.ReverseCookbook[id]) do
        if SousChef.settings.shoppingList[v] then return true end
    end
    return false
end

function SousChef:MarkRecipe()
    local link = GetRecipeResultItemLink(PROVISIONER:GetSelectedRecipeListIndex(), PROVISIONER:GetSelectedRecipeIndex(), LINK_STYLE_BRACKETS)
    SousChef.settings.shoppingList[zo_strformat(SI_TOOLTIP_ITEM_NAME, link)] = not SousChef.settings.shoppingList[zo_strformat(SI_TOOLTIP_ITEM_NAME, link)]
    PROVISIONER:DirtyRecipeTree()
end

function SousChef:HookRecipeTree(...)
    local eventId, craftingTable = ...
    if craftingTable ~= CRAFTING_TYPE_PROVISIONING then return end
    zo_callLater(function() SousChef:HookRecipeTreeFunction() end, 1000)
end

function SousChef:UnhookRecipeTree()
    if KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then
        KEYBIND_STRIP:RemoveKeybindButtonGroup(bGroup)
    end
end

function SousChef:HookGetRecipeInfo()
    SousChef.GetRecipeInfo = GetRecipeInfo
    GetRecipeInfo =
        function(recipeListIndex, recipeIndex)
            local val = SousChef.recipeIndex[recipeListIndex][recipeIndex]
            return val.known, val.name, val.ingredients, val.levelReq, val.quality, val.specialIngType
        end

    SousChef.GetSelectedRecipeIndex = PROVISIONER.GetSelectedRecipeIndex
    PROVISIONER.GetSelectedRecipeIndex =
        function()
            return SousChef.recipeLookup[PROVISIONER:GetSelectedRecipeListIndex()][SousChef.GetSelectedRecipeIndex(PROVISIONER)]
        end
end

local function SortRecipe(a, b)
    if a.levelReq == b.levelReq then
        if a.quality == b.quality then
            if a.name == b.name then
                return a.index < b.index
            end
            return a.name < b.name
        end
        return a.quality < b.quality
    end
    return a.levelReq < b.levelReq
end

function SousChef:ResortRecipes()
    SousChef.recipeIndex = {}
    SousChef.recipeLookup = {}

    for recipeListIndex = 1, GetNumRecipeLists() do
        local recipeListName, numRecipes = GetRecipeListInfo(recipeListIndex)
        SousChef.recipeIndex[recipeListIndex] = {}
        SousChef.recipeLookup[recipeListIndex] = {}
        for recipeIndex = 1, numRecipes do
            local known, recipeName, numIngredients, provisionerLevelReq, qualityReq, specialIngredientType = SousChef.GetRecipeInfo(recipeListIndex, recipeIndex)
            table.insert(SousChef.recipeIndex[recipeListIndex], {index = recipeIndex, known = known, name = recipeName, ingredients = numIngredients, levelReq = provisionerLevelReq, quality = qualityReq, specialIngType = specialIngredientType})
        end
        table.sort(SousChef.recipeIndex[recipeListIndex], SortRecipe)
        for i,v in ipairs(SousChef.recipeIndex[recipeListIndex]) do
            SousChef.recipeLookup[recipeListIndex][i] = v.index
        end
    end
end