--[[------------------------------------------------------------------
--SousChef.lua
--Author: Wobin

inspired by ingeniousclown's Research Assistant

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

SousChef = {}
SousChef.Utility = {}
SousChef.Media = {}

local SousChef = SousChef
local u = SousChef.Utility

local LAM = LibStub:GetLibrary("LibAddonMenu-1.0")

local BACKPACK = ZO_PlayerInventoryBackpack
local BANK = ZO_PlayerBankBackpack
local GUILD_BANK = ZO_GuildBankBackpack

SousChef.Pantry = {}
SousChef.Cookbook = {}
SousChef.ReverseCookbook = {}
SousChef.settings = nil
SousChef.slotLines = {}
SousChef.hookedFunctions = {}
SousChef.hookedDataFunction = nil

local rowHandler = {}

local function AddRecipe(Cookbook, link)
	for _,v in pairs(Cookbook) do
		if v == link then return end
	end
	table.insert(Cookbook, link)
end

function SousChef.ParseRecipes()
	local lists = GetNumRecipeLists()
	for listIndex = 1, lists do
		local name, count = GetRecipeListInfo(listIndex)
		for recipeIndex = 1, count do
			if GetRecipeInfo(listIndex, recipeIndex) then
				-- Store the recipes known
				local recipeName = u.CleanString((GetRecipeResultItemInfo(listIndex, recipeIndex)))
                SousChef.Cookbook[recipeName] = true
				if not SousChef.settings.Cookbook[recipeName] then
                    SousChef.settings.Cookbook[recipeName] = {}
				end
                SousChef.settings.Cookbook[recipeName][GetUnitName("player")] = true
				local _, _, ingredientCount, level, _, specialType = GetRecipeInfo(listIndex, recipeIndex)
				for ingredientIndex = 1, ingredientCount do
					local link = u.GetItemID(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex, LINK_STYLE_NORMAL))
					-- Store the fact that the ingredient is used
                    if ingredientIndex < 3 or not SousChef.settings.showSpecialIngredients then
                        SousChef.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0)
                        SousChef.settings.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0)
                    else
                        SousChef.Pantry[link] = specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8
                        SousChef.settings.Pantry[link] = specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8
                    end
					-- Store the recipe it's used in
					if not SousChef.ReverseCookbook[link] then SousChef.ReverseCookbook[link] = {} end
					AddRecipe(SousChef.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS)))
					-- Store the global reference
					if not SousChef.settings.ReverseCookbook[link] then SousChef.settings.ReverseCookbook[link] = {} end
					AddRecipe(SousChef.settings.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS)))
				end
			end

		end
	end
	ZO_ScrollList_RefreshVisible(BACKPACK)
	ZO_ScrollList_RefreshVisible(BANK)
	ZO_ScrollList_RefreshVisible(GUILD_BANK)

end

