// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace System.Linq
{
    public static partial class AsyncEnumerableEx
    {
        /// 
        /// Concatenates all inner async-enumerable sequences, as long as the previous async-enumerable sequence terminated successfully.
        /// 
        /// The type of the elements in the source sequences.
        /// Observable sequence of inner async-enumerable sequences.
        /// An async-enumerable sequence that contains the elements of each observed inner sequence, in sequential order.
        ///  is null.
        public static IAsyncEnumerable Concat(this IAsyncEnumerable> sources)
        {
            if (sources == null)
                throw Error.ArgumentNull(nameof(sources));
            return Core(sources);
            static async IAsyncEnumerable Core(IAsyncEnumerable> sources, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
            {
                await foreach (var source in sources.WithCancellation(cancellationToken).ConfigureAwait(false))
                {
                    await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
                    {
                        yield return item;
                    }
                }
            }
        }
        /// 
        /// Concatenates all async-enumerable sequences in the given enumerable sequence, as long as the previous async-enumerable sequence terminated successfully.
        /// 
        /// The type of the elements in the source sequences.
        /// Observable sequences to concatenate.
        /// An async-enumerable sequence that contains the elements of each given sequence, in sequential order.
        ///  is null.
        public static IAsyncEnumerable Concat(this IEnumerable> sources)
        {
            if (sources == null)
                throw Error.ArgumentNull(nameof(sources));
            return Core(sources);
            static async IAsyncEnumerable Core(IEnumerable> sources, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
            {
                foreach (var source in sources)
                {
                    await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
                    {
                        yield return item;
                    }
                }
            }
        }
        /// 
        /// Concatenates all of the specified async-enumerable sequences, as long as the previous async-enumerable sequence terminated successfully.
        /// 
        /// The type of the elements in the source sequences.
        /// Observable sequences to concatenate.
        /// An async-enumerable sequence that contains the elements of each given sequence, in sequential order.
        ///  is null.
        public static IAsyncEnumerable Concat(params IAsyncEnumerable[] sources)
        {
            if (sources == null)
                throw Error.ArgumentNull(nameof(sources));
            return Core(sources);
            static async IAsyncEnumerable Core(IAsyncEnumerable[] sources, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
            {
                foreach (var source in sources)
                {
                    await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
                    {
                        yield return item;
                    }
                }
            }
        }
    }
}