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

namespace System.Reactive.Linq.ObservableImpl
{
	internal abstract class PushToPullSink<TSource, TResult> : IObserver<TSource>, IEnumerator<TResult>, IDisposable, IEnumerator
	{
		public abstract void OnNext(TSource value);

		public abstract void OnError(Exception error);

		public abstract void OnCompleted();

		public abstract bool TryMoveNext(out TResult current);

		public bool MoveNext()
		{
			if (!this._done)
			{
				TResult tresult;
				if (this.TryMoveNext(out tresult))
				{
					this.Current = tresult;
					return true;
				}
				this._done = true;
				this.Dispose();
			}
			return false;
		}

		public TResult Current { get; private set; }

		object IEnumerator.Current
		{
			get
			{
				return this.Current;
			}
		}

		public void Reset()
		{
			throw new NotSupportedException();
		}

		public void Dispose()
		{
			Disposable.TryDispose(ref this._upstream);
		}

		public void SetUpstream(IDisposable d)
		{
			Disposable.SetSingle(ref this._upstream, d);
		}

		private IDisposable _upstream;

		private bool _done;
	}
}
