using System;
using System.Collections.Generic;

namespace System.Reactive.Linq.ObservableImpl
{
	internal sealed class Distinct<TSource, TKey> : Producer<TSource, Distinct<TSource, TKey>._>
	{
		public Distinct(IObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
		{
			this._source = source;
			this._keySelector = keySelector;
			this._comparer = comparer;
		}

		protected override Distinct<TSource, TKey>._ CreateSink(IObserver<TSource> observer)
		{
			return new Distinct<TSource, TKey>._(this, observer);
		}

		protected override void Run(Distinct<TSource, TKey>._ sink)
		{
			sink.Run(this._source);
		}

		private readonly IObservable<TSource> _source;

		private readonly Func<TSource, TKey> _keySelector;

		private readonly IEqualityComparer<TKey> _comparer;

		internal sealed class _ : IdentitySink<TSource>
		{
			public _(Distinct<TSource, TKey> parent, IObserver<TSource> observer)
				: base(observer)
			{
				this._keySelector = parent._keySelector;
				this._hashSet = new HashSet<TKey>(parent._comparer);
			}

			public override void OnNext(TSource value)
			{
				bool flag = false;
				try
				{
					TKey tkey = this._keySelector(value);
					flag = this._hashSet.Add(tkey);
				}
				catch (Exception ex)
				{
					base.ForwardOnError(ex);
					return;
				}
				if (flag)
				{
					base.ForwardOnNext(value);
				}
			}

			private readonly Func<TSource, TKey> _keySelector;

			private readonly HashSet<TKey> _hashSet;
		}
	}
}
