using MainShell.Common;
using MaxwellControl.Controls;
using MaxwellFramework.Core.Attributes;
using MwFramework.Controls.UIControl.Lighter;
using MwFramework.Device;
using MwFramework.Device.Delta;
using MwFramework.Device.DeviceInterface;
using MwFramework.Device.Drivers;
using MwFramework.ManagerService;
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MainShell.Hardware
{
    public static class AxisName
    {
        public const string Axis_SZ = "SZ";    //刺晶头 音圈电机
        public const string Axis_PHS_X1 = "PHS-X1";    //PHS龙门
        public const string Axis_PHS_X2 = "PHS-X2";    //PHS龙门
        public const string Axis_PHS_Y1 = "PHS-Y1";    //PHS龙门Y轴
        public const string Axis_WS_X3 = "WS-X3";    //WS龙门
        public const string Axis_WS_R = "WS-R";    //WS旋转轴
        public const string Axis_Stage_Y3 = "Stage-Y3";    //Stage平台Y3轴
        public const string Axis_PHS_Z1 = "PHS-Z1";    //刺晶头Z轴
        public const string Axis_PHS_Z3 = "PHS-Z3";    //相机Z轴
        public const string Axis_PHS_Z4 = "PHS-Z4";
        public const string Axis_PHS_Z5 = "PHS-Z5";
        public const string Axis_PHS_Z6 = "PHS-Z6";
        public const string Axis_Stage_Z7 = "Stage-Z7";
        public const string Axis_Stage_Z8 = "Stage-Z8";
        public const string Axis_Stage_Z9 = "Stage-Z9";
        public const string Axis_Stage_Z10 = "Stage-Z10";
        public const string Axis_Stage_CV_Y4 = "Stage-CV-Y4";
        public const string Axis_Stage_CV_Y5 = "Stage-CV-Y5";
        public const string Axis_WEU_Z11 = "WEU-Z11";
        public const string Axis_WEU_Z12 = "WEU-Z12";
        public const string Axis_WEU_Y6 = "WEU-Y6";
        public const string Axis_CV_Z13 = "CV-Z13";
        public const string Axis_CV_Y7 = "CV-Y7";
        public const string Axis_CV_Y8 = "CV-Y8";
        public const string Axis_CV_Y9 = "CV-Y9";
        public const string Axis_CV_Y10 = "CV-Y10";
    }
    [Singleton]
    public class HardwareManager
    {
        private const ushort DeltaDefaultNode = 0;
        private const ushort DeltaDefaultSlot = 0;
        private readonly List<DeviceIoPointDefinition> _ioPointDefinitions = new List<DeviceIoPointDefinition>();
        private readonly Dictionary<string, List<DeviceIoPointDefinition>> _ioPointDefinitionsByModule = new Dictionary<string, List<DeviceIoPointDefinition>>(StringComparer.OrdinalIgnoreCase);
        private readonly Dictionary<string, bool> _simulatedIoStates = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
        private const string DeviceIoConfigFileName = "DeviceIoPoints.csv";

        public IReadOnlyList<DeviceIoPointDefinition> IoPointDefinitions => _ioPointDefinitions;
        public IReadOnlyDictionary<string, List<DeviceIoPointDefinition>> IoPointDefinitionsByModule => _ioPointDefinitionsByModule;

        #region//内部类
        public class CameraAxisDevicesManager
        {
            //public List<HardwareDevice> TopPositionCameraAxisDevices { get; set; } = new List<HardwareDevice>();

            //public List<HardwareDevice> TopVirtualCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //public List<HardwareDevice> MapCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //public List<HardwareDevice> TopWideCameraAxisDevices { get; set; } = new List<HardwareDevice>();

            public List<HardwareDevice> TopPositionAndWideCameraAxisDevices { get; set;} = new List<HardwareDevice>();


            //public List<HardwareDevice> BottomCalibCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //public List<HardwareDevice> WSCalibCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //public List<HardwareDevice> PadCalibCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //public List<HardwareDevice> WSCalibWideCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //public List<HardwareDevice> PadCalibWideCameraAxisDevices { get; set; } = new List<HardwareDevice>();




            //上相机拍Pad，运动轴X1、Y2
            public List<HardwareDevice> TopCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //上相机拍WS，运动轴X2、Y1
            public List<HardwareDevice> TopCameraWsAxisDevices { get; set; } = new List<HardwareDevice>();
            //广角相机拍Pad、运动轴X1、Y2
            public List<HardwareDevice> WideCameraAxisDevices { get; set; } = new List<HardwareDevice>();
            //广角相机拍ws、运动轴X2、Y1
            public List<HardwareDevice> WideCameraWsAxisDevices { get; set; } = new List<HardwareDevice>();
            //下相机拍WS，运动轴X2、Y2
            public List<HardwareDevice> BottomCameraAxisDevices { get; set; } = new List<HardwareDevice>();

        }
        #endregion
        #region 单轴对象
        public IAxis Axis_PHS_X1 => GetAxisInternal(AxisName.Axis_PHS_X1);
        public IAxis Axis_PHS_X2 => GetAxisInternal(AxisName.Axis_PHS_X2);
        public IAxis Axis_PHS_Y1 => GetAxisInternal(AxisName.Axis_PHS_Y1);
        //public IAxis Axis_PHS_Y2 => GetAxisInternal(AxisName.Axis_Stage_Y3);
        public IAxis Axis_WS_X3 => GetAxisInternal(AxisName.Axis_WS_X3);
        public IAxis Axis_WS_R => GetAxisInternal(AxisName.Axis_WS_R);
        public IAxis Axis_Stage_Y3 => GetAxisInternal(AxisName.Axis_Stage_Y3);
        public IAxis Axis_Stage_Z7 => GetAxisInternal(AxisName.Axis_Stage_Z7);
        public IAxis Axis_Stage_Z8 => GetAxisInternal(AxisName.Axis_Stage_Z8);
        public IAxis Axis_Stage_Z9 => GetAxisInternal(AxisName.Axis_Stage_Z9);
        public IAxis Axis_Stage_Z10 => GetAxisInternal(AxisName.Axis_Stage_Z10);
        public IAxis Axis_Stage_CV_Y4 => GetAxisInternal(AxisName.Axis_Stage_CV_Y4);
        public IAxis Axis_Stage_CV_Y5 => GetAxisInternal(AxisName.Axis_Stage_CV_Y5);
        public IAxis Axis_PHS_Z1 => GetAxisInternal(AxisName.Axis_PHS_Z1);
        public IAxis Axis_PHS_Z3 => GetAxisInternal(AxisName.Axis_PHS_Z3);
        public IAxis Axis_PHS_Z4 => GetAxisInternal(AxisName.Axis_PHS_Z4);
        public IAxis Axis_PHS_Z5 => GetAxisInternal(AxisName.Axis_PHS_Z5);
        public IAxis Axis_PHS_Z6 => GetAxisInternal(AxisName.Axis_PHS_Z6);
        public IAxis Axis_WEU_Z11 => GetAxisInternal(AxisName.Axis_WEU_Z11);
        public IAxis Axis_WEU_Z12 => GetAxisInternal(AxisName.Axis_WEU_Z12);
        public IAxis Axis_WEU_Y6 => GetAxisInternal(AxisName.Axis_WEU_Y6);
        public IAxis Axis_CV_Z13 => GetAxisInternal(AxisName.Axis_CV_Z13);
        public IAxis Axis_CV_Y7 => GetAxisInternal(AxisName.Axis_CV_Y7);
        public IAxis Axis_CV_Y8 => GetAxisInternal(AxisName.Axis_CV_Y8);
        public IAxis Axis_CV_Y9 => GetAxisInternal(AxisName.Axis_CV_Y9);
        public IAxis Axis_CV_Y10 => GetAxisInternal(AxisName.Axis_CV_Y10);
        public IAxis Axis_SZ => GetAxisInternal(AxisName.Axis_SZ);

        public IAxis Axis_X1 => Axis_PHS_X1;
        public IAxis Axis_X2 => Axis_PHS_X2;
        public IAxis Axis_Y1 => Axis_PHS_Y1;
        public IAxis Axis_Y2 => Axis_Stage_Y3;
        public IAxis Axis_Z1 => Axis_PHS_Z1;
        public IAxis Axis_Z3 => Axis_PHS_Z3;

        #endregion
        private readonly string _topCameraName = "TopPositionCamera";
        private readonly string _topWsCameraName = "TopWsCamera";

        private readonly string _topWideCameraName = "TopWideCamera";
        private readonly string _topWideWsCameraName = "TopWideWsCamera";

        private readonly string _bottomCameraName = "MapCamera";

        //private readonly string _topVirtualCameraName = "TopVirtualCamera";

        

        /// <summary>
        /// 相机轴参数对象
        /// </summary>
        public CameraAxisDevicesManager CameraAxisManager { get; protected set; } = new CameraAxisDevicesManager();
        /// <summary>
        /// 当前设备的所有轴
        /// </summary>
        public Dictionary<string,IAxis> AxesDic { get; protected set; } = new Dictionary<string, IAxis>(StringComparer.Ordinal);

      
        /// <summary>
        /// Acs卡对象
        /// </summary>
        public MwCard AcsCard { get; protected set; }
        /// <summary>
        /// 台达卡对象
        /// </summary>
        public MwCard TdCard { get; protected set; }
        private MwCamera _topCamera;
        /// <summary>
        /// 上相机
        /// </summary>
        public MwCameraExtend TopCameraExtend { get; protected set; }
       
        /// <summary>
        /// 虚拟相机(上相机)
        /// </summary>
        public MwCameraExtend TopVirtualCameraExtend { get; protected set; }

        /// <summary>
        /// 上相机(虚拟相机)
        /// </summary>
        public MwCameraExtend TopWsCameraExtend { get; protected set; }
        private MwCamera _bottomCamera;
        /// <summary>
        /// 下相机
        /// </summary>
        public MwCameraExtend BottomCameraExtend { get; protected set; }
        private MwCamera _topWideCamera;
        /// <summary>
        /// 大视野上相机
        /// </summary>
        public MwCameraExtend TopWideCameraExtend { get; protected set; }
        /// <summary>
        /// 大视野上相机(虚拟相机)
        /// </summary>
        public MwCameraExtend TopWideWsCameraExtend { get; protected set; }
        /// <summary>
        /// 光源控制器1
        /// </summary>
        public MwLamp LightControl1 { get; protected set; }
        /// <summary>
        /// 光源控制器2
        /// </summary>
        public MwLamp LightControl2 { get; protected set; }
        #region//光源通道
        public MwLight Up_PointRedLight { get; protected set; }
        public MwLight Up_RingRedLight { get; protected set; }
        public MwLight Up_PointBlueLight { get; protected set; }
        public MwLight Up_RingBlueLight { get; protected set; }
        public MwLight Up_RedBackLight { get; protected set; }
        public MwLight Down_PointRedLight { get; protected set; }
        public MwLight Down_RingRedLight { get; protected set; }
        public MwLight Down_PointBlueLight { get; protected set; }
        public MwLight Down_RingBlueLight { get; protected set; }
        public MwLight Map_RedLight { get; protected set; }
        public MwLight Map_BlueLight { get; protected set; }
        #endregion
        /// <summary>
        /// 激光测距仪
        /// </summary>
        public IDiastimeter Diastimeter { get; protected set; }

        public IFFU FFU { get; protected set; }

        [Inject]
        public IDeviceManager DeviceManager { get; set; }
        public HardwareManager()
        {

        }
        private IAxis GetAxisInternal(string axisName)
        {
            if (string.IsNullOrWhiteSpace(axisName) || AxesDic == null)
            {
                return null;
            }

            IAxis axis;
            return AxesDic.TryGetValue(axisName, out axis) ? axis : null;
        }

        public void Tesrt()
        {
            Debug.WriteLine("HardwareManager Test");
        }
        public void Initialize()
        {
            if (DeviceManager is IDeviceList devices)
            {
                //初始化硬件设备
                AcsCard=devices.GetDevice<MwCard>("AcsCard");
                TdCard=devices.GetDevice<MwCard>("Delta");
                _topCamera=devices.GetDevice<MwCamera>("TopPositionCamera");
                _bottomCamera = devices.GetDevice<MwCamera>("MapCamera");
                _topWideCamera= devices.GetDevice<MwCamera>("TopWideCamera");
                Diastimeter = devices.GetDevice<IDiastimeter>("GPACON");
                LightControl1= devices.GetDevice<MwLamp>("LightControllor1");
                LightControl2= devices.GetDevice<MwLamp>("LightControllor2");
                #region //光源通道初始化
                Up_PointRedLight = new MwLight("点红光", LightControl1, 0);
                Up_PointBlueLight=new MwLight("点蓝光", LightControl1, 3);
                Up_RingRedLight=new MwLight("环红光", LightControl1, 1);
                Up_RingBlueLight=new MwLight("环蓝光", LightControl1, 2);
                Up_RedBackLight=new MwLight("红背光", LightControl1, 4);

                Down_PointRedLight=new MwLight("点红光", LightControl2, 0);
                Down_PointBlueLight=new MwLight("点蓝光", LightControl2, 3);
                Down_RingRedLight=new MwLight("环红光",LightControl2, 1);
                Down_RingBlueLight=new MwLight("环蓝光", LightControl2, 2);
                Map_RedLight=new MwLight("平面红光", LightControl2, 4);
                Map_BlueLight=new MwLight("平面蓝光", LightControl2, 5);
                #endregion


                TopCameraExtend = new MwCameraExtend(_topCamera, _topCameraName, _topCameraName);
                TopWsCameraExtend = new MwCameraExtend(_topCamera, _topWsCameraName, _topWsCameraName);
                TopWideCameraExtend = new MwCameraExtend(_topWideCamera, _topWideCameraName, _topWideCameraName);
                TopWideWsCameraExtend = new MwCameraExtend(_topWideCamera, _topWideWsCameraName, _topWideWsCameraName);
                BottomCameraExtend = new MwCameraExtend(_bottomCamera, _bottomCameraName, _bottomCameraName);

                //TopVirtualCameraExtend = new MwCameraExtend(_topCamera, _topVirtualCameraName, _topVirtualCameraName);

                AxesDic = GetAxes();


                //初始化相机轴集合
                //CameraAxisManager.TopPositionCameraAxisDevices.Add(new HardwareDevice
                //{
                //    AxisX = Axis_PHS_X1,
                //    AxisY = Axis_Y1,
                //    AxisZ = Axis_PHS_Z3,
                //    Camera = TopCameraExtend,
                //});
                //CameraAxisManager.TopVirtualCameraAxisDevices.Add(new HardwareDevice
                //{
                //    AxisX = Axis_PHS_X1,
                //    AxisY = Axis_Y1,
                //    AxisZ = Axis_PHS_Z3,
                //    Camera = TopCameraExtend,
                //});

                //标定用相机轴组集合
                CameraAxisManager.TopCameraAxisDevices.Add(new HardwareDevice
                {
                    AxisX = Axis_X1,
                    AxisY = Axis_Y2,
                    AxisZ = Axis_PHS_Z3,
                    Camera = TopCameraExtend,
                });
                CameraAxisManager.TopCameraWsAxisDevices.Add(new HardwareDevice
                {
                    AxisX = Axis_X2,
                    AxisY = Axis_Y1,
                    AxisZ = Axis_PHS_Z3,
                    Camera = TopWsCameraExtend,
                });
                CameraAxisManager.WideCameraAxisDevices.Add(new HardwareDevice
                {
                    AxisX = Axis_X2,
                    AxisY = Axis_Y1,
                    AxisZ = Axis_PHS_Z3,
                    Camera = TopWideCameraExtend,
                });
                CameraAxisManager.WideCameraWsAxisDevices.Add(new HardwareDevice
                {
                    AxisX = Axis_X1,
                    AxisY = Axis_Y2,
                    AxisZ = Axis_PHS_Z3,
                    Camera = TopWideWsCameraExtend,
                });
                CameraAxisManager.BottomCameraAxisDevices.Add(new HardwareDevice
                {
                    AxisX = Axis_X2,
                    AxisY = Axis_Y2,
                    AxisZ = Axis_PHS_Z3,
                    Camera = BottomCameraExtend,
                });
               
                CameraAxisManager.TopPositionAndWideCameraAxisDevices.Add(CameraAxisManager.TopCameraAxisDevices.FirstOrDefault());
                CameraAxisManager.TopPositionAndWideCameraAxisDevices.Add(CameraAxisManager.WideCameraAxisDevices.FirstOrDefault());

            }
        }
        private Dictionary<string, IAxis> GetAxes()
        {
            // 收集所有轴到列表，先做空检查以免抛出 null 引用
            var allAxes = new List<IAxis>();
            if (AcsCard?.Axises != null)
            {
                allAxes.AddRange(AcsCard.Axises);
            }
            if (TdCard?.Axises != null)
            {
                allAxes.AddRange(TdCard.Axises);
            }

            var dict = new Dictionary<string, IAxis>(allAxes.Count , StringComparer.Ordinal);

            
            foreach (var axis in allAxes)
            {
                if (axis == null) continue;
                var name = axis.Name;
                if (string.IsNullOrEmpty(name)) continue;

                dict[name] = axis;
            }

            
            return dict;
        }
        public IAxis GetAxisByName(string axisName)
        {
            return GetAxisInternal(axisName);
        }

        public bool TryGetDeltaIoExtend(out IDeltaIoExtend deltaIoExtend)
        {
            deltaIoExtend = TdCard.Controller as IDeltaIoExtend;
            return deltaIoExtend != null;
        }

        public bool TryReadLogisticsIoSnapshot(out DeviceIoSnapshot snapshot)
        {
            snapshot = new DeviceIoSnapshot
            {
                IsValid = false
            };

            if (TdCard == null)
            {
                return false;
            }

            return false;
        }

        public IReadOnlyList<DeviceIoPointDefinition> GetIoDefinitionsByModule(string module)
        {
            if (string.IsNullOrWhiteSpace(module))
            {
                return new List<DeviceIoPointDefinition>();
            }

            List<DeviceIoPointDefinition> list;
            if (_ioPointDefinitionsByModule.TryGetValue(module, out list))
            {
                return list;
            }

            return new List<DeviceIoPointDefinition>();
        }

        private void LoadIoPointDefinitions()
        {
            _ioPointDefinitions.Clear();
            _ioPointDefinitionsByModule.Clear();

            var pointKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

            var path = ResolveIoConfigPath();
            if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
            {
                return;
            }

            var lines = File.ReadAllLines(path, Encoding.UTF8);
            for (var i = 0; i < lines.Length; i++)
            {
                var raw = lines[i];
                if (string.IsNullOrWhiteSpace(raw))
                {
                    continue;
                }

                var line = raw.Trim();
                if (line.StartsWith("#"))
                {
                    continue;
                }

                if (i == 0 && line.IndexOf("Id", StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    continue;
                }

                var cols = line.Split(',');
                if (cols.Length < 9)
                {
                    continue;
                }

                int id;

                if (!int.TryParse(cols[0].Trim(), out id))
                {
                    continue;
                }

                var hasModuleColumn = cols.Length >= 10;
                var moduleIndex = hasModuleColumn ? 1 : -1;
                var nameIndex = hasModuleColumn ? 2 : 1;
                var typeIndex = hasModuleColumn ? 3 : 2;
                var cardIndex = hasModuleColumn ? 4 : 3;
                var stationIndex = hasModuleColumn ? 5 : -1;
                var lineNoIndex = hasModuleColumn ? 6 : -1;
                var enabledIndex = hasModuleColumn ? 7 : 4;
                var defaultValueIndex = hasModuleColumn ? 8 : 5;
                var isInverseIndex = hasModuleColumn && cols.Length >= 11 ? 9 : -1;
                var descriptionIndex = hasModuleColumn ? (isInverseIndex >= 0 ? 10 : 9) : 6;

                var name = cols[nameIndex].Trim();
                if (string.IsNullOrWhiteSpace(name))
                {
                    continue;
                }

                var module = hasModuleColumn ? cols[moduleIndex].Trim() : ResolveModuleFromName(name);
                if (string.IsNullOrWhiteSpace(module))
                {
                    module = "Default";
                }

                var type = ParseIoPointType(cols[typeIndex]);
                var card = ParseIoCardType(cols[cardIndex]);
                var stationNo = stationIndex >= 0 ? ParseInt(cols[stationIndex]) : 0;
                var lineNo = lineNoIndex >= 0 ? cols[lineNoIndex].Trim() : string.Empty;
                var pointKey = DeviceIoPointDefinition.BuildPointKey(type, card, stationNo, lineNo);

                if (!pointKeys.Add(pointKey))
                {
                    continue;
                }

                if (!names.Add(name))
                {
                    continue;
                }

                var definition = new DeviceIoPointDefinition
                {
                    Id = id,
                    PointKey = pointKey,
                    Module = module,
                    Name = name,
                    Type = type,
                    Card = card,
                    StationNo = stationNo,
                    LineNo = lineNo,
                    Enabled = ParseBoolean(cols[enabledIndex], true),
                    DefaultValue = ParseBoolean(cols[defaultValueIndex], false),
                    IsInverse = isInverseIndex >= 0 && isInverseIndex < cols.Length && ParseBoolean(cols[isInverseIndex], false),
                    Description = cols.Length > descriptionIndex ? string.Join(",", cols.Skip(descriptionIndex)).Trim() : string.Empty
                };

                _ioPointDefinitions.Add(definition);

                List<DeviceIoPointDefinition> moduleDefinitions;
                if (!_ioPointDefinitionsByModule.TryGetValue(module, out moduleDefinitions))
                {
                    moduleDefinitions = new List<DeviceIoPointDefinition>();
                    _ioPointDefinitionsByModule[module] = moduleDefinitions;
                }

                moduleDefinitions.Add(definition);
            }
        }

        private static string ResolveModuleFromName(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                return "Default";
            }

            var parts = name.Split('.');
            if (parts.Length >= 2)
            {
                return parts[1];
            }

            return "Default";
        }

        private static IoPointType ParseIoPointType(string raw)
        {
            if (string.IsNullOrWhiteSpace(raw))
            {
                return IoPointType.Input;
            }

            var text = raw.Trim();
            if (string.Equals(text, "Output", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "OUT", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "DO", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "O", StringComparison.OrdinalIgnoreCase))
            {
                return IoPointType.Output;
            }

            return IoPointType.Input;
        }

        private static IoCardType ParseIoCardType(string raw)
        {
            if (string.IsNullOrWhiteSpace(raw))
            {
                return IoCardType.Td;
            }

            var text = raw.Trim();
            if (string.Equals(text, "Acs", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "ACS", StringComparison.OrdinalIgnoreCase))
            {
                return IoCardType.Acs;
            }

            return IoCardType.Td;
        }

        private static bool ParseBoolean(string raw, bool defaultValue)
        {
            if (string.IsNullOrWhiteSpace(raw))
            {
                return defaultValue;
            }

            var text = raw.Trim();
            if (string.Equals(text, "1", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "true", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "yes", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "y", StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }

            if (string.Equals(text, "0", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "false", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "no", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(text, "n", StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }

            return defaultValue;
        }

        private static int ParseInt(string raw)
        {
            int value;
            return int.TryParse((raw ?? string.Empty).Trim(), out value) ? value : 0;
        }

        internal bool TryReadIoPointValues(IReadOnlyList<DeviceIoPointDefinition> definitions, out Dictionary<string, bool> values)
        {
            values = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
            if (definitions == null || definitions.Count == 0)
            {
                return false;
            }

            bool hasAnyValue = false;
            IDeltaIoExtend deltaIoExtend;
            bool canReadDelta = TryGetDeltaIoExtend(out deltaIoExtend);
            List<DeviceIoPointDefinition> deltaDefinitions = new List<DeviceIoPointDefinition>();

            foreach (DeviceIoPointDefinition definition in definitions)
            {
                if (definition == null)
                {
                    continue;
                }

                bool simulatedValue;
                if (!string.IsNullOrWhiteSpace(definition.PointKey) && _simulatedIoStates.TryGetValue(definition.PointKey, out simulatedValue))
                {
                    values[definition.PointKey] = simulatedValue;
                    hasAnyValue = true;
                    continue;
                }

                if (definition.Card == IoCardType.Td && canReadDelta)
                {
                    deltaDefinitions.Add(definition);
                    continue;
                }

                bool singleValue;
                if (TryReadIoPointValue(definition, out singleValue))
                {
                    values[definition.PointKey] = singleValue;
                    hasAnyValue = true;
                }
            }

            IEnumerable<IGrouping<string, DeviceIoPointDefinition>> groups = deltaDefinitions.GroupBy(BuildDeltaReadGroupKey);
            foreach (IGrouping<string, DeviceIoPointDefinition> group in groups)
            {
                if (TryReadDeltaIoPointGroup(group, deltaIoExtend, values))
                {
                    hasAnyValue = true;
                    continue;
                }

                foreach (DeviceIoPointDefinition definition in group)
                {
                    bool singleValue;
                    if (TryReadDeltaIoPoint(definition, deltaIoExtend, out singleValue))
                    {
                        values[definition.PointKey] = singleValue;
                        hasAnyValue = true;
                    }
                }
            }

            return hasAnyValue;
        }

        internal bool TryReadIoPointValue(DeviceIoPointDefinition definition, out bool value)
        {
            value = false;
            if (definition == null)
            {
                return false;
            }

            if (!string.IsNullOrWhiteSpace(definition.PointKey) && _simulatedIoStates.TryGetValue(definition.PointKey, out value))
            {
                return true;
            }

            var card = definition.Card == IoCardType.Acs ? AcsCard : TdCard;
            if (card == null)
            {
                return false;
            }

            if (definition.Card == IoCardType.Td)
            {
                IDeltaIoExtend deltaIoExtend;
                if (!TryGetDeltaIoExtend(out deltaIoExtend))
                {
                    return false;
                }

                return TryReadDeltaIoPoint(definition, deltaIoExtend, out value);
            }

            return false;
        }

        private bool TryReadDeltaIoPoint(DeviceIoPointDefinition definition, IDeltaIoExtend deltaIoExtend, out bool value)
        {
            value = false;
            if (definition == null || deltaIoExtend == null)
            {
                return false;
            }

            ushort cardNo;
            ushort node;
            ushort slot;
            ushort index;
            ushort subIndex;
            byte bitNo;
            ushort ioType;
            if (!TryGetDeltaIoReadParameters(definition, out cardNo, out node, out slot, out index, out subIndex, out bitNo, out ioType))
            {
                return false;
            }

            bool rawValue;
            ushort result = deltaIoExtend.ReadBit(cardNo, node, slot, index, subIndex, bitNo, out rawValue, ioType);
            if (result != 0)
            {
                return false;
            }

            value = definition.IsInverse ? !rawValue : rawValue;
            return true;
        }

        private bool TryReadDeltaIoPointGroup(IGrouping<string, DeviceIoPointDefinition> group, IDeltaIoExtend deltaIoExtend, IDictionary<string, bool> values)
        {
            if (group == null || deltaIoExtend == null || values == null)
            {
                return false;
            }

            DeviceIoPointDefinition firstDefinition = group.FirstOrDefault();
            if (firstDefinition == null)
            {
                return false;
            }

            ushort cardNo;
            ushort node;
            ushort slot;
            ushort ioType;
            if (!TryGetDeltaGroupParameters(firstDefinition, out cardNo, out node, out slot, out ioType))
            {
                return false;
            }

            List<BitItem> points = new List<BitItem>();
            Dictionary<string, DeviceIoPointDefinition> definitionsByPointKey = new Dictionary<string, DeviceIoPointDefinition>(StringComparer.OrdinalIgnoreCase);
            foreach (DeviceIoPointDefinition definition in group)
            {
                ushort index;
                ushort subIndex;
                byte bitNo;
                if (!TryGetDeltaPointAddress(definition, out index, out subIndex, out bitNo))
                {
                    return false;
                }

                BitItem point = new BitItem();
                point.Name = definition.PointKey;
                point.Index = index;
                point.SubIndex = subIndex;
                point.BitNo = bitNo;
                points.Add(point);
                definitionsByPointKey[definition.PointKey] = definition;
            }

            ushort result = deltaIoExtend.ReadBits(cardNo, node, slot, points, ioType);
            if (result != 0)
            {
                return false;
            }

            foreach (BitItem point in points)
            {
                DeviceIoPointDefinition definition;
                if (!definitionsByPointKey.TryGetValue(point.Name ?? string.Empty, out definition))
                {
                    continue;
                }

                values[definition.PointKey] = definition.IsInverse ? !point.Value : point.Value;
            }

            return true;
        }

        private bool TryGetDeltaIoReadParameters(DeviceIoPointDefinition definition, out ushort cardNo, out ushort node, out ushort slot, out ushort index, out ushort subIndex, out byte bitNo, out ushort ioType)
        {
            cardNo = 0;
            node = 0;
            slot = 0;
            index = 0;
            subIndex = 0;
            bitNo = 0;
            ioType = 0;

            if (!TryGetDeltaGroupParameters(definition, out cardNo, out node, out slot, out ioType))
            {
                return false;
            }

            return TryGetDeltaPointAddress(definition, out index, out subIndex, out bitNo);
        }

        private bool TryGetDeltaIoWriteParameters(DeviceIoPointDefinition definition, out ushort cardNo, out ushort node, out ushort slot, out ushort index, out ushort subIndex, out byte bitNo, out ushort readIoType)
        {
            cardNo = 0;
            node = 0;
            slot = 0;
            index = 0;
            subIndex = 0;
            bitNo = 0;
            readIoType = 0;

            if (!TryGetDeltaGroupParameters(definition, out cardNo, out node, out slot, out readIoType))
            {
                return false;
            }

            return TryGetDeltaPointAddress(definition, out index, out subIndex, out bitNo);
        }

        private bool TryGetDeltaGroupParameters(DeviceIoPointDefinition definition, out ushort cardNo, out ushort node, out ushort slot, out ushort ioType)
        {
            cardNo = 0;
            node = 0;
            slot = 0;
            ioType = 0;
            if (definition == null)
            {
                return false;
            }

            if (!TryConvertToUShort(definition.StationNo, out cardNo))
            {
                return false;
            }

            node = DeltaDefaultNode;
            slot = DeltaDefaultSlot;
            ioType = definition.Type == IoPointType.Output ? (ushort)1 : (ushort)0;
            return true;
        }

        private bool TryGetDeltaPointAddress(DeviceIoPointDefinition definition, out ushort index, out ushort subIndex, out byte bitNo)
        {
            index = 0;
            subIndex = 0;
            bitNo = 0;
            if (definition == null)
            {
                return false;
            }

            if (!TryConvertHexIntToUShort(definition.Index, out index) ||
                !TryConvertHexIntToUShort(definition.SubIndex, out subIndex) ||
                !TryResolveBitNo(definition, out bitNo))
            {
                return false;
            }

            return true;
        }

        private static bool TryConvertHexIntToUShort(int value, out ushort ushortValue)
        {
            ushortValue = 0;

            string hexText = value.ToString(CultureInfo.InvariantCulture);
            return ushort.TryParse(hexText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ushortValue);
        }

        private static bool TryResolveBitNo(DeviceIoPointDefinition definition, out byte bitNo)
        {
            bitNo = 0;
            if (definition == null)
            {
                return false;
            }

            int lineNoBitIndex;
            if (TryParseBitIndexFromLineNo(definition.LineNo, out lineNoBitIndex))
            {
                bitNo = (byte)(lineNoBitIndex % 8);
                return true;
            }

            if (definition.Id < 0)
            {
                return false;
            }

            bitNo = (byte)(definition.Id % 8);
            return true;
        }

        private static bool TryParseBitIndexFromLineNo(string lineNo, out int bitIndex)
        {
            bitIndex = 0;
            if (string.IsNullOrWhiteSpace(lineNo))
            {
                return false;
            }

            string text = lineNo.Trim();
            if (text.Length < 2)
            {
                return false;
            }

            string suffix = text.Substring(text.Length - 2, 2);
            return int.TryParse(suffix, out bitIndex);
        }

        private static bool TryConvertToUShort(int value, out ushort ushortValue)
        {
            ushortValue = 0;
            if (value < ushort.MinValue || value > ushort.MaxValue)
            {
                return false;
            }

            ushortValue = (ushort)value;
            return true;
        }

        private static string BuildDeltaReadGroupKey(DeviceIoPointDefinition definition)
        {
            if (definition == null)
            {
                return string.Empty;
            }

            return string.Format(
                "{0}:{1}:{2}:{3}:{4}",
                definition.Card,
                definition.StationNo,
                definition.Type,
                definition.Index,
                definition.SubIndex);
        }

        internal bool TryWriteIoPointValue(DeviceIoPointDefinition definition, bool outputOn)
        {
            if (definition == null)
            {
                return false;
            }

            if (!string.IsNullOrWhiteSpace(definition.PointKey))
            {
                _simulatedIoStates[definition.PointKey] = outputOn;
            }

            var card = definition.Card == IoCardType.Acs ? AcsCard : TdCard;
            if (card == null)
            {
                return true;
            }

            bool rawOutput = definition.IsInverse ? !outputOn : outputOn;

            if (definition.Card == IoCardType.Td)
            {
                IDeltaIoExtend deltaIoExtend;
                if (!TryGetDeltaIoExtend(out deltaIoExtend))
                {
                    return false;
                }

                ushort cardNo;
                ushort node;
                ushort slot;
                ushort index;
                ushort subIndex;
                byte bitNo;
                ushort readIoType;
                if (!TryGetDeltaIoWriteParameters(definition, out cardNo, out node, out slot, out index, out subIndex, out bitNo, out readIoType))
                {
                    return false;
                }

                ushort result = deltaIoExtend.WriteBit(cardNo, node, slot, index, subIndex, bitNo, rawOutput, readIoType);
                return result == 0;
            }

            return false;
        }

        private static string ResolveIoConfigPath()
        {
            var baseDir = AppDomain.CurrentDomain.BaseDirectory;
            var localPath = Path.Combine(baseDir, "Configuration", DeviceIoConfigFileName);
            var sourcePath = ResolveRootConfigPath(baseDir, DeviceIoConfigFileName);

            if (TrySyncConfigToLocal(sourcePath, localPath))
            {
                return localPath;
            }

            return File.Exists(localPath) ? localPath : null;
        }

        private static string ResolveRootConfigPath(string baseDir, string fileName)
        {
            var current = new DirectoryInfo(baseDir);
            while (current != null)
            {
                var rootConfigDir = Path.Combine(current.FullName, "Configuration");
                if (Directory.Exists(rootConfigDir) && Directory.Exists(Path.Combine(current.FullName, "MainShell")))
                {
                    var path = Path.Combine(rootConfigDir, fileName);
                    if (File.Exists(path))
                    {
                        return path;
                    }
                }

                current = current.Parent;
            }

            return null;
        }

        private static bool TrySyncConfigToLocal(string sourcePath, string localPath)
        {
            if (string.IsNullOrWhiteSpace(sourcePath) || !File.Exists(sourcePath))
            {
                return false;
            }

            if (!string.Equals(Path.GetFullPath(sourcePath), Path.GetFullPath(localPath), StringComparison.OrdinalIgnoreCase))
            {
                var localDir = Path.GetDirectoryName(localPath);
                if (!string.IsNullOrWhiteSpace(localDir))
                {
                    Directory.CreateDirectory(localDir);
                }

                if (!File.Exists(localPath) || File.GetLastWriteTimeUtc(localPath) < File.GetLastWriteTimeUtc(sourcePath))
                {
                    File.Copy(sourcePath, localPath, true);
                }
            }

            return true;
        }
        #region // 获取相机
        public MwCameraExtend GetCamera(CameraType cameraType)
        {
            switch (cameraType)
            {
                case CameraType.MapCamera:
                    return BottomCameraExtend;
                case CameraType.TopWideCamera:
                    return TopWideCameraExtend;
                case CameraType.TopPositionCamera:
                    return TopCameraExtend;
                case CameraType.TopWideWsCamera:
                    return TopWideWsCameraExtend;
                case CameraType.TopWsCamera:
                    return TopWsCameraExtend;
            }
            throw new Exception("未知的相机类型，请检查相机类型参数");
        }

        public string GetCameraName(CameraType cameraType)
        {
            var cameraExtend = GetCamera(cameraType);
            return cameraExtend != null ? cameraExtend.Name : throw new Exception("未知的相机类型，请检查相机类型参数");
        }
        #endregion

        #region //设置光源强度
        private void SetLightIntensity(MwLight light, int intensity)
        {
            if (light != null)
            {
                light.Intensity = intensity;
            }
        }
        private int GetLightIntensity(MwLight light)
        {
            if (light != null)
            {
                return light.Intensity;
            }
            return 0;
        }
        public void SetUpPointRedLightIntensity(int intensity)
        {
            SetLightIntensity(Up_PointRedLight, intensity);
        }
        public void SetUpRingRedLightIntensity(int intensity)
        {
            SetLightIntensity(Up_RingRedLight, intensity);
        }
        public void SetUpPointBlueLightIntensity(int intensity)
        {
            SetLightIntensity(Up_PointBlueLight, intensity);
        }
        public void SetUpRingBlueLightIntensity(int intensity)
        {
            SetLightIntensity(Up_RingBlueLight, intensity);
        }
        public void SetDownPointRedLightIntensity(int intensity)
        {
            SetLightIntensity(Down_PointRedLight, intensity);
        }
        public void SetDownRingRedLightIntensity(int intensity)
        {
            SetLightIntensity(Down_RingRedLight, intensity);
        }
        public void SetDownPointBlueLightIntensity(int intensity)
        {
            SetLightIntensity(Down_PointBlueLight, intensity);
        }
        public void SetDownRingBlueLightIntensity(int intensity)
        {
            SetLightIntensity(Down_RingBlueLight, intensity);
        }
        public void SetMapRedLightIntensity(int intensity)
        {
            SetLightIntensity(Map_RedLight, intensity);
        }
        public void SetMapBlueLightIntensity(int intensity)
        {
            SetLightIntensity(Map_BlueLight, intensity);
        }
        public void SetUpRedBackLightIntensity(int intensity)
        {
            SetLightIntensity(Up_RedBackLight, intensity);
        }


        public int GetUpPointRedLightIntensity()
        {
            return GetLightIntensity(Up_PointRedLight);
        }
        public int GetUpRingRedLightIntensity()
        {
            return GetLightIntensity(Up_RingRedLight);
        }
        public int GetUpPointBlueLightIntensity()
        {
            return GetLightIntensity(Up_PointBlueLight);
        }
        public int GetUpRingBlueLightIntensity()
        {
            return GetLightIntensity(Up_RingBlueLight);
        }
        public int GetDownPointRedLightIntensity()
        {
            return GetLightIntensity(Down_PointRedLight);
        }
        public int GetDownRingRedLightIntensity()
        {
            return GetLightIntensity(Down_RingRedLight);
        }
        public int GetDownPointBlueLightIntensity()
        {
            return GetLightIntensity(Down_PointBlueLight);
        }
        public int GetDownRingBlueLightIntensity()
        {
            return GetLightIntensity(Down_RingBlueLight);
        }
        public int GetMapRedLightIntensity()
        {
            return GetLightIntensity(Map_RedLight);
        }
        public int GetMapBlueLightIntensity()
        {
            return GetLightIntensity(Map_BlueLight);
        }
        public int GetUpRedBackLightIntensity()
        {
            return GetLightIntensity(Up_RedBackLight);
        }


        #endregion
    }
}
