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

namespace MainShell.Process
{
    public class PreparationSignalActivity : ActivityAbstractBase
    {
        public PreparationSignalActivity(string name)
            : base(name)
        {
        }

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

            bool pendingChipLoad;
            if (context.TryGetData<bool>(WorkflowContextKeys.PendingChipLoad, out pendingChipLoad) && !pendingChipLoad)
            {
                return Task.FromResult(ActivityResult.Success);
            }

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

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

            string rejectReason;
            if (preparationAreaService.TryRequestPrepare(request, out rejectReason) || CanIgnoreReject(preparationAreaService))
            {
                context.SetData(WorkflowContextKeys.PreparationAreaStatus, preparationAreaService.CurrentStatus);
                return Task.FromResult(ActivityResult.Success);
            }

            return Task.FromResult(Fail(
                context,
                MessageKey.ProcessStepFailedWithReason,
                new object[]
                {
                    Name,
                    string.IsNullOrWhiteSpace(rejectReason) ? "芯片准备信号触发失败。" : rejectReason
                }));
        }

        private static bool CanIgnoreReject(PreparationAreaService preparationAreaService)
        {
            return preparationAreaService.CurrentStatus == ChipPreparationStatus.Preparing ||
                   preparationAreaService.CurrentStatus == ChipPreparationStatus.Prepared ||
                   preparationAreaService.CurrentStatus == ChipPreparationStatus.Loading ||
                   preparationAreaService.CurrentStatus == ChipPreparationStatus.Loaded;
        }

        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;
        }
    }
}