// 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
    {
        /// 
        /// Repeats the element indefinitely.
        /// 
        /// The type of the elements in the source sequence.
        /// Element to repeat.
        /// The async-enumerable sequence producing the element repeatedly and sequentially.
        public static IAsyncEnumerable Repeat(TResult element)
        {
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
            return Core(element);
            static async IAsyncEnumerable Core(TResult element, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
            {
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    yield return element;
                }
            }
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        }
        /// 
        /// Repeats the async-enumerable sequence indefinitely.
        /// 
        /// The type of the elements in the source sequence.
        /// Observable sequence to repeat.
        /// The async-enumerable sequence producing the elements of the given sequence repeatedly and sequentially.
        ///  is null.
        public static IAsyncEnumerable Repeat(this IAsyncEnumerable source)
        {
            if (source == null)
                throw Error.ArgumentNull(nameof(source));
            return Core(source);
            static async IAsyncEnumerable Core(IAsyncEnumerable source, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
            {
                while (true)
                {
                    await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
                    {
                        yield return item;
                    }
                }
            }
        }
        /// 
        /// Repeats the async-enumerable sequence a specified number of times.
        /// 
        /// The type of the elements in the source sequence.
        /// Observable sequence to repeat.
        /// Number of times to repeat the sequence.
        /// The async-enumerable sequence producing the elements of the given sequence repeatedly.
        ///  is null.
        ///  is less than zero.
        public static IAsyncEnumerable Repeat(this IAsyncEnumerable source, int count)
        {
            if (source == null)
                throw Error.ArgumentNull(nameof(source));
            if (count < 0)
                throw Error.ArgumentOutOfRange(nameof(count));
            return Core(source, count);
            static async IAsyncEnumerable Core(IAsyncEnumerable source, int count, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
            {
                for (var i = 0; i < count; i++)
                {
                    await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
                    {
                        yield return item;
                    }
                }
            }
        }
    }
}