// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Reactive.Concurrency;
using System.Threading;
#if !NO_TPL
using System.Threading.Tasks;
#endif
namespace System.Reactive.Linq
{
    public static partial class Observable
    {
        #region + ForEachAsync +
#if !NO_TPL
        /// 
        /// Invokes an action for each element in the observable sequence, and returns a Task object that will get signaled when the sequence terminates.
        /// 
        /// The type of the elements in the source sequence.
        /// Source sequence.
        /// Action to invoke for each element in the observable sequence.
        /// Task that signals the termination of the sequence.
        ///  or  is null.
        /// This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.
        public static Task ForEachAsync(this IObservable source, Action onNext)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (onNext == null)
                throw new ArgumentNullException("onNext");
            return s_impl.ForEachAsync(source, onNext);
        }
        /// 
        /// Invokes an action for each element in the observable sequence, and returns a Task object that will get signaled when the sequence terminates.
        /// The loop can be quit prematurely by setting the specified cancellation token.
        /// 
        /// The type of the elements in the source sequence.
        /// Source sequence.
        /// Action to invoke for each element in the observable sequence.
        /// Cancellation token used to stop the loop.
        /// Task that signals the termination of the sequence.
        ///  or  is null.
        /// This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.
        public static Task ForEachAsync(this IObservable source, Action onNext, CancellationToken cancellationToken)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (onNext == null)
                throw new ArgumentNullException("onNext");
            return s_impl.ForEachAsync(source, onNext, cancellationToken);
        }
        /// 
        /// Invokes an action for each element in the observable sequence, incorporating the element's index, and returns a Task object that will get signaled when the sequence terminates.
        /// 
        /// The type of the elements in the source sequence.
        /// Source sequence.
        /// Action to invoke for each element in the observable sequence.
        /// Task that signals the termination of the sequence.
        ///  or  is null.
        /// This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.
        public static Task ForEachAsync(this IObservable source, Action onNext)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (onNext == null)
                throw new ArgumentNullException("onNext");
            return s_impl.ForEachAsync(source, onNext);
        }
        /// 
        /// Invokes an action for each element in the observable sequence, incorporating the element's index, and returns a Task object that will get signaled when the sequence terminates.
        /// The loop can be quit prematurely by setting the specified cancellation token.
        /// 
        /// The type of the elements in the source sequence.
        /// Source sequence.
        /// Action to invoke for each element in the observable sequence.
        /// Cancellation token used to stop the loop.
        /// Task that signals the termination of the sequence.
        ///  or  is null.
        /// This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.
        public static Task ForEachAsync(this IObservable source, Action onNext, CancellationToken cancellationToken)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (onNext == null)
                throw new ArgumentNullException("onNext");
            return s_impl.ForEachAsync(source, onNext, cancellationToken);
        }
