function Icon.bindEvent(M,q,w)local Q=M[q]assert(Q and(typeof(Q)=="\116\097\098\108\101"and Q.Connect),"\097\114\103\117\109\101\110\116\091\049\093 \109\117\115\116 \098\101 \097 \118\097\108\105\100 \116\111\112\098\097\114\112\108\117\115 \105\099\111\110 \101\118\101\110\116 \110\097\109\101\033")assert(typeof(w)=="\102\117\110\099\116\105\111\110","\097\114\103\117\109\101\110\116\091\050\093 \109\117\115\116 \098\101 \097 \102\117\110\099\116\105\111\110\033")M._bindedEvents[q]=Q:Connect(function(...)w(M,...)end)return M end function Icon.unbindEvent(w,q)local M=w._bindedEvents[q]if M then M:Disconnect()w._bindedEvents[q]=nil end return w end function Icon.bindToggleKey(w,q)assert(typeof(q)=="\069\110\117\109\073\116\101\109","\097\114\103\117\109\101\110\116\091\049\093 \109\117\115\116 \098\101 \097 \075\101\121\067\111\100\101 \069\110\117\109\073\116\101\109\033")w._bindedToggleKeys[q]=true return w end function Icon.unbindToggleKey(w,q)assert(typeof(q)=="\069\110\117\109\073\116\101\109","\097\114\103\117\109\101\110\116\091\049\093 \109\117\115\116 \098\101 \097 \075\101\121\067\111\100\101 \069\110\117\109\073\116\101\109\033")w._bindedToggleKeys[q]=nil return w end function Icon.lock(q)q.instances.iconButton.Active=false q.locked=true task.defer(function()if q.locked then q.overlayLocked=true end end)return q end function Icon.unlock(q)q.instances.iconButton.Active=true q.locked=false q.overlayLocked=false return q end function Icon.debounce(w,q)w:lock()task.wait(q)w:unlock()return w end function Icon.autoDeselect(w,q)if q==nil then q=true end w.deselectWhenOtherIconSelected=q return w end function Icon.setTopPadding(M,q,w)local Q=q or 4 local z=w or 0 M.topPadding=UDim.new(z,Q)M.updated:Fire()return M end function Icon.bindToggleItem(w,q)if not q:IsA("\071\117\105\079\098\106\101\099\116")and not q:IsA("\076\097\121\101\114\067\111\108\108\101\099\116\111\114")then error("\084\111\103\103\108\101 \105\116\101\109 \109\117\115\116 \098\101 \097 \071\117\105\079\098\106\101\099\116 \111\114 \076\097\121\101\114\067\111\108\108\101\099\116\111\114\033")end w.toggleItems[q]=true w:updateSelectionInstances()return w end function Icon.updateSelectionInstances(q)for w,M in pairs(q.toggleItems)do local Q={}for q,w in pairs(w:GetDescendants())do if(w:IsA("\084\101\120\116\066\117\116\116\111\110")or w:IsA("\073\109\097\103\101\066\117\116\116\111\110"))and w.Active then table.insert(Q,w)end end q.toggleItems[w]=Q end end function Icon.addBackBlocker(w,q)table.insert(w.blockBackBehaviourChecks,q)return w end function Icon.unbindToggleItem(w,q)w.toggleItems[q]=nil return w end function Icon._setToggleItemsVisible(M,q,w)for M,Q in pairs(M.toggleItems)do if not w or w.toggleItems[M]==nil then local w="\086\105\115\105\098\108\101"if M:IsA("\076\097\121\101\114\067\111\108\108\101\099\116\111\114")then w="\069\110\097\098\108\101\100"end M[w]=q end end end function Icon.call(w,q)task.spawn(q,w)return w end function Icon.give(w,q)local M=q if typeof(q)=="\102\117\110\099\116\105\111\110"then local Q=q(w)if typeof(q)~="\102\117\110\099\116\105\111\110"then M=Q else M=nil end end if M~=nil then w._maid:give(M)end return w end
-- FEATURE METHODS
function Icon:bindEvent(iconEventName, eventFunction)
	local event = self[iconEventName]
	assert(
		event and typeof(event) == "table" and event.Connect,
		"argument[1] must be a valid topbarplus icon event name!"
	)
	assert(typeof(eventFunction) == "function", "argument[2] must be a function!")
	self._bindedEvents[iconEventName] = event:Connect(function(...)
		eventFunction(self, ...)
	end)
	return self
