local _G = getfenv(0)
local tonumber = _G.tonumber
local strmatch = _G.string.match
local strsub = _G.string.sub
local tinsert = _G.table.insert
local tremove = _G.table.remove
local GetInventoryItemLink = _G.GetInventoryItemLink
local IsAltKeyDown = _G.IsAltKeyDown
local IsControlKeyDown = _G.IsControlKeyDown
local IsShiftKeyDown = _G.IsShiftKeyDown
local IsModifierKeyDown = _G.IsModifierKeyDown
local PlaySound = _G.PlaySound

local function GetItemID(link)
	local itemID = strmatch(link, "item:(%d+):")
	local enchantID = strmatch(link, "enchant:(%d+)")
	if itemID then
		return tonumber(itemID)
	elseif enchantID then
		return -tonumber(enchantID)
	else
		return nil
	end
end

local function updateGUI()
	if BlueItemInfo2.GUI and BlueItemInfo2.GUI:IsVisible() and strsub(BlueItemInfo2DB.category, 1, 1) then
		BlueItemInfo2:SetCategory()
	end
end

function BlueItemInfo2:InitFavorite()
	self:CreateFavoriteItemTable()
	self:HookOtherAddons()
end

function BlueItemInfo2:CreateFavoriteItemTable(order)
	if self.data.items then
		local fitem = BlueItemInfo2Char.favorite
		if order then
			local code = "A"..order.."0"
			local i = order + 1
			self.data.items[code] = nil
			for j = 1, #(fitem[i]) do
				self.data.items[code] = self.data.items[code] and (self.data.items[code].."/"..fitem[i][j]) or fitem[i][j]
			end
		else
			local code
			for i = 1, 5 do
				code = "A"..(i - 1).."0"
				self.data.items[code] = nil
				for j = 1, #(fitem[i]) do
					self.data.items[code] = self.data.items[code] and (self.data.items[code].."/"..fitem[i][j]) or fitem[i][j]
				end
			end
		end
	end
end

local hook = {}
local hookScript = {}
local dummyFunc = function() end

local function HookScript(method, script, func)
	hookScript[method] = hookScript[method] or {}
	hookScript[method][script] = method:GetScript(script) or dummyFunc
	method:SetScript(script, func)
end

local function Hook(method, funcName, newFunc)
	if method and funcName and newFunc then
		hook[method] = 	hook[method] or {}
		hook[method][funcName] = method[funcName]
		method[funcName] = newFunc
	else
		newFunc = funcName
		funcName = method
		hook[funcName] = _G[funcName]
		_G[funcName] = newFunc
	end

end

