using JM1.JM1Params;
using Maxwell.SemiFramework.DefaultConfig.Vision;
using MaxwellControl.Controls;
using MaxwellFramework.Core.Interfaces;
using MaxWellGeneralLog.Extension;
using MwFramework.Controls.Components;
using MwFramework.Device;
using MwFramework.ManagerService;
using MwFramework.MXJM.ProcessAnalysis.Model;
using MXJM.Common;
using MXJM.Common.EventArgsFolder;
using MXJM.Logic.Operation;
using MXJM.Parameter.SystemSetting;
using MXJM.SystemSetting.ViewModel;
using SemiconductorVisionAlgorithm.SemiParams;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Markup;
using MessageBox = MaxwellControl.Controls.MessageBox;
using Point = System.Windows.Point;

namespace MXJM.Logic.SystemSetting
{
    public class CameraFusionCalibrationMotion02A : DelegateBase
    {
        public override bool Check(object state)
        {
            IoC.Get<IProjectManager>().EnablePageAndDisableOther("视觉标定");
            _device = IoC.Get<GlobalDeviceService>();
            double speed = 50;
            SafeAxisMotion.SetAxisSpeed(_device.Axis_X11, speed);
            SafeAxisMotion.SetAxisSpeed(_device.Axis_Y11, speed);
            SafeAxisMotion.SetAxisSpeed(_device.Axis_X21, speed);
            SafeAxisMotion.SetAxisSpeed(_device.Axis_Y21, speed);
            return true;
        }

        IParamList _paramList;
        GlobalDeviceService _device;
        VisionOperation _visionOperation;
        CameraWaferFusionCalibrationSetting _parameter;
        CameraWaferFusionCalibrationItem _cameraWaferFusionCalibrationItem;
        public Rectangle1 Rectangle { get; set; }
        bool _isCancle = false;

        private Dictionary<int, SemiconductorVisionAlgorithm.SemiParams.Point[,]> _calibWaferData = new Dictionary<int, SemiconductorVisionAlgorithm.SemiParams.Point[,]>();
        private List<double> _x11PosList = new List<double>();
        private SemiconductorVisionAlgorithm.SemiParams.Point[,] _initialwsPos =  new  SemiconductorVisionAlgorithm.SemiParams.Point[0,0];
        SafeAxisMotion motion;

        private int _x11Count = 0;
        private bool _isReDo = false;