#endif
        #endregion
        #region + Case +
        /// 
        /// Uses  to determine which source in  to return, choosing  if no match is found.
        /// 
        /// The type of the value returned by the selector function, used to look up the resulting source.
        /// The type of the elements in the result sequence.
        /// Selector function invoked to determine the source to lookup in the  dictionary.
        /// Dictionary of sources to select from based on the  invocation result.
        /// Default source to select in case no matching source in  is found.
        /// The observable sequence retrieved from the  dictionary based on the  invocation result, or  if no match is found.
        ///  or  or  is null.
        public static IObservable Case(Func selector, IDictionary> sources, IObservable defaultSource)
        {
            if (selector == null)
                throw new ArgumentNullException("selector");
            if (sources == null)
                throw new ArgumentNullException("sources");
            if (defaultSource == null)
                throw new ArgumentNullException("defaultSource");
            return s_impl.Case(selector, sources, defaultSource);
        }
        /// 
        /// Uses  to determine which source in  to return, choosing an empty sequence on the specified scheduler if no match is found.
        /// 
        /// The type of the value returned by the selector function, used to look up the resulting source.
        /// The type of the elements in the result sequence.
        /// Selector function invoked to determine the source to lookup in the  dictionary.
        /// Dictionary of sources to select from based on the  invocation result.
        /// Scheduler to generate an empty sequence on in case no matching source in  is found.
        /// The observable sequence retrieved from the  dictionary based on the  invocation result, or an empty sequence if no match is found.
        ///  or  or  is null.
        public static IObservable Case(Func selector, IDictionary> sources, IScheduler scheduler)
        {
            if (selector == null)
                throw new ArgumentNullException("selector");
            if (sources == null)
                throw new ArgumentNullException("sources");
            if (scheduler == null)
                throw new ArgumentNullException("scheduler");
            return s_impl.Case(selector, sources, scheduler);
        }
        /// 
        /// Uses  to determine which source in  to return, choosing an empty sequence if no match is found.
        /// 
        /// The type of the value returned by the selector function, used to look up the resulting source.
        /// The type of the elements in the result sequence.
        /// Selector function invoked to determine the source to lookup in the  dictionary.
        /// Dictionary of sources to select from based on the  invocation result.
        /// The observable sequence retrieved from the  dictionary based on the  invocation result, or an empty sequence if no match is found.
        ///  or  is null.
        public static IObservable Case(Func selector, IDictionary> sources)
        {
            if (selector == null)
                throw new ArgumentNullException("selector");
            if (sources == null)
                throw new ArgumentNullException("sources");
            return s_impl.Case(selector, sources);
        }
        #endregion
        #region + DoWhile +
        /// 
        /// Repeats the given  as long as the specified  holds, where the  is evaluated after each repeated  completed.
        /// 
        /// The type of the elements in the source sequence.
        /// Source to repeat as long as the  function evaluates to true.
        /// Condition that will be evaluated upon the completion of an iteration through the , to determine whether repetition of the source is required.
        /// The observable sequence obtained by concatenating the  sequence as long as the  holds.
        ///  or  is null.
        public static IObservable DoWhile(this IObservable source, Func condition)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (condition == null)
                throw new ArgumentNullException("condition");
            return s_impl.DoWhile(source, condition);
        }
        #endregion
        #region + For +
        /// 
        /// Concatenates the observable sequences obtained by running the  for each element in the given enumerable .
        /// 
        /// The type of the elements in the enumerable source sequence.
        /// The type of the elements in the observable result sequence.
        /// Enumerable source for which each element will be mapped onto an observable source that will be concatenated in the result sequence.
        /// Function to select an observable source for each element in the .
        /// The observable sequence obtained by concatenating the sources returned by  for each element in the .
        ///  or  is null.
        public static IObservable For(IEnumerable source, Func> resultSelector)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (resultSelector == null)
                throw new ArgumentNullException("resultSelector");
            return s_impl.For(source, resultSelector);
        }
        #endregion
        #region + If +
        /// 
        /// If the specified  evaluates true, select the  sequence. Otherwise, select the  sequence.
        /// 
        /// The type of the elements in the result sequence.
        /// Condition evaluated to decide which sequence to return.
        /// Sequence returned in case  evaluates true.
        /// Sequence returned in case  evaluates false.
        ///  if  evaluates true;  otherwise.
        ///  or  or  is null.
        public static IObservable If(Func condition, IObservable thenSource, IObservable elseSource)
        {
            if (condition == null)
                throw new ArgumentNullException("condition");
            if (thenSource == null)
                throw new ArgumentNullException("thenSource");
            if (elseSource == null)
                throw new ArgumentNullException("elseSource");
            return s_impl.If(condition, thenSource, elseSource);
        }
        /// 
        /// If the specified  evaluates true, select the  sequence. Otherwise, return an empty sequence.
        /// 
        /// The type of the elements in the result sequence.
        /// Condition evaluated to decide which sequence to return.
        /// Sequence returned in case  evaluates true.
        ///  if  evaluates true; an empty sequence otherwise.
        ///  or  is null.
        public static IObservable If(Func condition, IObservable thenSource)
        {
            if (condition == null)
                throw new ArgumentNullException("condition");
            if (thenSource == null)
                throw new ArgumentNullException("thenSource");
            return s_impl.If(condition, thenSource);
        }
        /// 
        /// If the specified  evaluates true, select the  sequence. Otherwise, return an empty sequence generated on the specified scheduler.
        /// 
        /// The type of the elements in the result sequence.
        /// Condition evaluated to decide which sequence to return.
        /// Sequence returned in case  evaluates true.
        /// Scheduler to generate an empty sequence on in case  evaluates false.
        ///  if  evaluates true; an empty sequence otherwise.
        ///  or  or  is null.
        public static IObservable If(Func condition, IObservable thenSource, IScheduler scheduler)
        {
            if (condition == null)
                throw new ArgumentNullException("condition");
            if (thenSource == null)
                throw new ArgumentNullException("thenSource");
            if (scheduler == null)
                throw new ArgumentNullException("scheduler");
            return s_impl.If(condition, thenSource, scheduler);
        }
        #endregion
        #region + While +
        /// 
        /// Repeats the given  as long as the specified  holds, where the  is evaluated before each repeated  is subscribed to.
        /// 
        /// The type of the elements in the source sequence.
        /// Source to repeat as long as the  function evaluates to true.
        /// Condition that will be evaluated before subscription to the , to determine whether repetition of the source is required.
        /// The observable sequence obtained by concatenating the  sequence as long as the  holds.
        ///  or  is null.
        public static IObservable While(Func condition, IObservable source)
        {
            if (condition == null)
                throw new ArgumentNullException("condition");
            if (source == null)
                throw new ArgumentNullException("source");
            return s_impl.While(condition, source);
        }
        #endregion
    }
}