using MainShell.Filewritable;
using MainShell.Hardware;
using MainShell.PageCalib.OriginCalib.Service;
using MXJM.FileWritable;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;

namespace MainShell.PageCalib.OriginCalib.Model
{
    public static class OriginCalibModuleNames
    {
        public const string GantryX1Y1 = "X1Y1";
        public const string GantryX2 = "X2";
        public const string StageY2 = "StageY2";
        public const string WSX3 = "WSX3";
        public const string Z1 = "Z1";
        public const string Z3 = "Z3";
        public const string Z4 = "Z4";
        public const string Z5 = "Z5";
        public const string Z6 = "Z6";
    }

    public class AvoidanceAxisItem
    {
        public string AxisName { get; set; }
        public double Position { get; set; }
    }

    public class CalibrationAxisItem
    {
        public string AxisName { get; set; }
        public double TargetPosition { get; set; }
        public double LastPosition { get; set; }
        public double Offset { get; set; }
        public bool IsCalibrated { get; set; }
    }

    public class OriginCalibModuleItem
    {
        public string ModuleName { get; set; }
        public bool IsIndependent { get; set; }
        public string TemplatePath { get; set; }
        public List<AvoidanceAxisItem> AvoidanceAxes { get; set; } = new List<AvoidanceAxisItem>();
        public List<CalibrationAxisItem> CalibrationAxes { get; set; } = new List<CalibrationAxisItem>();

        [JsonIgnore]
        public ICalibrationPostProcessor PostProcessor { get; set; }

        public void EnsureCollections()
        {
            if (AvoidanceAxes == null)
            {
                AvoidanceAxes = new List<AvoidanceAxisItem>();
            }

            if (CalibrationAxes == null)
            {
                CalibrationAxes = new List<CalibrationAxisItem>();
            }

            if (string.IsNullOrWhiteSpace(TemplatePath))
            {
                TemplatePath = GetDefaultTemplatePath(ModuleName);
            }
        }

        private static string GetDefaultTemplatePath(string moduleName)
        {
            switch (moduleName)
            {
                case OriginCalibModuleNames.GantryX1Y1:
                    return Paths.OriginCalibGantryX1Y1TemplatePath;

                case OriginCalibModuleNames.GantryX2:
                    return Paths.OriginCalibGantryX2TemplatePath;

                case OriginCalibModuleNames.StageY2:
                    return Paths.OriginCalibStageY2TemplatePath;

                case OriginCalibModuleNames.WSX3:
                    return Paths.OriginCalibWSX3TemplatePath;

                default:
                    return Paths.OriginCalibDefaultTemplatePath;
            }
        }
    }

    public class OriginCalibSetting : JsonFileWritableBase
    {
        [JsonIgnore]
        public override string Dir => Paths.CalibSettingPath;

        [JsonIgnore]
        public override string FileName => "OriginCalibSetting.json";

        public List<OriginCalibModuleItem> Modules { get; set; } = new List<OriginCalibModuleItem>();

        public static OriginCalibSetting LoadOrCreate()
        {
            OriginCalibSetting setting = new OriginCalibSetting();
            string path = Path.Combine(setting.Dir, setting.FileName);
            if (File.Exists(path))
            {
                setting.Read(path);
                setting.EnsureCollections();
                return setting;
            }

            setting.Modules = CreateDefaultModules();
            setting.Write(path);
            return setting;
        }

        public void EnsureCollections()
        {
            if (Modules == null)
            {
                Modules = new List<OriginCalibModuleItem>();
            }

            foreach (OriginCalibModuleItem module in Modules)
            {
                if (module != null)
                {
                    module.EnsureCollections();
                }
            }
        }

        private static List<OriginCalibModuleItem> CreateDefaultModules()
        {
            List<OriginCalibModuleItem> modules = new List<OriginCalibModuleItem>
            {
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.GantryX1Y1,
                    IsIndependent = true,
                    TemplatePath = Paths.OriginCalibGantryX1Y1TemplatePath,
                    AvoidanceAxes = new List<AvoidanceAxisItem>
                    {
                        new AvoidanceAxisItem
                        {
                             AxisName=AxisName.Axis_Stage_Y3,
                             Position=0
                        }
                    },
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_X1, TargetPosition = 0.0 },
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_Y1, TargetPosition = 0.0 }
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.GantryX2,
                    IsIndependent = true,
                    TemplatePath = Paths.OriginCalibGantryX2TemplatePath,
                    AvoidanceAxes = new List<AvoidanceAxisItem>
                    {
                        new AvoidanceAxisItem{ AxisName=AxisName.Axis_Stage_Y3, Position= 0  },
                    },
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_X2, TargetPosition = 0.0 },
                        new CalibrationAxisItem { AxisName=AxisName.Axis_PHS_Y1, TargetPosition= 0.0  },
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.StageY2,
                    IsIndependent = true,
                    TemplatePath = Paths.OriginCalibStageY2TemplatePath,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_Stage_Y3, TargetPosition = 0.0 }
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.WSX3,
                    IsIndependent = true,
                    TemplatePath = Paths.OriginCalibWSX3TemplatePath,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_WS_X3, TargetPosition = 0.0 },
                        new CalibrationAxisItem { AxisName=AxisName.Axis_PHS_Y1, TargetPosition= 0.0  },
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.Z1,
                    IsIndependent = true,
                    TemplatePath = string.Empty,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_Z1, TargetPosition = 0.0 },
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.Z3,
                    IsIndependent = true,
                    TemplatePath = string.Empty,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_Z3, TargetPosition = 0.0 },
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.Z4,
                    IsIndependent = true,
                    TemplatePath = string.Empty,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_Z4, TargetPosition = 0.0 },
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.Z5,
                    IsIndependent = true,
                    TemplatePath = string.Empty,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_Z5, TargetPosition = 0.0 },
                    }
                },
                new OriginCalibModuleItem
                {
                    ModuleName = OriginCalibModuleNames.Z6,
                    IsIndependent = true,
                    TemplatePath = string.Empty,
                    AvoidanceAxes = new List<AvoidanceAxisItem>(),
                    CalibrationAxes = new List<CalibrationAxisItem>
                    {
                        new CalibrationAxisItem { AxisName = AxisName.Axis_PHS_Z6, TargetPosition = 0.0 },
                    }
                },
            };

            return modules;
        }
    }
}