        public override void Do(object state)
        {
            try
            {
                _isCancle = false;
                if (_isReDo)
                {
                    _isReDo = false;
                }
                else
                {
                    _calibWaferData.Clear();
                    _x11PosList.Clear();
                }
                var objects=state as object[];
                var pointDic = objects[1] as FusionPoint[,];

                bool isRecheck = Convert.ToBoolean(objects[0]);
                _paramList = IoC.Get<IParameterManager>() as IParamList;
                _parameter = _paramList.GetParameter<CameraWaferFusionCalibrationSetting>();
                _cameraWaferFusionCalibrationItem = _parameter.CameraWaferFusionCalibrationItem;
         
                motion = IoC.Get<SafeAxisMotion>();
                _device = IoC.Get<GlobalDeviceService>();
                _visionOperation = IoC.Get<VisionOperation>();
                double stageY = _device.Axis_Y11.State.ActualPos;
                double waferStep = _cameraWaferFusionCalibrationItem.WaferStepXY;
                string modelFileName = _cameraWaferFusionCalibrationItem.ModelPath;
                string path = System.AppDomain.CurrentDomain.BaseDirectory + modelFileName;

                if (_x11PosList.Count != _cameraWaferFusionCalibrationItem.CountX || _calibWaferData.Count != _cameraWaferFusionCalibrationItem.CountX)
                {
                    _calibWaferData.Clear();
                    _x11PosList.Clear();
                    _x11Count = 0;
                    for (int i = 0; i < _cameraWaferFusionCalibrationItem.CountX; i++)
                    {
                        _x11PosList.Add(0);
                        _calibWaferData.Add(i, new SemiconductorVisionAlgorithm.SemiParams.Point[0, 0]);
                    }
                }


                //相机移到起点  //wafer移到起点
                //motion.SafeMovePHSAndWS(_cameraWaferFusionCalibrationItem.CameraX, stageY, _cameraWaferFusionCalibrationItem.WaferStartX, _cameraWaferFusionCalibrationItem.WaferStartY, isCalib: true);
                if(_cameraWaferFusionCalibrationItem.UseCircleCalib)
                {
                    _initialwsPos = ApprochWSCircleTable(pointDic, _cameraWaferFusionCalibrationItem.WSPlatCalibXPos, stageY, _cameraWaferFusionCalibrationItem.WSApproachXPos,
                                      _cameraWaferFusionCalibrationItem.WSApproachYPos, 0, path);
                }
                else
                _initialwsPos = ApprochWSTable(waferStep, _cameraWaferFusionCalibrationItem.WSPlatCalibXPos, stageY, _cameraWaferFusionCalibrationItem.WSApproachXPos,
                    _cameraWaferFusionCalibrationItem.WSApproachYPos, 0, path);

                int count = 0;

                for (int i = _x11Count; i < _cameraWaferFusionCalibrationItem.CountX; i++)
                {
                    if (_isCancle)
                    {
                        return;
                    }

                    count++;


                    double x1 = _cameraWaferFusionCalibrationItem.CameraX + _cameraWaferFusionCalibrationItem.StepX * i;
                    double y1 = _device.Axis_Y11.State.ActualPos;

                    double x2 = _cameraWaferFusionCalibrationItem.WaferStartX + _cameraWaferFusionCalibrationItem.StepX * i;
                    double y2 = _cameraWaferFusionCalibrationItem.WaferStartY;


                    //如果是检查 ，X1=1/2 * StepX  Y1是stage的那个黑色平台 Y2是ws 
                    if (isRecheck)
                    {
                        x1 = _cameraWaferFusionCalibrationItem.CameraX - 0.5 * _cameraWaferFusionCalibrationItem.StepX + _cameraWaferFusionCalibrationItem.StepX * i;
                        y1 = _device.Axis_Y11.State.ActualPos;
                        x2 = _cameraWaferFusionCalibrationItem.WaferStartX - 0.5 * _cameraWaferFusionCalibrationItem.StepX + _cameraWaferFusionCalibrationItem.StepX * i;
                        y2 = _cameraWaferFusionCalibrationItem.WaferStartY;
                    }
                    SemiconductorVisionAlgorithm.SemiParams.Point[,] points = null;
                    if (_cameraWaferFusionCalibrationItem.UseCircleCalib)
                    {
                        points = ApprochWSCircleTable(pointDic, x1, y1, x2, y2, count, path);
                    }
                    else
                    points = ApprochWSTable(waferStep, x1, y1, x2, y2, count, path);
                    if (_calibWaferData.ContainsKey(i))
                    {
                        _calibWaferData[i] = points;
                    }
                    else
                    {
                        _calibWaferData.Add(i, points);
                    }

                    _x11PosList[i] = _device.Axis_X11.State.ActualPos;
                }

                //当count为1时，认为是老标定
                if (_cameraWaferFusionCalibrationItem.WaferCountXY == 1)
                {
                    SemiconductorVisionAlgorithm.SemiParams.Point ini_wsPos = new SemiconductorVisionAlgorithm.SemiParams.Point(_cameraWaferFusionCalibrationItem.WSApproachXPos,
                 _cameraWaferFusionCalibrationItem.WSApproachYPos);
                    List<SemiconductorVisionAlgorithm.SemiParams.Point> wsList = new List<SemiconductorVisionAlgorithm.SemiParams.Point>();
                    _calibWaferData.ForEach(p =>
                    {
                        if (p.Value.Length > 0)
                        {
                            wsList.Add(p.Value[0, 0]);
                        }
                    });
                    //JM1Vision.JM1Manager.Instance.cal_interpolate_affine(_cameraWaferFusionCalibrationItem.WSPlatCalibXPos, ini_wsPos,
                    //    _x11PosList, wsList);
                }
                else
                {
                    SemiconductorVisionAlgorithm.SemiParams.Point[,] _circleInitialwsPos = new SemiconductorVisionAlgorithm.SemiParams.Point[0, 0];
                    Dictionary<int, SemiconductorVisionAlgorithm.SemiParams.Point[,]> _circleCalibData = new Dictionary<int, SemiconductorVisionAlgorithm.SemiParams.Point[,]>(_calibWaferData.Count);
                    if (_cameraWaferFusionCalibrationItem.UseCircleCalib)
                    {
                        ConvertToRecheckDiePoint(ref _initialwsPos);
                       
                        foreach (var item in _calibWaferData)
                        {
                            var rows=item.Value.GetLength(0);
                            var cols=item.Value.GetLength(1);
                            RecheckDiePoint[,] recheckDiePoint = new RecheckDiePoint[rows, cols];
                            for (int i = 0; i < rows; i++)
                            {
                                for (int j = 0; j < cols; j++)
                                {
                                    var point=item.Value[i, j];
                                    bool isexist = !(point.X == 0 && point.Y == 0);
                                    var recheckPoint = new RecheckDiePoint
                                    {
                                        X = point.X,
                                        Y = point.Y,
                                        State = isexist
                                    };
                                    recheckDiePoint[i,j]= recheckPoint;
                                }
                            }
                            JM1Vision.JM1Manager.Instance.FillCalibData(recheckDiePoint, _cameraWaferFusionCalibrationItem.WaferStepXY,
                                _cameraWaferFusionCalibrationItem.WaferCountXY,out RecheckDiePoint[,] resutPoint);
                            SemiconductorVisionAlgorithm.SemiParams.Point[,] finalResultPoint = new SemiconductorVisionAlgorithm.SemiParams.Point[rows, cols];
                            for (int i = 0; i < rows; i++)
                            {
                                for (int j = 0; j < cols; j++)
                                {
                                    var point = resutPoint[i, j];

                                    finalResultPoint[i, j] = new SemiconductorVisionAlgorithm.SemiParams.Point
                                    {
                                        X = point.X,
                                        Y = point.Y,
                                    };
                                }
                            }
                            _circleCalibData[item.Key] = finalResultPoint;
                        }
                        _calibWaferData= _circleCalibData;

                    }

                    JM1Vision.JM1Manager.Instance.cal_wafer_fusion(_calibWaferData, _x11PosList, _initialwsPos, _cameraWaferFusionCalibrationItem.StepX, waferStep, _cameraWaferFusionCalibrationItem.WaferCountXY);
                }
                    

                string filePath = System.AppDomain.CurrentDomain.BaseDirectory + @"CalibData";
                JM1Vision.JM1Manager.Instance.Save(filePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                if (MessageBox.Show("是否继续！", null, "是否继续", MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.Cancel) == MessageBoxResult.OK)
                {
                    _isReDo = true;
                    this.Do(state);
                }
                else
                {
                    _isReDo = false;
                }
            }

            MessageBox.Show("校正完成");
        }

        private void ConvertToRecheckDiePoint(ref SemiconductorVisionAlgorithm.SemiParams.Point[,] pointArray)
        {
            var rows = pointArray.GetLength(0);
            var cols = pointArray.GetLength(1);
            RecheckDiePoint[,] recheckDiePoint =new RecheckDiePoint[rows, cols];
            for (int i = 0; i < recheckDiePoint.GetLength(0); i++)
            {
                for (int j = 0; j < recheckDiePoint.GetLength(1); j++)
                {
                    var point = pointArray[i, j];
                    bool isExist = !(point.X == 0 && point.Y == 0);
                    recheckDiePoint[i, j] = new RecheckDiePoint
                    {
                        X = point.X,
                        Y = point.Y,
                        State = isExist
                    };
                }
            }
            JM1Vision.JM1Manager.Instance.FillCalibData(recheckDiePoint, _cameraWaferFusionCalibrationItem.WaferStepXY,
                               _cameraWaferFusionCalibrationItem.WaferCountXY, out RecheckDiePoint[,] resutPoint);

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    var point = resutPoint[i, j];

                    pointArray[i, j] = new SemiconductorVisionAlgorithm.SemiParams.Point
                    {
                        X = point.X,
                        Y = point.Y,
                    };
                }
            }
        }

