local C=require(script.Parent.Roact)local function e()local e local O local function o(C,e)local O=setmetatable({node=e},{__index=C})O:init()return O end local function D(C)return function(...)assert(e,"\072\111\111\107\115 \109\097\121 \111\110\108\121 \098\101 \117\115\101\100 \105\110 \097 \102\117\110\099\116\105\111\110\097\108 \099\111\109\112\111\110\101\110\116 \119\114\097\112\112\101\100 \105\110 \104\111\111\107\105\102\121\040\041")local D=e local t=O O+=1 local R=D.hooks[t]if R then assert(R.__class==C.__class,("\072\111\111\107 \116\121\112\101 \109\105\115\109\097\116\099\104 \040\101\120\112\101\099\116\101\100 \037\115\044 \103\111\116 \037\115\041\046 \077\097\107\101 \115\117\114\101 \116\104\101 \117\115\101\072\111\111\107 \099\097\108\108 \105\115\110\'\116 \105\110 \097 \108\111\111\112 \111\114 \099\111\110\100\105\116\105\111\110\097\108\033"):format(C.__name,R.__name))else R=o(C,D)D.hooks[t]=R end return R:use(...)end end local function t(C)e=C O=1 end local function R()e=nil O=nil end local function P(e,O)local o=C.Component:extend(O or"\072\111\111\107\105\102\121\065\110\111\110\121\109\111\117\115")function o.init(C)C.hooks={}C.handlers={}end function o.register(O,C,e)assert(C~="\114\101\110\100\101\114","\058\114\101\110\100\101\114\040\041 \099\097\110\110\111\116 \098\101 \114\101\103\105\115\116\101\114\101\100 \097\115 \097 \104\097\110\100\108\101\114")assert(C~="\105\110\105\116","\058\105\110\105\116\040\041 \099\097\110\110\111\116 \098\101 \114\101\103\105\115\116\101\114\101\100 \097\115 \097 \104\097\110\100\108\101\114")local o=O.handlers[C]if not o then o={}O[C]=function(C,...)for C,e in ipairs(o)do e(...)end end O.handlers[C]=o end table.insert(o,e)end function o.render(C)t(C)local O=e(C.props)R()return O end return o end return{wrapFunctionalComponent=P,createHookRunner=D}end return e
local Roact = require(script.Parent.Roact)

local function createHookCapture()
	local currentNode
	local currentHookIndex

	local function createHookInstance(base, node)
		local hookInstance = setmetatable({
			node = node
		}, { __index = base })

		hookInstance:init()

		return hookInstance
	end

	local function createHookRunner(base)
		return function(...)
			assert(currentNode, "Hooks may only be used in a functional component wrapped in hookify()")

			local node = currentNode
			local hookIndex = currentHookIndex

			currentHookIndex += 1

			local hook = node.hooks[hookIndex]

			if hook then
				-- Type check current hook
				assert(hook.__class == base.__class, ("Hook type mismatch (expected %s, got %s). Make sure the useHook call isn't in a loop or conditional!"):format(
					base.__name,
					hook.__name
				))
			else
				-- Create new hook
				hook = createHookInstance(base, node)
				node.hooks[hookIndex] = hook
			end

			return hook:use(...)
		end
	end

	local function startCapture(node)
		currentNode = node
		currentHookIndex = 1
	end

	local function endCapture()
		currentNode = nil
		currentHookIndex = nil
	end

	local function wrapFunctionalComponent(functionalComponent, name)
		local component = Roact.Component:extend(name or "HookifyAnonymous")

		function component:init()
			self.hooks = {}
			self.handlers = {}
		end

		function component:register(handlerName, newHandler)
			assert(handlerName ~= "render", ":render() cannot be registered as a handler")
			assert(handlerName ~= "init", ":init() cannot be registered as a handler")

			local handlerList = self.handlers[handlerName]

			if not handlerList then
				handlerList = {}

				self[handlerName] = function(_, ...)
					for _, handler in ipairs(handlerList) do
						handler(...)
					end
				end

				self.handlers[handlerName] = handlerList
			end

			table.insert(handlerList, newHandler)
		end

		function component:render()
			startCapture(self)
			local element = functionalComponent(self.props)
			endCapture()
			return element
		end

		return component
	end

	return {
		wrapFunctionalComponent = wrapFunctionalComponent,
		createHookRunner = createHookRunner
	}
end

return createHookCapture