using System;
using System.Reactive.Disposables;

namespace System.Reactive
{
	internal abstract class SafeObserver<TSource> : ISafeObserver<TSource>, IObserver<TSource>, IDisposable
	{
		public static ISafeObserver<TSource> Wrap(IObserver<TSource> observer)
		{
			AnonymousObserver<TSource> anonymousObserver = observer as AnonymousObserver<TSource>;
			if (anonymousObserver != null)
			{
				return anonymousObserver.MakeSafe();
			}
			return new SafeObserver<TSource>.WrappingSafeObserver(observer);
		}

		public abstract void OnNext(TSource value);

		public abstract void OnError(Exception error);

		public abstract void OnCompleted();

		public void SetResource(IDisposable resource)
		{
			Disposable.SetSingle(ref this._disposable, resource);
		}

		public void Dispose()
		{
			this.Dispose(true);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				Disposable.TryDispose(ref this._disposable);
			}
		}

		private IDisposable _disposable;

		private sealed class WrappingSafeObserver : SafeObserver<TSource>
		{
			public WrappingSafeObserver(IObserver<TSource> observer)
			{
				this._observer = observer;
			}

			public override void OnNext(TSource value)
			{
				bool flag = false;
				try
				{
					this._observer.OnNext(value);
					flag = true;
				}
				finally
				{
					if (!flag)
					{
						base.Dispose();
					}
				}
			}

			public override void OnError(Exception error)
			{
				try
				{
					this._observer.OnError(error);
				}
				finally
				{
					if (this != null)
					{
						((IDisposable)this).Dispose();
					}
				}
			}

			public override void OnCompleted()
			{
				try
				{
					this._observer.OnCompleted();
				}
				finally
				{
					if (this != null)
					{
						((IDisposable)this).Dispose();
					}
				}
			}

			private readonly IObserver<TSource> _observer;
		}
	}
}
