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

namespace MainShell.Process
{
    public class ChipUnloadActivity : ActivityAbstractBase
    {
        private readonly TimeSpan _timeout;

        public ChipUnloadActivity(string name, TimeSpan? timeout = null)
            : base(name)
        {
            _timeout = timeout ?? TimeSpan.FromSeconds(30);
        }

        protected override async Task<ActivityResult> OnExecuteAsync(WorkflowContext context, ActivityControl activityControl)
        {
            activityControl.ThrowIfCancellationRequested();

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

            CurrentChipStateService currentChipStateService;
            if (!context.TryGetData<CurrentChipStateService>(WorkflowContextKeys.CurrentChipStateService, out currentChipStateService) || currentChipStateService == null)
            {
                throw new InvalidOperationException("未在工作流上下文中找到当前芯片状态服务。");
            }

            AutoProductionRuntimeStateService autoProductionRuntimeStateService;
            if (!context.TryGetData<AutoProductionRuntimeStateService>(WorkflowContextKeys.AutoProductionRuntimeStateService, out autoProductionRuntimeStateService) || autoProductionRuntimeStateService == null)
            {
                throw new InvalidOperationException("未在工作流上下文中找到自动流程运行态服务。");
            }

            if (currentChipStateService.CurrentState == CurrentChipLifecycleState.Empty)
            {
                autoProductionRuntimeStateService.SetCurrentChipRemainingCount(0);
                context.SetData(WorkflowContextKeys.CurrentChipState, CurrentChipLifecycleState.Empty);
                context.SetData(WorkflowContextKeys.PendingChipLoad, true);
                context.SetData(WorkflowContextKeys.PreparationAreaStatus, preparationAreaService.CurrentStatus);
                context.SetData(WorkflowContextKeys.CurrentChipRemainingCount, autoProductionRuntimeStateService.CurrentChipRemainingCount);
                return ActivityResult.Success;
            }

            currentChipStateService.SetState(CurrentChipLifecycleState.Unloading);
            context.SetData(WorkflowContextKeys.CurrentChipState, CurrentChipLifecycleState.Unloading);

            ChipPreparationRequest request = new ChipPreparationRequest
            {
                RecipeName = ResolveRecipeName(context),
                Action = ChipPreparationAction.Unload,
                SourceStepId = ResolveSourceStepId(context)
            };

            string rejectReason;
            if (!preparationAreaService.TryRequestPrepare(request, out rejectReason))
            {
                return Fail(
                    context,
                    MessageKey.ProcessStepFailedWithReason,
                    new object[]
                    {
                        Name,
                        string.IsNullOrWhiteSpace(rejectReason) ? "芯片下料请求失败。" : rejectReason
                    });
            }

            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 (!preparationAreaService.TryConsumeReady(out rejectReason))
            {
                return Fail(
                    context,
                    MessageKey.ProcessStepFailedWithReason,
                    new object[]
                    {
                        Name,
                        string.IsNullOrWhiteSpace(rejectReason) ? "芯片下料结果消费失败。" : rejectReason
                    });
            }

                currentChipStateService.SetState(CurrentChipLifecycleState.Empty);
                autoProductionRuntimeStateService.SetCurrentChipRemainingCount(0);
                context.SetData(WorkflowContextKeys.PreparationAreaStatus, preparationAreaService.CurrentStatus);
            context.SetData(WorkflowContextKeys.CurrentChipState, CurrentChipLifecycleState.Empty);
            context.SetData(WorkflowContextKeys.PendingChipLoad, true);
                context.SetData(WorkflowContextKeys.CurrentChipRemainingCount, autoProductionRuntimeStateService.CurrentChipRemainingCount);
            return ActivityResult.Success;
        }

        private static string ResolveRecipeName(WorkflowContext context)
        {
            RecipeManager recipeManager;
            if (context.TryGetData<RecipeManager>(WorkflowContextKeys.RecipeManager, out recipeManager) &&
                recipeManager != null &&
                recipeManager.CurrentWaferRecipe != null)
            {
                return recipeManager.CurrentWaferRecipe.RecipeName;
            }

            return string.Empty;
        }

        private static string ResolveSourceStepId(WorkflowContext context)
        {
            string stepId;
            if (context.TryGetData<string>(WorkflowContextKeys.CurrentStepId, out stepId))
            {
                return stepId;
            }

            return string.Empty;
        }
    }
}