using System;
using System.Collections.Generic;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;

namespace System.Reactive.Linq.ObservableImpl
{
	internal sealed class ToObservableRecursive<TSource> : Producer<TSource, ToObservableRecursive<TSource>._>
	{
		public ToObservableRecursive(IEnumerable<TSource> source, IScheduler scheduler)
		{
			this._source = source;
			this._scheduler = scheduler;
		}

		protected override ToObservableRecursive<TSource>._ CreateSink(IObserver<TSource> observer)
		{
			return new ToObservableRecursive<TSource>._(observer);
		}

		protected override void Run(ToObservableRecursive<TSource>._ sink)
		{
			sink.Run(this._source, this._scheduler);
		}

		private readonly IEnumerable<TSource> _source;

		private readonly IScheduler _scheduler;

		internal sealed class _ : IdentitySink<TSource>
		{
			public _(IObserver<TSource> observer)
				: base(observer)
			{
			}

			public void Run(IEnumerable<TSource> source, IScheduler scheduler)
			{
				try
				{
					this._enumerator = source.GetEnumerator();
				}
				catch (Exception ex)
				{
					base.ForwardOnError(ex);
					return;
				}
				scheduler.Schedule<ToObservableRecursive<TSource>._>(this, (IScheduler innerScheduler, ToObservableRecursive<TSource>._ @this) => @this.LoopRec(innerScheduler));
			}

			protected override void Dispose(bool disposing)
			{
				base.Dispose(disposing);
				if (disposing)
				{
					this._disposed = true;
				}
			}

			private IDisposable LoopRec(IScheduler scheduler)
			{
				bool flag = false;
				Exception ex = null;
				TSource tsource = default(TSource);
				IEnumerator<TSource> enumerator = this._enumerator;
				if (this._disposed)
				{
					this._enumerator.Dispose();
					this._enumerator = null;
					return Disposable.Empty;
				}
				try
				{
					if (flag = enumerator.MoveNext())
					{
						tsource = enumerator.Current;
					}
				}
				catch (Exception ex)
				{
				}
				if (ex != null)
				{
					enumerator.Dispose();
					this._enumerator = null;
					base.ForwardOnError(ex);
					return Disposable.Empty;
				}
				if (!flag)
				{
					enumerator.Dispose();
					this._enumerator = null;
					base.ForwardOnCompleted();
					return Disposable.Empty;
				}
				base.ForwardOnNext(tsource);
				scheduler.Schedule<ToObservableRecursive<TSource>._>(this, (IScheduler innerScheduler, ToObservableRecursive<TSource>._ @this) => @this.LoopRec(innerScheduler));
				return Disposable.Empty;
			}

			private IEnumerator<TSource> _enumerator;

			private volatile bool _disposed;
		}
	}
}
