using MainShell.Common;
using MW.WorkFlow;
using System;
using System.Threading.Tasks;

namespace MainShell.Process
{
    public class ChipPreparationWaitActivity : ActivityAbstractBase
    {
        private readonly TimeSpan _timeout;
        private readonly bool _consumeOnSuccess;

        public ChipPreparationWaitActivity(string name, TimeSpan? timeout = null, bool consumeOnSuccess = false)
            : base(name)
        {
            _timeout = timeout ?? TimeSpan.FromSeconds(30);
            _consumeOnSuccess = consumeOnSuccess;
        }

        protected override async Task<ActivityResult> OnExecuteAsync(WorkflowContext context, ActivityControl activityControl)
        {
            PreparationAreaService preparationAreaService;
            if (!context.TryGetData<PreparationAreaService>(WorkflowContextKeys.PreparationAreaService, out preparationAreaService) || preparationAreaService == null)
            {
                throw new InvalidOperationException("未在工作流上下文中找到准备区服务。");
            }

            ChipPreparationWaitResult waitResult = await preparationAreaService.WaitUntilReadyAsync(_timeout, activityControl.CancellationToken).ConfigureAwait(false);
            if (!waitResult.Success)
            {
                if (waitResult.IsCanceled)
                {
                    SetWorkflowFailure(context, string.IsNullOrWhiteSpace(waitResult.ErrorMessage) ? "等待芯片后台准备已取消。" : waitResult.ErrorMessage);
                    return ActivityResult.Canceled;
                }

                return Fail(
                    context,
                    MessageKey.ProcessStepFailedWithReason,
                    new object[]
                    {
                        Name,
                        string.IsNullOrWhiteSpace(waitResult.ErrorMessage) ? "等待芯片后台准备失败。" : waitResult.ErrorMessage
                    });
            }

            if (!_consumeOnSuccess)
            {
                return ActivityResult.Success;
            }

            string rejectReason;
            if (preparationAreaService.TryConsumeReady(out rejectReason))
            {
                context.SetData(WorkflowContextKeys.PreparationAreaStatus, preparationAreaService.CurrentStatus);
                return ActivityResult.Success;
            }

            return Fail(
                context,
                MessageKey.ProcessStepFailedWithReason,
                new object[]
                {
                    Name,
                    string.IsNullOrWhiteSpace(rejectReason) ? "芯片后台准备结果自动消费失败。" : rejectReason
                });
        }
    }
}
