local O="    "local function Z(p,j)j=j or 0 local N={}if typeof(p)=="\116\097\098\108\101"then table.insert(N,"\123\n")for p,T in pairs(p)do table.insert(N,O:rep(j+1))table.insert(N,tostring(p))table.insert(N," \061 ")table.insert(N,Z(T,j+1))table.insert(N,"\n")end table.insert(N,O:rep(j))table.insert(N,"\125")elseif typeof(p)=="\115\116\114\105\110\103"then table.insert(N,string.format("\037\113",p))table.insert(N," \040\115\116\114\105\110\103\041")else table.insert(N,tostring(p))table.insert(N," \040")table.insert(N,typeof(p))table.insert(N,"\041")end return table.concat(N,"")end local p={outputFunction=print}function p.middleware(O,j)return function(N)local T=O(N)p.outputFunction(("\065\099\116\105\111\110 \100\105\115\112\097\116\099\104\101\100\058 \037\115\n\083\116\097\116\101 \099\104\097\110\103\101\100 \116\111\058 \037\115"):format(Z(N),Z(j:getState())))return T end end return p
local indent = "    "

local function prettyPrint(value, indentLevel)
	indentLevel = indentLevel or 0
	local output = {}

	if typeof(value) == "table" then
		table.insert(output, "{\n")

		for key, value in pairs(value) do
			table.insert(output, indent:rep(indentLevel + 1))
			table.insert(output, tostring(key))
			table.insert(output, " = ")

			table.insert(output, prettyPrint(value, indentLevel + 1))
			table.insert(output, "\n")
		end

		table.insert(output, indent:rep(indentLevel))
		table.insert(output, "}")
	elseif typeof(value) == "string" then
		table.insert(output, string.format("%q", value))
		table.insert(output, " (string)")
	else
		table.insert(output, tostring(value))
		table.insert(output, " (")
		table.insert(output, typeof(value))
		table.insert(output, ")")
	end

	return table.concat(output, "")
end

-- We want to be able to override outputFunction in tests, so the shape of this
-- module is kind of unconventional.
--
-- We fix it this weird shape in init.lua.
local loggerMiddleware = {
	outputFunction = print,
}

function loggerMiddleware.middleware(nextDispatch, store)
	return function(action)
		local result = nextDispatch(action)

		loggerMiddleware.outputFunction(("Action dispatched: %s\nState changed to: %s"):format(
			prettyPrint(action),
			prettyPrint(store:getState())
		))

		return result
	end
end

return loggerMiddleware
