using FLY.Thick.Base.IService;
using FlyADBase;
using FObjBase;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace FLY.Thick.Base.Common
{
    /// <summary>
    /// AD盒IO定义，避免忘记IO口的定义，出现功能重复
    /// 
    /// 使用方法：
    /// 1.每款机型例如吹膜 继承FlyADIODefine
    /// 2.添加 输入口，输出口
    /// 3.重载 GetInputPropertyNames 显示输出 输入口定义
    /// 4.重载 GetOutputPropertyNames 显示输出 输出口定义
    /// 5.重定义 static new FlyADIODefine Instance
    /// 
    /// 6.在Gage中 调用 FlyADIODefine.SetInstance(new FlyADIODefine());
    /// 7.在Gage中 注册 AD盒事件， AD盒版本修改时，FlyADIODefine.SerVersion(version);
    /// </summary>
    public class FlyADIODefine: IFlyAdIoDefineService
    {
        protected static FlyADIODefine instance;
        public static void SetInstance(FlyADIODefine flyADIODefine) 
        {
            instance = flyADIODefine;
        }
        /// <summary>
        /// 子类 需要 重新 把子类对象 赋值给 Instance, 确保整个环境只用一个版本的 单例
        /// </summary>
        public static FlyADIODefine Instance => instance;

        #region 输入口

        /// <summary>
        /// 扫描按钮信号
        /// </summary>
        public int InNo_Scan { get; protected set; } = 1 - 1;

        /// <summary>
        /// 归零信号
        /// </summary>
        public int InNo_Org { get; protected set; } = 2 - 1;

        /// <summary>
        /// 正向限位
        /// </summary>
        public int InNo_Limit_Forw { get; protected set; } = 3 - 1;
        /// <summary>
        /// 反向限位
        /// </summary>
        public int InNo_Limit_Backw { get; protected set; } = 4 - 1;

        /// <summary>
        /// 数据有效
        /// </summary>
        public int InNo_DataValid { get; protected set; } = 6 - 1;

        /// <summary>
        /// 急停 and 手动正转
        /// </summary>
        public int InNo_Manual_Forw { get; protected set; } = 7 - 1;

        /// <summary>
        /// 急停 and 手动反转
        /// </summary>
        public int InNo_Manual_Backw { get; protected set; } = 8 - 1;

        /// <summary>
        /// 同步输入信号
        /// </summary>
        public int InNo_Sync { get; protected set; } = 9 - 1;

        /// <summary>
        /// 辊速信号
        /// </summary>
        public int InNo_Roll { get; protected set; } = 11 - 1;

        /// <summary>
        /// 控制主轴脉冲启动计数输入， o3 接 i11;
        /// i11 为 0 计数停止
        /// </summary>
        public int InNo_Pos2OnOff { get; protected set; } = 11 - 1;

        /// <summary>
        /// 纵向光纤信号
        /// </summary>
        public int InNo_VSign { get; protected set; } = 12 - 1;

        #endregion
        #region 输出口

        /// <summary>
        /// 扫描动作中
        /// </summary>
        [Description("扫描动作中")]
        public int OutNo_Scan { get; protected set; } = 1 - 1;

        /// <summary>
        /// 变频器反转 VF0 是松下的变频器牌子
        /// </summary>
        [Description("变频器反转")]
        public int OutNo_VF0_Backw { get; protected set; } = 1 - 1;
        /// <summary>
        /// 变频器正转 VF0 是松下的变频器牌子
        /// </summary>
        [Description("变频器正转")]
        public int OutNo_VF0_Forw { get; protected set; } = 2 - 1;
        /// <summary>
        /// 变频器减速 VF0 是松下的变频器牌子
        /// </summary>
        [Description("变频器减速")]
        public int OutNo_VF0_Slow { get; protected set; } = 3 - 1;

        /// <summary>
        /// 控制主轴脉冲启动计数
        /// </summary>
        [Description("主轴脉冲启动计数")]
        public int OutNo_Pos2OnOff { get; protected set; } = 3 - 1;

        /// <summary>
        /// 同步输出信号
        /// </summary>
        [Description("同步输出信号")]
        public int OutNo_Sync { get; protected set; } = 3 - 1;

        /// <summary>
        /// 报警信号
        /// </summary>
        [Description("报警信号")]
        public int OutNo_Alarm { get; protected set; } = 4 - 1;


        #endregion

        IFlyAD flyAD;
        public virtual void SetFlyAD(IFlyAD _flyAD) 
        {
            this.flyAD = _flyAD;
            Misc.BindingOperations.SetBinding(flyAD, nameof(flyAD.HardwareVersion), () =>
            {
                if (this.flyAD.HardwareVersion < 3)
                {
                    InNo_Org = 2 - 1;
                    InNo_Limit_Forw = 3 - 1;
                    InNo_Limit_Backw = 4 - 1;

                    InNo_Roll = 11 - 1;
                }
                else
                {
                    InNo_Org = 13 - 1;
                    InNo_Limit_Forw = 14 - 1;
                    InNo_Limit_Backw = 16 - 1;

                    InNo_Roll = 15 - 1;
                }
            });
        }

        /// <summary>
        /// 获取输入口 属性名
        /// </summary>
        /// <returns></returns>
        protected virtual List<string> GetInputPropertyNames() 
        {
            List<string> reponse = new List<string>();
            Type t = this.GetType();
            var properties = t.GetProperties();

            foreach (var property in properties)
            {
                if (property.Name.StartsWith("InNo_"))
                {
                    //输入
                    reponse.Add(property.Name);
                }
            }
            return reponse;
        }
        /// <summary>
        /// 获取输出口 属性名
        /// </summary>
        /// <returns></returns>
        protected virtual List<string> GetOutputPropertyNames()
        {
            List<string> reponse = new List<string>();
            Type t = this.GetType();
            var properties = t.GetProperties();

            foreach (var property in properties)
            {
                if (property.Name.StartsWith("OutNo_"))
                {
                    //输入
                    reponse.Add(property.Name);
                }
            }
            return reponse;
        }
        public void GetIODefine(AsyncCBHandler asyncDelegate, object asyncContext)
        {
            //获取全部带 Description 的属性，且名字 InNo_XXX 或 OutNo_XXX
            IODefineCollection response = new IODefineCollection();
            
            List<IODefine> list = new List<IODefine>();
            response.List = list;
            if (flyAD.HardwareVersion < 3)
            {
                response.InCount = 12;
                response.OutCount = 4;
            }
            else {
                response.InCount = 16;
                response.OutCount = 8;
            }

            var inputPropertyNames = GetInputPropertyNames();
            var outputPropertyNames = GetOutputPropertyNames();

            if (flyAD.MotorType != FlyADBase.MOTORTYPE.VF0)
            {
                //把 变频器 接口删除
                outputPropertyNames.Remove(nameof(OutNo_VF0_Forw));
                outputPropertyNames.Remove(nameof(OutNo_VF0_Backw));
                outputPropertyNames.Remove(nameof(OutNo_VF0_Slow));
            }

            if (flyAD.MotorType == FlyADBase.MOTORTYPE.VF0)
            {
                //变频器 模式 没有扫描状态灯
                outputPropertyNames.Remove(nameof(OutNo_Scan));
            }

            Type t = this.GetType();
            
            foreach (var propertyName in inputPropertyNames)
            {
                var property = t.GetProperty(propertyName);
               
                string desp = propertyName;

                var index = (int)property.GetValue(this);
                var iodefine = new IODefine()
                {
                    IoType = IODefine.IOTYPE.Input,
                    Index = index,
                    Description = desp
                };
                
                list.Add(iodefine);
            }

            foreach (var propertyName in outputPropertyNames)
            {
                var property = t.GetProperty(propertyName);

                string desp = propertyName;

                var index = (int)property.GetValue(this);
                var iodefine = new IODefine()
                {
                    IoType = IODefine.IOTYPE.Output,
                    Index = index,
                    Description = desp
                };
                list.Add(iodefine);
            }

            asyncDelegate?.Invoke(asyncContext, response);
        }
    }
}
