using MainShell.Common;
using MainShell.DeviceMaintance.Model;
using MainShell.EventArgsFolder;
using MainShell.Parameter;
using MainShell.ParaSetting.Model;
using MaxwellFramework.Core.Attributes;
using MW.WorkFlow;
using MwFramework.ManagerService;
using Stylet;
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MainShell.Process
{
    [Singleton]
    public class NeedleZCalibrationActivity : ActivityAbstractBase
    {
        private readonly NeedleZCalibrationService _needleZCalibrationService;

       
        public NeedleZCalibrationActivity(NeedleZCalibrationService needleZCalibrationService) : base("NeedleZCalibrationActivity")
        {
            _needleZCalibrationService = needleZCalibrationService ?? throw new ArgumentNullException(nameof(needleZCalibrationService));
        }

        protected override async Task<ActivityResult> OnExecuteAsync(WorkflowContext context, ActivityControl activityControl)
        {
            NeedleZCalibrationWorkflowData workflowData = GetWorkflowData(context);
            IParamList paramList = workflowData.GetParameterList();
            NeedleCalibrationSetting needleCalibrationSetting = paramList?.GetParameter<NeedleCalibrationSetting>();
            EquipmentParaSysSetting equipmentParaSysSetting = paramList?.GetParameter<EquipmentParaSysSetting>();

            try
            {
                NeedleZCalibrationExecutionContext executionContext = _needleZCalibrationService.CreateExecutionContext(
                    needleCalibrationSetting,
                    equipmentParaSysSetting,
                    workflowData.TouchCount,
                    workflowData.AutoRaiseZ1);
                IReadOnlyList<double> results = await _needleZCalibrationService.ExecuteCalibrationAsync(
                    executionContext,
                    activityControl,
                    workflowData.CancellationToken,
                    result => PublishResult(workflowData, result));
                WriteResults(context, results);
                return ActivityResult.Success;
            }
            catch (InvalidOperationException ex)
            {
                return Fail(context, MessageKey.ProcessStepFailedWithReason, new object[] { Name, ex.Message });
            }
        }

        private static void PublishResult(NeedleZCalibrationWorkflowData workflowData, double result)
        {
            workflowData.EventAggregator?.PublishOnUIThread(new NeedleZCalibrationResultEventArgs(result));
        }

        private static void WriteResults(WorkflowContext context, IReadOnlyList<double> results)
        {
            if (context == null || results == null || results.Count == 0)
            {
                return;
            }

            context.SetData(WorkflowContextKeys.NeedleZCalibrationResults, results);
            context.SetData(WorkflowContextKeys.NeedleZCalibrationLastResult, results.Last());
            context.SetData(WorkflowContextKeys.NeedleZCalibrationAverageResult, results.Average());
        }

        private static NeedleZCalibrationWorkflowData GetWorkflowData(WorkflowContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            NeedleZCalibrationWorkflowData workflowData = null;
            if (!context.TryGetData(WorkflowContextKeys.NeedleZCalibrationWorkflowData, out workflowData) || workflowData == null)
            {
                throw new InvalidOperationException("未提供针头Z对刀工作流数据。");
            }

            return workflowData;
        }

    }
}
