local DGV = DugisGuideViewer
if not DGV then return end

local ItemButton = DGV:RegisterModule("ItemButton")

local function GetItemLink(itemOrInfo)
	local infoType = type(itemOrInfo)
	if infoType == "table" then
		return itemOrInfo:GetItemLink()
	elseif infoType == "string" then
		return itemOrInfo
	else
		return (select(2, C_Item.GetItemInfo(itemOrInfo)))
	end
end

local function GetItemID(itemOrInfo)
	local infoType = type(itemOrInfo)
	if infoType == "table" then
		return itemOrInfo:GetItemID()
	else
		return (C_Item.GetItemInfoInstant(itemOrInfo) or C_Item.GetItemIDForItemInfo(itemOrInfo))
	end
end

local function GetItemIcon(itemOrInfo)
	local infoType = type(itemOrInfo)
	if infoType == "table" then
		return itemOrInfo:GetItemIcon()
	else
		return C_Item.GetItemIconByID(itemOrInfo)
	end
end

local function ChatLinkItem(button)
	local link = GetItemLink(button.item)
	if ( ChatEdit_GetActiveWindow() ) then
		ChatEdit_InsertLink(link)
	else
		ChatFrame_OpenChat(link)
	end
end

DugisItemButtonMixin = {
	--OnEvent = QuestObjectiveItemButtonMixin.OnEvent, --creates error Blizzard_ObjectiveTrackerShared.lua:42: attempt to call method 'UpdateInsideBlob' (a nil value) seems to work fine without it
	OnShow = QuestObjectiveItemButtonMixin.OnShow,
	OnHide = QuestObjectiveItemButtonMixin.OnHide,

	OnLoad = function(self)
		self:RegisterForClicks("AnyUp", "AnyDown")
	end,

	OnUpdate = function(self, elapsed)
		-- Handle range indicator
		local rangeTimer = self.rangeTimer;
		if rangeTimer then
			rangeTimer = rangeTimer - elapsed;
			if rangeTimer <= 0 then
				local count = self.HotKey;
				local valid = (self.questLogIndex and IsQuestLogSpecialItemInRange(self.questLogIndex))
				if not valid and not InCombatLockdown() and self.item then
					valid = C_Item.IsItemInRange(GetItemID(self.item), "target")
				end
				if valid == 0 then
					count:Show();
					count:SetVertexColor(1.0, 0.1, 0.1);
				elseif valid == 1 then
					count:Show();
					count:SetVertexColor(0.6, 0.6, 0.6);
				else
					count:Hide();
				end
				rangeTimer = TOOLTIP_UPDATE_TIME;
			end

			self.rangeTimer = rangeTimer;
		end
	end,

	OnEnter = function(self)
		if self.item then
			GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
			GameTooltip:SetItemByID(GetItemID(self.item));
		end
	end,

	UpdateCooldown = function(self)
		if self.item then
			local start, duration, enable = C_Item.GetItemCooldown(GetItemID(self.item))
			if start then
				CooldownFrame_Set(self.Cooldown, start, duration, enable);
				if duration > 0 and enable == 0 then
					SetItemButtonTextureVertexColor(self, 0.4, 0.4, 0.4);
				else
					SetItemButtonTextureVertexColor(self, 1, 1, 1);
				end
			end
		end
	end,

	SetUseItem = function(self, item, charges, questLogIndex)
		if InCombatLockdown() then
			DGV.DoOutOfCombat(self.SetUseItem, self, item, charges, questLogIndex)
			return
		end
		self:SetAttribute("type*", "item")
		self:SetAttribute("item*", "item:"..GetItemID(item))
		self:SetAttribute("shift-type*", "dugisHandler")
		self.dugisHandler = ChatLinkItem
		self.item = item
		self.charges = charges
		self.questLogIndex = questLogIndex
		self.rangeTimer = -1;
		SetItemButtonTexture(self, GetItemIcon(item));
		SetItemButtonCount(self, charges);
		self:UpdateCooldown(self);
	end,

	SetUp = function(self, questLogIndex)
		local link, item, charges = questLogIndex and GetQuestLogSpecialItemInfo(questLogIndex)
		self:SetUseItem(link or item, charges, questLogIndex)
	end
}

function ItemButton:Initialize()

	function ItemButton:Load()
		local frame = DugisItemButton

		local function SetUseItem(item, charges, questLogIndex)
			if InCombatLockdown() then
				DGV.DoOutOfCombat(SetUseItem, item, charges, questLogIndex)
				return
			end
			if not (item and DGV:UserSetting(DGV_ITEMBUTTONON)) then 
				frame:Hide()
				return
			end
			frame:SetUseItem(item, charges, questLogIndex)
			frame:Show()
		end

		--[[local function IterateItemLocations(invariant, control)
			local bag, slot, equip
			if not control then 
				control, bag, slot = ItemLocation:CreateEmpty(), Enum.BagIndex.Backpack, 0
			else
				bag, slot = control:GetBagAndSlot()
				equip = control:GetEquipmentSlot()
			end
			if slot and slot >= C_Container.GetContainerNumSlots(bag) then
				if bag >= NUM_TOTAL_EQUIPPED_BAG_SLOTS then
					equip = 0
				else
					bag = bag + 1
					slot = 0
				end
			elseif equip and equip >= INVSLOT_LAST_EQUIPPED then
				return
			end
			if equip then
				control:SetEquipmentSlot(equip + 1)
			else
				control:SetBagAndSlot(bag, slot + 1)
			end
			return control
		end

		local function FindItem(itemInfo)
			for loc in IterateItemLocations do
				if loc:IsValid() and (itemInfo == C_Item.GetItemID(loc) or itemInfo == C_Item.GetItemLink(loc)) then
					return Item:CreateFromItemLocation(loc)
				end
			end
		end

		local function FindAndSetItem(itemInfo, charges, logIndex)
			local item = itemInfo and FindItem(itemInfo)
			if item then
				DGV.DoOutOfCombat(SetUseItem, item, charges or item:GetStackCount(), logIndex)
				return item
			end
		end]]

		function ItemButton:SetUseItem(index)
			--DGV:DebugFormat("SetUseItem", "stack", debugstack())
			if DGV:IsModuleLoaded("Guides") then
				local questId = DGV.qid[index]
				if ItemButton:SetUseItemByQID(questId) then return end

				local useitem = tonumber(DGV.useitem[index])
				SetUseItem(useitem)
			end
		end
		
		function ItemButton:SetUseItemByQID(questId)
			if questId then
				local logIndex = questId and DGV:GetQuestLogIndexByQID(questId)
				if logIndex then
					local link, itemId, charges = logIndex and GetQuestLogSpecialItemInfo(logIndex)
					if SetUseItem(link or itemId, charges, logIndex) then return true end
				end
			end
		end

		function ItemButton:Update()
			SetUseItem(frame.item, frame.charges, frame.questLogIndex)
		end
	end

	function ItemButton:Unload()
		DugisItemButton:Hide()
	end
end
