using System;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Runtime.CompilerServices;

namespace System.Reactive
{
	internal abstract class BasicProducer<TSource> : IProducer<TSource>, IObservable<TSource>
	{
		public IDisposable Subscribe(IObserver<TSource> observer)
		{
			if (observer == null)
			{
				throw new ArgumentNullException("observer");
			}
			return this.SubscribeRaw(observer, true);
		}

		public IDisposable SubscribeRaw(IObserver<TSource> observer, bool enableSafeguard)
		{
			ISafeObserver<TSource> safeObserver = null;
			if (enableSafeguard)
			{
				safeObserver = (observer = SafeObserver<TSource>.Wrap(observer));
			}
			IDisposable disposable;
			if (CurrentThreadScheduler.IsScheduleRequired)
			{
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				CurrentThreadScheduler.Instance.ScheduleAction(new ValueTuple<BasicProducer<TSource>, SingleAssignmentDisposable, IObserver<TSource>>(this, singleAssignmentDisposable, observer), ([TupleElementNames(new string[] { "this", "runAssignable", "observer" })] ValueTuple<BasicProducer<TSource>, SingleAssignmentDisposable, IObserver<TSource>> tuple) => tuple.Item2.Disposable = tuple.Item1.Run(tuple.Item3));
				disposable = singleAssignmentDisposable;
			}
			else
			{
				disposable = this.Run(observer);
			}
			if (safeObserver != null)
			{
				safeObserver.SetResource(disposable);
			}
			return disposable;
		}

		protected abstract IDisposable Run(IObserver<TSource> observer);
	}
}
