using System;

namespace System.Reactive.Linq.ObservableImpl
{
	internal sealed class MostRecent<TSource> : PushToPullAdapter<TSource, TSource>
	{
		public MostRecent(IObservable<TSource> source, TSource initialValue)
			: base(source)
		{
			this._initialValue = initialValue;
		}

		protected override PushToPullSink<TSource, TSource> Run()
		{
			return new MostRecent<TSource>._(this._initialValue);
		}

		private readonly TSource _initialValue;

		private sealed class _ : PushToPullSink<TSource, TSource>
		{
			public _(TSource initialValue)
			{
				this._kind = NotificationKind.OnNext;
				this._value = initialValue;
			}

			public override void OnNext(TSource value)
			{
				this._value = value;
				this._kind = NotificationKind.OnNext;
			}

			public override void OnError(Exception error)
			{
				base.Dispose();
				this._error = error;
				this._kind = NotificationKind.OnError;
			}

			public override void OnCompleted()
			{
				base.Dispose();
				this._kind = NotificationKind.OnCompleted;
			}

			public override bool TryMoveNext(out TSource current)
			{
				switch (this._kind)
				{
				case NotificationKind.OnNext:
					current = this._value;
					return true;
				case NotificationKind.OnError:
					this._error.Throw();
					break;
				}
				current = default(TSource);
				return false;
			}

			private volatile NotificationKind _kind;

			private TSource _value;

			private Exception _error;
		}
	}
}