function BlueItemInfo2:HookOtherAddons()
	local slotNames = { "Head", "Neck", "Shoulder", "Back", "Chest", "Shirt", "Tabard", "Wrist", "Hands", "Waist", "Legs", "Feet", "Finger0", "Finger1", "Trinket0", "Trinket1", "MainHand", "SecondaryHand", "Ranged" }
	-- Examiner
	if Examiner then
		for i = 1, #(slotNames) do
			local f = _G["ExaminerItemButton"..slotNames[i].."Slot"]
			if f then
				HookScript(f, "OnClick", function(frame, button)
					if frame.link then
						local id = GetItemID(frame.link)
						if IsAltKeyDown() then
							self:AddFavoriteItem(id)
						elseif IsControlKeyDown() and IsShiftKeyDown() then
							self:AddMemo(id)
						elseif not IsModifierKeyDown() then
							ChatFrame_OnHyperlinkShow(frame.link, frame.link)
						else
							hookScript[frame].OnClick(frame, button)
						end
					else
						hookScript[frame].OnClick(frame, button)
					end
				end)
			end
		end
	-- SuperInspect
	elseif SuperInspect_InspectPaperDollItemSlotButton_OnClick then
		Hook("SuperInspect_InspectPaperDollItemSlotButton_OnClick", function(button, ignoreModifiers)
			local id = GetItemID(this.link or GetInventoryItemLink("target", this:GetID()))
			if IsAltKeyDown() then
				self:AddFavoriteItem(id)
			elseif IsControlKeyDown() and IsShiftKeyDown() then
				self:AddMemo(id)
			else
				hook.SuperInspect_InspectPaperDollItemSlotButton_OnClick(button, ignoreModifiers)
			end
		end)
	-- BlizzardInspect
	else
		local function InspectOnClick()
			local link = GetInventoryItemLink(InspectFrame.unit, this:GetID())
			local id = GetItemID(link)
			if IsAltKeyDown() then
				BlueItemInfo2:AddFavoriteItem(id)
			elseif IsControlKeyDown() and IsShiftKeyDown() then
				BlueItemInfo2:AddMemo(id)
			elseif IsModifierKeyDown() then
				HandleModifiedItemClick(link)
			else
				SetItemRef(link)
			end
		end
		Hook("InspectUnit", function(unit)
			hook["InspectUnit"](unit)
			self:ScheduleEvent("InspectUnit", function()
				if InspectPaperDollFrame_OnLoad then
					local f
					for _, v in pairs(slotNames) do
						f = _G["Inspect"..v.."Slot"]
						if f then
							f:SetScript("OnClick", InspectOnClick)
						end
					end
				end
			end, 2)
			InspectUnit = hook["InspectUnit"]
			hook["InspectUnit"] = nil
		end)
	end
	-- Ludwig
	if LudwigUI_OnItemClick then
		Hook("LudwigUI_OnItemClick", function(frame)
			local id = GetItemID(Ludwig:GetItemLink(frame:GetID()))
			if IsAltKeyDown() then
				self:AddFavoriteItem(id)
			elseif IsControlKeyDown() and IsShiftKeyDown() then
				self:AddMemo(id)
			else
				hook.LudwigUI_OnItemClick(frame)
			end
		end)
	end
	-- Telo's LootLink
	if LootLinkItemButton_OnClick then
		Hook("LootLinkItemButton_OnClick", function(button)
			local id = GetItemID(LootLink_GetLink(this:GetText()))
			if IsAltKeyDown() then
				self:AddFavoriteItem(id)
			elseif IsControlKeyDown() and IsShiftKeyDown() then
				self:AddMemo(id)
			else
				self.hooks.LootLinkItemButton_OnClick(button)
			end
		end)
	-- Saeris's LootLink
	elseif LootLink and LootLink.Results_ItemButton_OnClick then
		Hook(LootLink, "Results_ItemButton_OnClick", function(obj, button)
			local id = GetItemID(obj:Matching_GetHyperlinkByItemTableAndSuffixID(button.ItemTable, button.SuffixID, button.InstanceID))
			if IsAltKeyDown() then
				self:AddFavoriteItem(id)
			elseif IsControlKeyDown() and IsShiftKeyDown() then
				self:AddMemo(id)
			else
				hook[obj].Results_ItemButton_OnClick(obj, button)
			end
		end)
	end
	-- ItemSync
	if ItemSync and ItemSync.ButtonClick then
		Hook(ItemSync, "ButtonClick", function(obj, sButton)
			if not this.invalid then
				local id = GetItemID(this.iteminfo.idcore)
				if IsAltKeyDown() then
					self:AddFavoriteItem()
				elseif IsControlKeyDown() and IsShiftKeyDown() then
					self:AddMemo(id)
				else
					self.hooks[obj].ButtonClick(obj, sButton)
				end
			else
				hook[obj].ButtonClick(obj, sButton)
			end
		end)
	end
end

local order, colorName, orderTable, itemType, itemEquipLoc, t, hasItem

function BlueItemInfo2:AddFavoriteItem(id)
	if not id then return end
	order = 3
	colorName = select(2, self:GetItemInfo(id))
	if id > 0 then
		orderTable = { ["INVTYPE_2HWEAPON"] = 0, ["INVTYPE_WEAPON"] = 0, ["INVTYPE_WEAPONMAINHAND"] = 0, ["INVTYPE_WEAPONOFFHAND"] = 0, ["INVTYPE_RANGEDRIGHT"] = 0, ["INVTYPE_RANGED"] = 0, ["INVTYPE_THROWN"] = 0, ["INVTYPE_HEAD"] = 1, ["INVTYPE_NECK"] = 2, ["INVTYPE_SHOULDER"] = 1, ["INVTYPE_CLOAK"] = 1, ["INVTYPE_CHEST"] = 1, ["INVTYPE_ROBE"] = 1, ["INVTYPE_WRIST"] = 1, ["INVTYPE_HAND"] = 1, ["INVTYPE_WAIST"] = 1, ["INVTYPE_LEGS"] = 1, ["INVTYPE_FEET"] = 1, ["INVTYPE_TRINKET"] = 2, ["INVTYPE_FINGER"] = 2, ["INVTYPE_RELIC"] = 0, ["INVTYPE_SHIELD"] = 0, ["INVTYPE_HOLDABLE"] = 0 }
		itemType, _, _, itemEquipLoc = select(6, GetItemInfo(id))
		order = orderTable[itemEquipLoc or "*"] or itemType == "제조법" and 3 or 4
	end
	t = BlueItemInfo2Char.favorite[order + 1] or {}
	hasItem = nil
	for p, v in pairs(t) do
		if v == id then
			hasItem = p
			break
		end
	end
	if hasItem then
		tremove(t, hasItem)
		DEFAULT_CHAT_FRAME:AddMessage(colorName.."|1이;가; 즐겨찾기에서 삭제되었습니다.")
		PlaySound("igMainMenuOptionCheckBoxOff")
	else
		tinsert(t, id)
		t = self:SortItemTable(t)
		DEFAULT_CHAT_FRAME:AddMessage(colorName.."|1이;가; 즐겨찾기에 추가되었습니다.")
		PlaySound("igMainMenuOptionCheckBoxOn")
	end
	BlueItemInfo2Char.favorite[order + 1] = t or {}
	self:CreateFavoriteItemTable(order)
	updateGUI()
end