using System;

namespace System.Reactive.Linq.ObservableImpl
{
	internal sealed class If<TResult> : Producer<TResult, If<TResult>._>, IEvaluatableObservable<TResult>
	{
		public If(Func<bool> condition, IObservable<TResult> thenSource, IObservable<TResult> elseSource)
		{
			this._condition = condition;
			this._thenSource = thenSource;
			this._elseSource = elseSource;
		}

		public IObservable<TResult> Eval()
		{
			if (!this._condition())
			{
				return this._elseSource;
			}
			return this._thenSource;
		}

		protected override If<TResult>._ CreateSink(IObserver<TResult> observer)
		{
			return new If<TResult>._(this, observer);
		}

		protected override void Run(If<TResult>._ sink)
		{
			sink.Run();
		}

		private readonly Func<bool> _condition;

		private readonly IObservable<TResult> _thenSource;

		private readonly IObservable<TResult> _elseSource;

		internal sealed class _ : IdentitySink<TResult>
		{
			public _(If<TResult> parent, IObserver<TResult> observer)
				: base(observer)
			{
				this._parent = parent;
			}

			public void Run()
			{
				IObservable<TResult> observable;
				try
				{
					observable = this._parent.Eval();
				}
				catch (Exception ex)
				{
					base.ForwardOnError(ex);
					return;
				}
				base.SetUpstream(observable.SubscribeSafe(this));
			}

			private readonly If<TResult> _parent;
		}
	}
}
