// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace DotNetCore.CAP.Processor
{
    public class ProcessingContext : IDisposable
    {
        private IServiceScope _scope;

        public ProcessingContext()
        {
        }

        private ProcessingContext(ProcessingContext other)
        {
            Provider = other.Provider;
            CancellationToken = other.CancellationToken;
        }

        public ProcessingContext(
            IServiceProvider provider,
            CancellationToken cancellationToken)
        {
            Provider = provider;
            CancellationToken = cancellationToken;
        }

        public IServiceProvider Provider { get; private set; }

        public CancellationToken CancellationToken { get; }

        public bool IsStopping => CancellationToken.IsCancellationRequested;

        public void Dispose()
        {
            _scope?.Dispose();
        }

        public void ThrowIfStopping()
        {
            CancellationToken.ThrowIfCancellationRequested();
        }

        public ProcessingContext CreateScope()
        {
            var serviceScope = Provider.CreateScope();

            return new ProcessingContext(this)
            {
                _scope = serviceScope,
                Provider = serviceScope.ServiceProvider
            };
        }

        public Task WaitAsync(TimeSpan timeout)
        {
            return Task.Delay(timeout, CancellationToken);
        }
    }
}