namespace Caliburn.Micro.Core {
    using System;
    using System.Threading.Tasks;
    /// 
    /// A couroutine that encapsulates an .
    /// 
    public class TaskResult : IResult {
        readonly Task innerTask;
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The task.
        public TaskResult(Task task) {
            innerTask = task;
        }
        /// 
        /// Executes the result using the specified context.
        /// 
        /// The context.
        public void Execute(CoroutineExecutionContext context) {
            if (innerTask.IsCompleted)
                OnCompleted(innerTask);
            else
                innerTask.ContinueWith(OnCompleted,
                    System.Threading.SynchronizationContext.Current != null
                        ? TaskScheduler.FromCurrentSynchronizationContext()
                        : TaskScheduler.Current);
        }
        /// 
        /// Called when the asynchronous task has completed.
        /// 
        /// The completed task.
        protected virtual void OnCompleted(Task task) {
            Completed(this, new ResultCompletionEventArgs {WasCancelled = task.IsCanceled, Error = task.Exception});
        }
        /// 
        /// Occurs when execution has completed.
        /// 
        public event EventHandler Completed = delegate { };
    }
    /// 
    /// A couroutine that encapsulates an .
    /// 
    /// The type of the result.
    public class TaskResult : TaskResult, IResult {
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The task.
        public TaskResult(Task task)
            : base(task) {
        }
        /// 
        /// Gets the result of the asynchronous operation.
        /// 
        public TResult Result { get; private set; }
        /// 
        /// Called when the asynchronous task has completed.
        /// 
        /// The completed task.
        protected override void OnCompleted(Task task) {
            if (!task.IsFaulted && !task.IsCanceled)
                Result = ((Task) task).Result;
            base.OnCompleted(task);
        }
    }
}