        private SemiconductorVisionAlgorithm.SemiParams.Point[,] ApprochWSTable (double waferStep, double x1,double y1,double x2,double y2, int count,string path)
        {
            SemiconductorVisionAlgorithm.SemiParams.Point[,] pointArray =
                new SemiconductorVisionAlgorithm.SemiParams.Point[_cameraWaferFusionCalibrationItem.WaferCountXY, _cameraWaferFusionCalibrationItem.WaferCountXY];
            motion.MovePHSAndWS(x1, y1, x2, y2);
            for (int y = 0; y < _cameraWaferFusionCalibrationItem.WaferCountXY; y++)
            {
                double waferY = y * waferStep + y2;
                for (int x = 0; x < _cameraWaferFusionCalibrationItem.WaferCountXY; x++)
                {
                    int index = y % 2 == 0 ? x : _cameraWaferFusionCalibrationItem.WaferCountXY - 1 - x;
                    double waferX = index * waferStep + x2;
                   
                    if (_isCancle)
                    {
                        return pointArray;
                    }

                    motion.SafeMoveWS(waferX, waferY);

                    Point point = new Point();

                    //相机拍照
                    if (!_visionOperation.ApproachPointCircle(_device.Camera_ExtendWS, _device.Axis_X21, _device.Axis_Y21,
                        path, Rectangle, out point))
                    {
                        Cancel();
                    }

                    Thread.Sleep(100);
                    AxisAndPixelPointItem item = new AxisAndPixelPointItem();
                    item.Id = count;
                    item.AxisX1 = _device.Axis_X11.State.ActualPos;
                    item.AxisX2 = _device.Axis_X21.State.ActualPos;
                    item.AxisY1 = _device.Axis_Y11.State.ActualPos;
                    item.AxisY2 = _device.Axis_Y21.State.ActualPos;
                    item.PixelX = point.X;
                    item.PixelY = point.Y;

                    pointArray[index, y] = new SemiconductorVisionAlgorithm.SemiParams.Point(item.AxisX2, item.AxisY2);
                    //IoC.Get<IEventAggregator>()?.Publish(new WaferFusionCalibrationResultEventArgs(item));
                }
            }

            return pointArray;
        }

