using System;
using System.Collections.Generic;

namespace System.Reactive.Linq.ObservableImpl
{
	internal sealed class Min<TSource> : Producer<TSource, Min<TSource>._>
	{
		public Min(IObservable<TSource> source, IComparer<TSource> comparer)
		{
			this._source = source;
			this._comparer = comparer;
		}

		protected override Min<TSource>._ CreateSink(IObserver<TSource> observer)
		{
			if (default(TSource) != null)
			{
				return new Min<TSource>.NonNull(this._comparer, observer);
			}
			return new Min<TSource>.Null(this._comparer, observer);
		}

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

		private readonly IObservable<TSource> _source;

		private readonly IComparer<TSource> _comparer;

		internal abstract class _ : IdentitySink<TSource>
		{
			protected _(IComparer<TSource> comparer, IObserver<TSource> observer)
				: base(observer)
			{
				this._comparer = comparer;
			}

			protected readonly IComparer<TSource> _comparer;
		}

		private sealed class NonNull : Min<TSource>._
		{
			public NonNull(IComparer<TSource> comparer, IObserver<TSource> observer)
				: base(comparer, observer)
			{
			}

			public override void OnNext(TSource value)
			{
				if (this._hasValue)
				{
					int num;
					try
					{
						num = this._comparer.Compare(value, this._lastValue);
					}
					catch (Exception ex)
					{
						base.ForwardOnError(ex);
						return;
					}
					if (num < 0)
					{
						this._lastValue = value;
						return;
					}
				}
				else
				{
					this._hasValue = true;
					this._lastValue = value;
				}
			}

			public override void OnError(Exception error)
			{
				base.ForwardOnError(error);
			}

			public override void OnCompleted()
			{
				if (!this._hasValue)
				{
					base.ForwardOnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
					return;
				}
				base.ForwardOnNext(this._lastValue);
				base.ForwardOnCompleted();
			}

			private bool _hasValue;

			private TSource _lastValue;
		}

		private sealed class Null : Min<TSource>._
		{
			public Null(IComparer<TSource> comparer, IObserver<TSource> observer)
				: base(comparer, observer)
			{
			}

			public override void OnNext(TSource value)
			{
				if (value != null)
				{
					if (this._lastValue == null)
					{
						this._lastValue = value;
						return;
					}
					int num;
					try
					{
						num = this._comparer.Compare(value, this._lastValue);
					}
					catch (Exception ex)
					{
						base.ForwardOnError(ex);
						return;
					}
					if (num < 0)
					{
						this._lastValue = value;
					}
				}
			}

			public override void OnCompleted()
			{
				base.ForwardOnNext(this._lastValue);
				base.ForwardOnCompleted();
			}

			private TSource _lastValue;
		}
	}
}
