using System;
using System.Runtime.CompilerServices;

namespace System.Threading.Channels
{
	[Nullable(0)]
	[NullableContext(1)]
	public static class Channel
	{
		public static Channel<T> CreateUnbounded<[Nullable(2)] T>()
		{
			return new UnboundedChannel<T>(true);
		}

		public static Channel<T> CreateUnbounded<[Nullable(2)] T>(UnboundedChannelOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (!options.SingleReader)
			{
				return new UnboundedChannel<T>(!options.AllowSynchronousContinuations);
			}
			return new SingleConsumerUnboundedChannel<T>(!options.AllowSynchronousContinuations);
		}

		public static Channel<T> CreateBounded<[Nullable(2)] T>(int capacity)
		{
			if (capacity < 1)
			{
				throw new ArgumentOutOfRangeException("capacity");
			}
			return new BoundedChannel<T>(capacity, BoundedChannelFullMode.Wait, true, null);
		}

		public static Channel<T> CreateBounded<[Nullable(2)] T>(BoundedChannelOptions options)
		{
			return Channel.CreateBounded<T>(options, null);
		}

		public static Channel<T> CreateBounded<[Nullable(2)] T>(BoundedChannelOptions options, [Nullable(new byte[] { 2, 1 })] Action<T> itemDropped)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			return new BoundedChannel<T>(options.Capacity, options.FullMode, !options.AllowSynchronousContinuations, itemDropped);
		}
	}
}