        private SemiconductorVisionAlgorithm.SemiParams.Point[,] ApprochWSCircleTable(FusionPoint[,] tableDic, double x1, double y1, double x2, double y2, int count, string path)
        {
            SemiconductorVisionAlgorithm.SemiParams.Point[,] pointArray =
                new SemiconductorVisionAlgorithm.SemiParams.Point[_cameraWaferFusionCalibrationItem.WaferCountXY, _cameraWaferFusionCalibrationItem.WaferCountXY];
            motion.MovePHSAndWS(x1, y1, x2, y2);
            var offsetX = x2 - _cameraWaferFusionCalibrationItem.CenterX;
            var rowCount = tableDic.GetLength(0);
            var columnCount = tableDic.GetLength(1);
            for (int y = 0; y < rowCount; y++)
            {
                
                for (int x = 0; x < columnCount; x++)
                {
                    int index = y % 2 == 0 ? x : columnCount - 1 - x;
                  

                    if (_isCancle)
                    {
                        return pointArray;
                    }
                    //var movePoint = tableDic[y,x];
                    var movePoint = tableDic[y, index];
                    if (!movePoint.IsExist)
                    {
                        pointArray[index, y] = new SemiconductorVisionAlgorithm.SemiParams.Point(0, 0);
                        continue;
                    }
                    motion.SafeMoveWS(movePoint.X+ offsetX, movePoint.Y);

                    Point point = new Point();

                    //相机拍照
                    if (!_visionOperation.ApproachPointCircle(_device.Camera_ExtendWS, _device.Axis_X21, _device.Axis_Y21,
                        path, Rectangle, out point))
                    {
                        Cancel();
                    }

                    Thread.Sleep(100);
                    AxisAndPixelPointItem item = new AxisAndPixelPointItem();
                    item.Id = count;
                    item.AxisX1 = _device.Axis_X11.State.ActualPos;
                    item.AxisX2 = _device.Axis_X21.State.ActualPos;
                    item.AxisY1 = _device.Axis_Y11.State.ActualPos;
                    item.AxisY2 = _device.Axis_Y21.State.ActualPos;
                    item.PixelX = point.X;
                    item.PixelY = point.Y;

                    pointArray[index, y] = new SemiconductorVisionAlgorithm.SemiParams.Point(item.AxisX2, item.AxisY2);
                    //IoC.Get<IEventAggregator>()?.Publish(new WaferFusionCalibrationResultEventArgs(item));
                }
            }

            return pointArray;
        }

        public override void Finish()
        {
            base.Finish();
            IoC.Get<IProjectManager>().SwitchState();
        }

        public override void Cancel()
        {
            _isCancle = true;
        }

    }


}
