--[[
	Middleware for triggering events on action dispatch

	Each key in the `events` object should be the type of an action. For
	example:

		local fooAction = { type = "foo" }
		local events = {
			[fooAction.type] = Instance.new("BindableEvent")
		}

		local store = Rodux.Store.new(reducer, nil, {
			actionsAsEvents(events)
		})

		store:dispatch(fooAction)

	If you use Rodux.makeActionCreator() then you can optionally use the `name`
	field instead:

		local fooAction = Rodux.makeActionCreator("foo", function()
			return {}
		end)

		local events = {
			[fooAction.name] = Instance.new("BindableEvent")
		}

		local store = Rodux.Store.new(reducer, nil, {
			actionsAsEvents(events)
		})

		store:dispatch(fooAction())
]]


export type Action = {
	type: string,
	eventArguments: { any }?,
}

export type Event = BindableEvent | {
	Fire: (...any) -> (),
}

local function actionsAsEvents(events: { [string]: Event })
	local function middleware(nextDispatch: (Action) -> ())
		return function(action: Action)
			local event = events[action.type]
			if event then
				if action.eventArguments then
					-- FIXME Luau: Need to cast `event` to `any` to clear
					-- "Cannot call non-function" error
					(event :: any):Fire(table.unpack(action.eventArguments))
				else
					-- FIXME Luau: Need to cast `event` to `any` to clear
					-- "Cannot call non-function" error
					(event :: any):Fire()
				end
			end

			return nextDispatch(action)
		end
	end

	return middleware
end

return actionsAsEvents
