using System;

namespace System.Reactive.Linq.ObservableImpl
{
	internal sealed class Defer<TValue> : Producer<TValue, Defer<TValue>._>, IEvaluatableObservable<TValue>
	{
		public Defer(Func<IObservable<TValue>> observableFactory)
		{
			this._observableFactory = observableFactory;
		}

		protected override Defer<TValue>._ CreateSink(IObserver<TValue> observer)
		{
			return new Defer<TValue>._(this._observableFactory, observer);
		}

		protected override void Run(Defer<TValue>._ sink)
		{
			sink.Run();
		}

		public IObservable<TValue> Eval()
		{
			return this._observableFactory();
		}

		private readonly Func<IObservable<TValue>> _observableFactory;

		internal sealed class _ : IdentitySink<TValue>
		{
			public _(Func<IObservable<TValue>> observableFactory, IObserver<TValue> observer)
				: base(observer)
			{
				this._observableFactory = observableFactory;
			}

			public void Run()
			{
				IObservable<TValue> observable = null;
				try
				{
					observable = this._observableFactory();
				}
				catch (Exception ex)
				{
					base.ForwardOnError(ex);
					return;
				}
				this.Run(observable);
			}

			private readonly Func<IObservable<TValue>> _observableFactory;
		}
	}
}
