namespace Everbytes.Collections
{
    using System.Threading;
    using System.Threading.Tasks;

    /// <summary>
    ///     Represents an abstract item awaiter.
    /// </summary>
    internal interface IAwaiter<T>
    {
        /// <summary>
        ///     The task that's completed when the awaiter gets the result.
        /// </summary>
        Task<T> Task { get; }

        /// <summary>
        ///     <para>Attempts to complete the awaiter with a specified result.</para>
        ///     <para>Returns false if the awaiter has been canceled.</para>
        /// </summary>
        bool TrySetResult(T result);
    }

    /// <summary>
    ///     A simple <see cref="TaskCompletionSource{TResult}" /> wrapper that implements <see cref="IAwaiter{T}" />.
    /// </summary>
    internal class CompletionSourceAwaiter<T> : IAwaiter<T>
    {
        private readonly TaskCompletionSource<T> _completionSource;

        public CompletionSourceAwaiter(CancellationToken cancellationToken)
        {
            _completionSource = new TaskCompletionSource<T>();

            cancellationToken.Register(
                state =>
                {
                    var awaiter = state as TaskCompletionSource<T>;
                    awaiter.TrySetCanceled();
                },
                _completionSource,
                false);
        }

        #region IAwaiter<T> Members

        public bool TrySetResult(T result)
        {
            return _completionSource.TrySetResult(result);
        }

        public Task<T> Task
        {
            get { return _completionSource.Task; }
        }

        #endregion
    }
}
