using System;
using System.Reactive.Disposables;
using System.Threading;

namespace System.Reactive.Concurrency
{
	public class SynchronizationContextScheduler : LocalScheduler
	{
		public SynchronizationContextScheduler(SynchronizationContext context)
		{
			if (context == null)
			{
				throw new ArgumentNullException("context");
			}
			this._context = context;
			this._alwaysPost = true;
		}

		public SynchronizationContextScheduler(SynchronizationContext context, bool alwaysPost)
		{
			if (context == null)
			{
				throw new ArgumentNullException("context");
			}
			this._context = context;
			this._alwaysPost = alwaysPost;
		}

		public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (!this._alwaysPost && this._context == SynchronizationContext.Current)
			{
				return action(this, state);
			}
			SingleAssignmentDisposable d = new SingleAssignmentDisposable();
			this._context.PostWithStartComplete(delegate
			{
				if (!d.IsDisposed)
				{
					d.Disposable = action(this, state);
				}
			});
			return d;
		}

		public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			TimeSpan timeSpan = Scheduler.Normalize(dueTime);
			if (timeSpan.Ticks == 0L)
			{
				return this.Schedule<TState>(state, action);
			}
			return DefaultScheduler.Instance.Schedule<TState>(state, timeSpan, (IScheduler _, TState state1) => this.Schedule<TState>(state1, action));
		}

		private readonly SynchronizationContext _context;

		private readonly bool _alwaysPost;
	}
}