local function SousChefCreateSettings()
    d("Creating menu")
	local panel = LAM:CreateControlPanel("SousChefMenu", "Sous Chef")

	LAM:AddHeader(panel, "SousChef_General", "Settings")

    LAM:AddCheckbox(panel, "processRecipes", "Have Sous Chef check for recipes", "Non English clients may want to untick this if the experimental matching isn't sufficient",
                        function() return SousChef.settings.processRecipes end,
                        function(value)
                            SousChef.settings.processRecipes = not SousChef.settings.processRecipes
                            if SousChef.settings.processRecipes then
                                ZO_Options_SetOptionInactive(markLearnt)
                                ZO_Options_SetOptionInactive(markAltKnows)
                            else
                                ZO_Options_SetOptionActive(markLearnt)
                                ZO_Options_SetOptionActive(markAltKnows)
                            end
                        end)
  	LAM:AddDropdown(panel, "markLearnt", "Mark if recipes are ",
						"How do you want Sous Chef to indicate your knowledge of a recipe?",
						{"known", "unknown"}, function() return SousChef.settings.checkKnown end,
						function(valueString) SousChef.settings.checkKnown = valueString end)
	LAM:AddCheckbox(panel, "markAltKnows", "Alternate Character Check", "Indicate if an alt knows the recipe on unknown recipes. Will only work if the above setting is set to 'unknown'",
						function() return SousChef.settings.markAlt end,
						function(value) SousChef.settings.markAlt = not SousChef.settings.markAlt end)
	LAM:AddCheckbox(panel, "showAltKnows", "Alternate Character Recipe Knowledge", "Show rank indicators on alts for all recipe knowledge of all alternate characters",
						function() return SousChef.settings.showAltKnowledge end,
						function(value) SousChef.settings.showAltKnowledge = not SousChef.settings.showAltKnowledge end)
	LAM:AddCheckbox(panel, "useBold", "Use bolder icons", "Swap out rank icon to a more flat display",
						function() return SousChef.settings.boldIcon end,
						function(value) SousChef.settings.boldIcon = not SousChef.settings.boldIcon end)
	LAM:AddCheckbox(panel, "specialIngredients", "Show special ingredients", "Indicate if an ingredient is considered a Spice/Flavour rather than the tier of the max ranked recipe you have that uses it",
						function() return SousChef.settings.showSpecialIngredients end,
						function(value) SousChef.settings.showSpecialIngredients = not SousChef.settings.showSpecialIngredients SousChef.ParseRecipes() end)
	LAM:AddColorPicker(panel, "setColour", "Indicator colour",
						"Allows you to set the colour of the indicator",
						function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end,
						function(r,g,b) SousChef.settings.colour[1] = r; SousChef.settings.colour[2] = g; SousChef.settings.colour[3] = b end)
    LAM:AddCheckbox(panel, "experimental", "Use the experimental recipe matcher", [[Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better.

    (NOTE: please file a bug report if you find recipes that don't match the results exactly, with the recipe/result names and/or screenshots so I can update this dictionary)]],
                        function() return SousChef.settings.experimentalMatch end,
                        function(value) SousChef.settings.experimentalMatch = not SousChef.settings.experimentalMatch end)
end



local function SousChef_Loaded(eventCode, addOnName)

	if(addOnName ~= "SousChef") then
        return
    end

	local defaults = {
		watching = true,
		checkKnown = "unknown",
		markAlt = false,
		colour = {1, 1, 1},
		Cookbook = {},
		Pantry = {},
		ReverseCookbook = {},
		showAltKnowledge = false,
		boldIcon = false,
        experimentalMatch = false,
        processRecipes = true,
        showSpecialIngredients = false,
        ignoredRecipes = {}
	}

    SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 8, nil, defaults)

	local function tablelength(T)
		local count = 0
		for _ in pairs(T) do count = count + 1 end
		return count
	end

	SLASH_COMMANDS['/scstats'] = function()
		d("Number of recipes known: ".. tablelength(SousChef.settings.Cookbook))
		d("Number of ingredients tracked: "..tablelength(SousChef.settings.Pantry))
	end

	SousChefCreateSettings()

	zo_callLater(SousChef.ParseRecipes, 1000)

	SLASH_COMMANDS['/sciadd'] = SousChef.AddRecipeToIgnoreList
	SLASH_COMMANDS['/sciremove'] = SousChef.RemoveRecipeFromIgnoreList
	SLASH_COMMANDS['/scilist'] = SousChef.ListIgnoredRecipes

	-- Now we want to hook into the function that sets the details on the inventory slot
	zo_callLater(SousChef.HookEvents, 3000)
end


function SousChef.HookEvents()
	EVENT_MANAGER:RegisterForEvent("SousChefTrading", EVENT_TRADING_HOUSE_RESPONSE_RECEIVED, SousChef.HookTrading)
	EVENT_MANAGER:RegisterForEvent("SousChefLearnt", EVENT_RECIPE_LEARNED, SousChef.ParseRecipes)
    EVENT_MANAGER:RegisterForEvent("SousChefProvi", EVENT_CRAFTING_STATION_INTERACT, SousChef.HookRecipeTree)
    SousChef.HookInventory()
end

EVENT_MANAGER:RegisterForEvent("SousChefLoaded", EVENT_ADD_ON_LOADED, SousChef_Loaded)