--[=[
	Given an observable that emits observables, emit an
	observable that once the initial observable completes,
	the latest values of each emitted observable will be
	combined into an array that will be emitted.

	https://rxjs.dev/api/operators/combineLatestAll

	@return (source: Observable<Observable<T>>) -> Observable<{ T }>
]=]

function Rx.combineLatestAll()
	return function(source)
		assert(Observable.isObservable(source), "Bad observable")

		return Observable.new(function(sub)
			local observables = {}
			local maid = Maid.new()

			local alive = true
			maid:GiveTask(function()
				alive = false
			end)

			maid:GiveTask(source:Subscribe(
				function(value)
					assert(Observable.isObservable(value))

					table.insert(observables, value)
				end,
				function(...)
					sub:Fail(...)
				end),
				function()
					if not alive then
						return
					end

					maid:GiveTask(Rx.combineLatest(observables))
						:Subscribe(sub:GetFireFailComplete())
				end)

			return maid
		end)
	end
end