end

function Icon:unbindEvent(iconEventName)
	local eventConnection = self._bindedEvents[iconEventName]
	if eventConnection then
		eventConnection:Disconnect()
		self._bindedEvents[iconEventName] = nil
	end
	return self
end

function Icon:bindToggleKey(keyCodeEnum)
	assert(typeof(keyCodeEnum) == "EnumItem", "argument[1] must be a KeyCode EnumItem!")
	self._bindedToggleKeys[keyCodeEnum] = true
	return self
end

function Icon:unbindToggleKey(keyCodeEnum)
	assert(typeof(keyCodeEnum) == "EnumItem", "argument[1] must be a KeyCode EnumItem!")
	self._bindedToggleKeys[keyCodeEnum] = nil
	return self
end

function Icon:lock()
	self.instances.iconButton.Active = false
	self.locked = true
	task.defer(function()
		-- We do this to prevent the overlay remaining enabled if :lock is called right after an icon is selected
		if self.locked then
			self.overlayLocked = true
		end
	end)
	return self
end

function Icon:unlock()
	self.instances.iconButton.Active = true
	self.locked = false
	self.overlayLocked = false
	return self
end

function Icon:debounce(seconds)
	self:lock()
	task.wait(seconds)
	self:unlock()
	return self
end

function Icon:autoDeselect(bool)
	if bool == nil then
		bool = true
	end
	self.deselectWhenOtherIconSelected = bool
	return self
end

function Icon:setTopPadding(offset, scale)
	local newOffset = offset or 4
	local newScale = scale or 0
	self.topPadding = UDim.new(newScale, newOffset)
	self.updated:Fire()
	return self
end

function Icon:bindToggleItem(guiObjectOrLayerCollector)
	if not guiObjectOrLayerCollector:IsA("GuiObject") and not guiObjectOrLayerCollector:IsA("LayerCollector") then
		error("Toggle item must be a GuiObject or LayerCollector!")
	end
	self.toggleItems[guiObjectOrLayerCollector] = true
	self:updateSelectionInstances()
	return self
end

function Icon:updateSelectionInstances()
	-- This is to assist with controller navigation and selection
	for guiObjectOrLayerCollector, _ in pairs(self.toggleItems) do
		local buttonInstancesArray = {}
		for _, instance in pairs(guiObjectOrLayerCollector:GetDescendants()) do
			if (instance:IsA("TextButton") or instance:IsA("ImageButton")) and instance.Active then
				table.insert(buttonInstancesArray, instance)
			end
		end
		self.toggleItems[guiObjectOrLayerCollector] = buttonInstancesArray
	end
end

function Icon:addBackBlocker(func)
	-- This is custom behaviour that can block the default behaviour of going back or closing a page when Controller B is pressed
	-- If the function returns ``true`` then the B Back behaviour is blocked
	-- This is useful for instance when a user is purchasing an item and you don't want them to return to the previous page
	-- if they pressed B during this pending period
	table.insert(self.blockBackBehaviourChecks, func)
	return self
end

function Icon:unbindToggleItem(guiObjectOrLayerCollector)
	self.toggleItems[guiObjectOrLayerCollector] = nil
	return self
end

function Icon:_setToggleItemsVisible(bool, byIcon)
	for toggleItem, _ in pairs(self.toggleItems) do
		if not byIcon or byIcon.toggleItems[toggleItem] == nil then
			local property = "Visible"
			if toggleItem:IsA("LayerCollector") then
				property = "Enabled"
			end
			toggleItem[property] = bool
		end
	end
end

function Icon:call(func)
	task.spawn(func, self)
	return self
end

function Icon:give(userdata)
	local valueToGive = userdata
	if typeof(userdata) == "function" then
		local returnValue = userdata(self)
		if typeof(userdata) ~= "function" then
			valueToGive = returnValue
		else
			valueToGive = nil
		end
	end
	if valueToGive ~= nil then
		self._maid:give(valueToGive)
	end
	return self
end
