return Rodux.createReducer({},{[SetOwnedAssets.name]=function(m,U)local b={}local F=m[U.assetTypeId]and m[U.assetTypeId]or{}for m,U in pairs(F)do b[U]=U end for m,U in pairs(U.assets)do if not b[U]then F[#F+1]=U end end return Cryo.Dictionary.join(m,{[U.assetTypeId]=F})end;[GrantAsset.name]=function(m,U)if GetAENewNavigationEnabled()then local b={}local F=tostring(U.assetTypeId)local u=tostring(U.assetId)local L=AssetTypeToSearchUuids[F]if not L then return m end for U,F in ipairs(L)do local L=m[F]and m[F]or{}local e={u}local Q=false for m,U in ipairs(L)do if U==u then Q=true break else e[m+1]=U end end if not Q then b[F]=e end end if next(b)then return Cryo.Dictionary.join(m,b)end return m else local b=tostring(U.assetTypeId)local F=tostring(U.assetId)local u=m[b]and m[b]or{}local L={F}for U,b in ipairs(u)do if b==F then return m else L[U+1]=b end end return Cryo.Dictionary.join(m,{[b]=L})end end;[RevokeAsset.name]=function(m,U)if GetAENewNavigationEnabled()then local b={}local F=tostring(U.assetTypeId)local u=tostring(U.assetId)local L=AssetTypeToSearchUuids[F]if not L then return m end for U,F in ipairs(L)do local L=m[F]and m[F]or{}local e=Cryo.List.removeValue(L,u)if#L~=#e then b[F]=e end end if next(b)then return Cryo.Dictionary.join(m,b)end return m else local b=tostring(U.assetTypeId)local F=tostring(U.assetId)local u=m[b]and m[b]or{}local L=Cryo.List.removeValue(u,F)return Cryo.Dictionary.join(m,{[b]=L})end end;[GrantOutfit.name]=function(m,U)local b=tostring(U.outfitId)local F=m[AvatarEditorConstants.CharacterKey]or{}local u={b}for U,F in ipairs(F)do if F==b then return m else u[U+1]=F end end return Cryo.Dictionary.join(m,{[AvatarEditorConstants.CharacterKey]=u})end,[RevokeOutfit.name]=function(m,U)local b=tostring(U.outfitId)local F=m[AvatarEditorConstants.CharacterKey]or{}local u=Cryo.List.removeValue(F,b)return Cryo.Dictionary.join(m,{[AvatarEditorConstants.CharacterKey]=u})end})
--[[
	Add more owned asset ids to the players list. Keep order by checking for duplicates and only
	appending new ones to the list.
]]

return Rodux.createReducer({}, {
	[SetOwnedAssets.name] = function(state, action)
		local checkForDups = {}
		local currentAssets = state[action.assetTypeId] and state[action.assetTypeId] or {}

		for _, assetId in pairs(currentAssets) do
			checkForDups[assetId] = assetId
		end

		for _, assetId in pairs(action.assets) do
			if not checkForDups[assetId] then
				currentAssets[#currentAssets + 1] = assetId
			end
		end

		return Cryo.Dictionary.join(state, { [action.assetTypeId] = currentAssets })
	end,

	[GrantAsset.name] = function(state, action)
		if GetAENewNavigationEnabled() then
			local updatedCategories = {}

			local assetTypeId = tostring(action.assetTypeId)
			local newAssetId = tostring(action.assetId)

			local searchUuids = AssetTypeToSearchUuids[assetTypeId]
			if not searchUuids then
				return state
			end

			for _, searchUuid in ipairs(searchUuids) do
				local currentAssets = state[searchUuid] and state[searchUuid] or {}

				local updatedAssets = { newAssetId }
				local owned = false

				for i, assetId in ipairs(currentAssets) do
					if assetId == newAssetId then
						owned = true
						break
					else
						updatedAssets[i + 1] = assetId
					end
				end

				-- Do nothing if this asset is already owned.
				if not owned then
					updatedCategories[searchUuid] = updatedAssets
				end
			end

			if next(updatedCategories) then
				return Cryo.Dictionary.join(state, updatedCategories)
			end

			return state
		else
			local assetTypeId = tostring(action.assetTypeId)
			local newAssetId = tostring(action.assetId)
			local currentAssets = state[assetTypeId] and state[assetTypeId] or {}

			local updatedAssets = { newAssetId }

			for i, assetId in ipairs(currentAssets) do
				-- Do nothing if this asset is already owned.
				if assetId == newAssetId then
					return state
				else
					updatedAssets[i + 1] = assetId
				end
			end

			return Cryo.Dictionary.join(state, { [assetTypeId] = updatedAssets })
		end
	end,

	[RevokeAsset.name] = function(state, action)
		if GetAENewNavigationEnabled() then
			local updatedCategories = {}

			local assetTypeId = tostring(action.assetTypeId)
			local assetToRevokeId = tostring(action.assetId)

			local searchUuids = AssetTypeToSearchUuids[assetTypeId]
			if not searchUuids then
				return state
			end

			for _, searchUuid in ipairs(searchUuids) do
				local currentAssets = state[searchUuid] and state[searchUuid] or {}
				local updatedAssets = Cryo.List.removeValue(currentAssets, assetToRevokeId)

				-- Do nothing if this asset is not owned.
				if #currentAssets ~= #updatedAssets then
					updatedCategories[searchUuid] = updatedAssets
				end
			end

			if next(updatedCategories) then
				return Cryo.Dictionary.join(state, updatedCategories)
			end

			return state
		else
			local assetTypeId = tostring(action.assetTypeId)
			local assetToRevokeId = tostring(action.assetId)
			local currentAssets = state[assetTypeId] and state[assetTypeId] or {}

			local updatedAssets = Cryo.List.removeValue(currentAssets, assetToRevokeId)

			return Cryo.Dictionary.join(state, { [assetTypeId] = updatedAssets })
		end
	end,

	[GrantOutfit.name] = function(state, action)
		local actionOutfitId = tostring(action.outfitId)
		local currentOutfits = state[AvatarEditorConstants.CharacterKey] or {}

		local updatedOutfits = { actionOutfitId }

		for i, outfitId in ipairs(currentOutfits) do
			-- Do nothing if this costume is already owned.
			if outfitId == actionOutfitId then
				return state
			else
				updatedOutfits[i + 1] = outfitId
			end
		end

		return Cryo.Dictionary.join(state, { [AvatarEditorConstants.CharacterKey] = updatedOutfits })
	end,

	[RevokeOutfit.name] = function(state, action)
		local outfitId = tostring(action.outfitId)
		local currentOutfits = state[AvatarEditorConstants.CharacterKey] or {}
		local costumeList = Cryo.List.removeValue(currentOutfits, outfitId)

		return Cryo.Dictionary.join(state, { [AvatarEditorConstants.CharacterKey] = costumeList })
	end,
})
