using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;

namespace Mesnac.Action.ChemicalWeighing
{
    /// <summary>
    /// PLCSchema.xml配置文件解析辅助类
    /// </summary>
    public class PlcSchemaHelper
    {
        #region 单例实现

        private static PlcSchemaHelper _instance = null;

        private PlcSchemaHelper()
        {

        }
        /// <summary>
        /// PLCSchema.xml配置文件解析类
        /// </summary>
        public static PlcSchemaHelper Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new PlcSchemaHelper();
                }
                return _instance;
            }
        }

        #endregion

        #region 获取PlcSchema.xml文件路径

        /// <summary>
        /// 获取PLCSchema.xml文件路径
        /// </summary>
        /// <returns></returns>
        private string getPlcSchemaPath()
        {
            string path = System.Windows.Forms.Application.StartupPath;
            return Path.Combine(path, "Data\\MCProject\\PlcSchema.xml");
        }

        #endregion

        #region 读取PLCSchema.xml配置文件

        #region 解析XML元素的属性值

        /// <summary>
        /// 解析XML元素的属性值
        /// </summary>
        /// <param name="node">XML元素节点</param>
        /// <param name="key">要获取值的属性名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>解析成功返回对应的属性值,解析失败返回默认值 - String类型属性</returns>
        private string ToValue(XmlNode node, string key, string defaultValue)
        {
            foreach (XmlAttribute a in node.Attributes)
            {
                if (a.Name.Equals(key, StringComparison.CurrentCultureIgnoreCase))
                {
                    return a.Value;
                }
            }
            return defaultValue;
        }
        /// <summary>
        /// 解析XML元素的属性值(重载方法)
        /// </summary>
        /// <param name="node">XML元素节点</param>
        /// <param name="key">要获取值的属性名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>解析成功返回对应的属性值,解析失败返回默认值 - Int类型属性</returns>
        private int ToValue(XmlNode node, string key, int defaultValue)
        {
            int Result = 0;
            string value = ToValue(node, key, string.Empty);
            if (!string.IsNullOrWhiteSpace(value)
                && int.TryParse(value, out Result))
            {
                return Result;
            }
            return defaultValue;
        }
        /// <summary>
        /// 解析XML元素的属性值(重载方法)
        /// </summary>
        /// <param name="node">XML元素节点</param>
        /// <param name="key">要获取值的属性名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>解析成功返回对应的属性值,解析失败返回默认值 - bool类型属性</returns>
        private bool ToValue(XmlNode node, string key, bool defaultValue)
        {
            bool Result = false;
            string value = ToValue(node, key, string.Empty);
            if (!string.IsNullOrWhiteSpace(value) && bool.TryParse(value, out Result))
            {
                return Result;
            }
            return defaultValue;
        }

        #endregion

        #region 解析PlCSchema.xml文件中的存盘项
        /// <summary>
        /// 解析PlCSchema.xml文件中的存盘项
        /// </summary>
        /// <param name="tableName">元素名 - 对应存盘项节点</param>
        /// <returns>返回存盘数据项集合</returns>
        public List<PlcRecipeReader> GetCWSSPlcReader(string tableName)
        {
            lock (String.Empty)
            {
                List<PlcRecipeReader> result = new List<PlcRecipeReader>();
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(getPlcSchemaPath());
                foreach (XmlNode configNode in xmlDocument)
                {
                    //跳过注释
                    if (configNode.NodeType == XmlNodeType.Comment)
                    {
                        continue;
                    }
                    if (!configNode.Name.Equals("configuration", StringComparison.CurrentCultureIgnoreCase))
                    {
                        continue;
                    }
                    foreach (XmlNode readNode in configNode.ChildNodes)
                    {
                        //跳过注释
                        if (readNode.NodeType == XmlNodeType.Comment)
                        {
                            continue;
                        }
                        if (!readNode.Name.Equals("CWSSPlcSaveRead", StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }
                        foreach (XmlNode serviceNode in readNode.ChildNodes)
                        {
                            //跳过注释
                            if (serviceNode.NodeType == XmlNodeType.Comment)
                            {
                                continue;
                            }
                            if (!serviceNode.Name.Equals(tableName, StringComparison.CurrentCultureIgnoreCase))
                            {
                                continue;
                            }
                            PlcRecipeReader reader = new PlcRecipeReader();
                            reader.TargetTable = ToValue(serviceNode, "targetTable", string.Empty);
                            reader.PlcFiledName = ToValue(serviceNode, "equip", string.Empty);
                            reader.ThisCount = ToValue(serviceNode, "count", 1);
                            reader.ThisType = ToValue(serviceNode, "type", 0);
                            foreach (XmlNode node in serviceNode.ChildNodes)
                            {
                                //跳过注释
                                if (node.NodeType == XmlNodeType.Comment)
                                {
                                    continue;
                                }
                                PlcRecipeReaderItem plc = new PlcRecipeReaderItem();
                                plc.DataFieldName = ToValue(node, "field", string.Empty);
                                plc.PlcFiledName = ToValue(node, "equip", string.Empty);
                                plc.PlcShifting = ToValue(node, "shifting", 0);
                                plc.DefaultValue = ToValue(node, "default", 0);
                                plc.ValueLen = ToValue(node, "len", 1);
                                plc.DataType = ToValue(node, "datatype", string.Empty);
                                plc.Multiply = ToValue(node, "multiply", 1);
                                reader.ItemList.Add(plc);
                            }
                            result.Add(reader);
                        }
                    }
                }
                return result;
            }
        }
        #endregion

        #region 解析PlCSchema.xml文件中的计划的配方头数据的下传PLC项

        /// <summary>
        /// 解析PlCSchema.xml文件中的计划的配方头数据的下传PLC项
        /// </summary>
        /// <param name="tableName">元素名 - 对应下传数据项节点</param>
        /// <returns>返回称量参数下传PLC数据项集合</returns>
        public List<PlcWriter> GetPlcWriter(string tableName)
        {
            List<PlcWriter> result = new List<PlcWriter>();
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(getPlcSchemaPath());
            foreach (XmlNode configNode in xmlDocument)
            {
                //跳过注释
                if (configNode.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }
                if (!configNode.Name.Equals("configuration", StringComparison.CurrentCultureIgnoreCase))
                {
                    continue;
                }
                foreach (XmlNode writeNode in configNode.ChildNodes)
                {
                    //跳过注释
                    if (writeNode.NodeType == XmlNodeType.Comment)
                    {
                        continue;
                    }
                    if (!writeNode.Name.Equals("PlcPlanAndRecipeWrite", StringComparison.CurrentCultureIgnoreCase))
                    {
                        continue;
                    }
                    foreach (XmlNode serviceNode in writeNode.ChildNodes)
                    {
                        //跳过注释
                        if (serviceNode.NodeType == XmlNodeType.Comment)
                        {
                            continue;
                        }
                        if (!serviceNode.Name.Equals(tableName, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }
                        PlcWriter writer = new PlcWriter();
                        writer.EquipRunName = ToValue(serviceNode, "equip", string.Empty);
                        writer.DataFieldName = ToValue(serviceNode, "field", string.Empty);
                        writer.ThisCount = ToValue(serviceNode, "count", 1);
                        writer.ThisType = ToValue(serviceNode, "type", 0);
                        foreach (XmlNode node in serviceNode.ChildNodes)
                        {
                            //跳过注释
                            if (node.NodeType == XmlNodeType.Comment)
                            {
                                continue;
                            }
                            PlcWriteItem plc = new PlcWriteItem();
                            plc.DataFieldName = ToValue(node, "field", string.Empty);
                            if (string.IsNullOrWhiteSpace(plc.DataFieldName))
                            {
                                plc.DataFieldName = writer.DataFieldName;
                            }
                            plc.EquipRunName = ToValue(node, "equip", string.Empty);
                            if (string.IsNullOrWhiteSpace(plc.EquipRunName))
                            {
                                plc.EquipRunName = writer.EquipRunName;
                            }
                            plc.PlcShifting = ToValue(node, "shifting", 0);
                            plc.DefaultValue = ToValue(node, "default", 0);
                            plc.ValueLen = ToValue(node, "len", 1);
                            plc.DataType = ToValue(node, "datatype", string.Empty);
                            plc.Multiply = ToValue(node, "multiply", 1);
                            writer.SchemaList.Add(plc);
                        }
                        result.Add(writer);
                    }
                }
            }
            return result;
        }

        #endregion

        #region 解析PlCSchema.xml文件中的计划的物料信息数据的下传PLC项

        /// <summary>
        /// 解析PlCSchema.xml文件中的计划的物料信息数据的下传PLC项
        /// </summary>
        /// <param name="tableName">元素名 - 对应下传数据项节点</param>
        /// <returns>返回称量参数下传PLC数据项集合</returns>
        public List<PlcWriter> GetMaterialPlcWriter(string tableName)
        {
            List<PlcWriter> result = new List<PlcWriter>();
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(getPlcSchemaPath());
            foreach (XmlNode configNode in xmlDocument)
            {
                //跳过注释
                if (configNode.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }
                if (!configNode.Name.Equals("configuration", StringComparison.CurrentCultureIgnoreCase))
                {
                    continue;
                }
                foreach (XmlNode writeNode in configNode.ChildNodes)
                {
                    //跳过注释
                    if (writeNode.NodeType == XmlNodeType.Comment)
                    {
                        continue;
                    }
                    if (!writeNode.Name.Equals("PlcPlanAndRecipeWrite", StringComparison.CurrentCultureIgnoreCase))
                    {
                        continue;
                    }
                    foreach (XmlNode serviceNode in writeNode.ChildNodes)
                    {
                        //跳过注释
                        if (serviceNode.NodeType == XmlNodeType.Comment)
                        {
                            continue;
                        }
                        if (!serviceNode.Name.Equals(tableName, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }
                        PlcWriter writer = new PlcWriter();
                        writer.EquipRunName = ToValue(serviceNode, "equip", string.Empty);
                        writer.DataFieldName = ToValue(serviceNode, "field", string.Empty);
                        writer.ThisCount = ToValue(serviceNode, "count", 1);
                        writer.ThisType = ToValue(serviceNode, "type", 0);
                        foreach (XmlNode node in serviceNode.ChildNodes)
                        {
                            //跳过注释
                            if (node.NodeType == XmlNodeType.Comment)
                            {
                                continue;
                            }
                            PlcWriteItem plc = new PlcWriteItem();
                            plc.DataFieldName = ToValue(node, "field", string.Empty);
                            if (string.IsNullOrWhiteSpace(plc.DataFieldName))
                            {
                                plc.DataFieldName = writer.DataFieldName;
                            }
                            plc.EquipRunName = ToValue(node, "equip", string.Empty);
                            if (string.IsNullOrWhiteSpace(plc.EquipRunName))
                            {
                                plc.EquipRunName = writer.EquipRunName;
                            }
                            plc.PlcShifting = ToValue(node, "shifting", 0);
                            plc.DefaultValue = ToValue(node, "default", 0);
                            plc.ValueLen = ToValue(node, "len", 1);
                            plc.DataType = ToValue(node, "datatype", string.Empty);
                            plc.Multiply = ToValue(node, "multiply", 1);
                            writer.SchemaList.Add(plc);
                        }
                        result.Add(writer);
                    }
                }
            }
            return result;
        }

        #endregion

        #endregion

    }
}