using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QMAPP.FJC.Entity.Basic;
using System.Configuration;
using OpcSlushWinService.WebServiceForOpc;
using OPCPLC;
using OPCAutomation;
using System.Threading;
using QMFrameWork.Common.Serialization;
using QMAPP.FJC.DAL.Basic;

namespace OpcSlushWinService
{
    public static class ParaInit
    {
        //暂时使用,因为新搪塑机的时间错误问题
        public static int loadValue = 0;

        //用来存储生产设备信息
        public static List<MachineInfo> slushMachineList;

        //用来存储OPC配置参数与服务端句柄的对应关系
        //key:OPC配置参数,样式为  设备号+":"+模具号+":"+数据库字段
        //value:服务端句柄
        public static Dictionary<string, int> parameterSlushValueDict = new Dictionary<string, int>();

        /// <summary>
        /// 用来存储客户端句柄与设备参数对应关系
        /// key:客户端句柄值
        /// value:OPC配置参数,样式为设备号+":"+模具号+":"+数据库字段
        /// </summary>
        public static Dictionary<int, string> clientSlushHandleDict = new Dictionary<int, string>();

        //OPC配置参数列表静态变量
        public static List<ParameterConfig> paraSlushConfigList;

        //设备模具参数信息静态变量
        public static List<ParameterConfig> moldSlushList;

        private static OpcServiceClient client;

        private static int clientSlushHandleValue = 0;

        //OPC连接字典静态变量
        public static OPCPLCAutomation opcplcSlushConnection;

        public static OPCPLCAutomation MonitorSlushConnection;

        public static void InitParameter()
        {
            moldSlushList = new List<ParameterConfig>();

            slushMachineList = new List<MachineInfo>();

            //opcServer服务器IP
            string opcServerIP = ConfigurationManager.AppSettings.Get("OPCServerIP");

            //opcServer服务名称
            string opcServerName = ConfigurationManager.AppSettings.Get("OPCServerName");

            try
            {
                client = new OpcServiceClient();



                #region 获取搪塑设备

                string maincheStr = client.GetMachineList();
                //获取所有的设备信息
                slushMachineList = JsonConvertHelper.GetDeserialize<List<MachineInfo>>(maincheStr);

                slushMachineList = slushMachineList
                    .Where(o => o.PROCESSTYPE == EnumGeter.ProcessType.tangsu.GetHashCode().ToString())
                    .ToList<MachineInfo>();

                #endregion

                #region 获取plc配置项

                string paraConfigStr = client.GetParaConfigList();
                paraSlushConfigList = JsonConvertHelper.GetDeserialize<List<ParameterConfig>>(paraConfigStr);

                paraSlushConfigList = paraSlushConfigList
                    .Where(o => o.PROCESSTYPE == EnumGeter.ProcessType.tangsu.GetHashCode().ToString())
                    .ToList<ParameterConfig>();

                #endregion

                #region 获取设备模块信息

                //对加工参数配置信息按照设备及模具信息进行分组
                var objlist = from pc in paraSlushConfigList
                              group pc by new { pc.MACHINECODDE, pc.MOLDNUMBER } into g
                              select new ParameterConfig { MACHINECODDE = g.Key.MACHINECODDE, MOLDNUMBER = g.Key.MOLDNUMBER };

                //添加到静态变量中
                foreach (var ob in objlist)
                {
                    moldSlushList.Add(new ParameterConfig() { MACHINECODDE = ob.MACHINECODDE, MOLDNUMBER = ob.MOLDNUMBER });
                }

                //按照设备进行排序
                moldSlushList = moldSlushList.OrderBy(o => o.MACHINECODDE).ToList<ParameterConfig>();

                #endregion

                #region 建立获取数量连接

                opcplcSlushConnection = new OPCPLC.OPCPLCAutomation();
                opcplcSlushConnection.GetListOPCServers(opcServerIP);
                opcplcSlushConnection.ConnectRemoteServer(opcServerName, opcServerIP);

                #endregion

                #region 建立监控连接

                MonitorSlushConnection = new OPCPLC.OPCPLCAutomation();
                MonitorSlushConnection.GetListOPCServers(opcServerIP);
                MonitorSlushConnection.ConnectRemoteServer(opcServerName, opcServerIP);

                MonitorSlushConnection.CreateGroup("Monitor");
                MonitorSlushConnection.KepGroups.DefaultGroupIsActive = true;//激活组。  
                MonitorSlushConnection.KepGroups.DefaultGroupDeadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组。  
                MonitorSlushConnection.KepGroups.DefaultGroupUpdateRate = 50;//默认组群的刷新频率为200ms  
                MonitorSlushConnection.KepGroup.UpdateRate = 50;//刷新频率为1秒。  
                MonitorSlushConnection.KepGroup.IsSubscribed = true;//使用订阅功能,即可以异步,默认false 
                //绑定监控事件
                MonitorSlushConnection.KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);

                #endregion

                #region 加载模块下的加工参数配置信息

                //变量所有的模具信息
                foreach (var m in moldSlushList)
                {
                    MachineInfo machineEntity = slushMachineList.First(o => o.MACHINECODDE == m.MACHINECODDE);

                    #region 获取加工参数组

                    //获取该模块下所有的加工参数信息
                    List<ParameterConfig> paraList = paraSlushConfigList
                         .Where(o =>
                             o.MACHINECODDE == m.MACHINECODDE
                             && o.MOLDNUMBER == m.MOLDNUMBER
                             && o.COLUMNTYPE == EnumGeter.COLUMNTYPE.PARAMETER.GetHashCode().ToString()
                             )
                         .ToList<ParameterConfig>();


                    if (paraList.Count > 0)
                    {

                        //为该模块创建参数组
                        opcplcSlushConnection.CreateGroup(m.MACHINECODDE + ":" + m.MOLDNUMBER + ":GetData");

                        if (opcplcSlushConnection.KepGroups.DefaultGroupUpdateRate == 1000)
                        {
                            opcplcSlushConnection.KepGroups.DefaultGroupUpdateRate = 200;
                        }

                        //变该模块下的所有参数信息
                        foreach (var pc in paraList)
                        {

                            //初始化字典名称:  设备名称+模块编号+字段名称
                            string dicKeyStr = machineEntity.MACHINECODDE + ":" + m.MOLDNUMBER + ":" + pc.COLUMNCODE;

                            try
                            {

                                //初始化字段信息值为0
                                parameterSlushValueDict.Add(dicKeyStr, 0);

                                //获取opc中tagName
                                string itemName = pc.CONNECTIONSTRING;

                                clientSlushHandleValue++;

                                clientSlushHandleDict.Add(clientSlushHandleValue, dicKeyStr);

                                //将字典中的与PLC内存地址向绑定
                                parameterSlushValueDict[dicKeyStr] = opcplcSlushConnection.AddKepItem(itemName, clientSlushHandleValue);
                            }
                            catch (Exception ex)
                            {
                                //Console.WriteLine(ex.Message);
                                //Console.WriteLine(dicKeyStr);
                                continue;
                            }
                        }
                    }

                    #endregion

                    #region 公共参数组

                    List<ParameterConfig> commonPara = paraSlushConfigList
                        .Where(o =>
                            o.MACHINECODDE == m.MACHINECODDE
                            && o.MOLDNUMBER == m.MOLDNUMBER
                            && o.COLUMNTYPE == EnumGeter.COLUMNTYPE.PUBLICDATA.GetHashCode().ToString()
                            )
                        .ToList<ParameterConfig>();

                    if (commonPara.Count > 0)
                    {

                        opcplcSlushConnection.CreateGroup(m.MACHINECODDE + ":" + m.MOLDNUMBER + ":CommonPara");

                        //变该模块下的所有参数信息
                        foreach (var pc in commonPara)
                        {
                            //初始化字典名称:  设备名称+模块编号+字段名称
                            string dicKeyStr = machineEntity.MACHINECODDE + ":" + m.MOLDNUMBER + ":" + pc.COLUMNCODE;

                            try
                            {

                                //初始化字段信息值为0
                                parameterSlushValueDict.Add(dicKeyStr, 0);

                                //获取opc中tagName
                                string itemName = pc.CONNECTIONSTRING;

                                clientSlushHandleValue++;

                                clientSlushHandleDict.Add(clientSlushHandleValue, dicKeyStr);

                                //将字典中的与PLC内存地址向绑定
                                parameterSlushValueDict[dicKeyStr] = opcplcSlushConnection.AddKepItem(itemName, clientSlushHandleValue);
                            }
                            catch (Exception ex)
                            {
                                //Console.WriteLine(ex.Message);
                                //Console.WriteLine(dicKeyStr);
                                continue;
                            }
                        }
                    }

                    #endregion

                    #region 监控组


                    //获取设备扫描条码完成标记和设备加工完成标记
                    List<ParameterConfig> monitorList = paraSlushConfigList
                        .Where(o =>
                            o.MACHINECODDE == m.MACHINECODDE
                            && o.MOLDNUMBER == m.MOLDNUMBER
                            && (
                            o.COLUMNTYPE == EnumGeter.COLUMNTYPE.EQUIPSCANFLAG.GetHashCode().ToString()
                            || o.COLUMNTYPE == EnumGeter.COLUMNTYPE.COMPLETEFLAG.GetHashCode().ToString()
                            )
                            )
                        .ToList<ParameterConfig>();

                    if (monitorList.Count > 0)
                    {

                        //变该模块下的所有参数信息
                        foreach (var pc in monitorList)
                        {
                            //初始化字典名称:  设备名称+模块编号+字段名称
                            string dicKeyStr = machineEntity.MACHINECODDE + ":" + m.MOLDNUMBER + ":" + pc.COLUMNCODE;
                            //Console.WriteLine(dicKeyStr);
                            try
                            {
                                //初始化字段信息值为0
                                parameterSlushValueDict.Add(dicKeyStr, 0);

                                //获取opc中tagName
                                string itemName = pc.CONNECTIONSTRING;

                                clientSlushHandleValue++;

                                clientSlushHandleDict.Add(clientSlushHandleValue, dicKeyStr);

                                //将字典中的与PLC内存地址向绑定
                                parameterSlushValueDict[dicKeyStr] = MonitorSlushConnection.AddKepItem(itemName, clientSlushHandleValue);

                            }
                            catch (Exception ex)
                            {
                                //Console.WriteLine(ex.Message);
                                //Console.WriteLine(dicKeyStr);
                                continue;
                            }
                        }

                        //MonitorList.Add(mouldConnection);
                    }

                    #endregion

                }

                #endregion
            }
            catch (Exception ex)
            {
                WriteLog.Write(ex.Message);
                throw ex;
            }

           
        }


        private static void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            try
            {
                for (int i = 1; i <= NumItems; i++)
                {
                    try
                    {

                        #region 获取被获取的获取数据类型

                        //获取写入的值
                        var itemValue = ItemValues.GetValue(i);

                        //获取客户端句柄
                        int chvalue = Convert.ToInt32(ClientHandles.GetValue(i));

                        //获取服务端字典key值
                        string dicKeyStr = clientSlushHandleDict[chvalue];

                        //获取设备信息
                        string machCode = dicKeyStr.Substring(0, dicKeyStr.IndexOf(':'));

                        string moldAndColumn = dicKeyStr.Substring(dicKeyStr.IndexOf(':') + 1);

                        //获取模块信息
                        string moldNumber = moldAndColumn.Substring(0, moldAndColumn.IndexOf(':'));

                        //获取字段名称
                        string columnCode = dicKeyStr.Substring(dicKeyStr.LastIndexOf(':') + 1);

                        //获取该标记信息
                        ParameterConfig currentPC = paraSlushConfigList.First(o => o.MACHINECODDE == machCode && o.MOLDNUMBER == moldNumber && o.COLUMNCODE == columnCode);

                        //Console.WriteLine(currentPC.MACHINECODDE + ":" + currentPC.MOLDNUMBER + ":" + currentPC.COLUMNCODE.ToString());

                        #endregion

                        #region 捕获完成标记

                        if (currentPC.COLUMNTYPE == EnumGeter.COLUMNTYPE.COMPLETEFLAG.GetHashCode().ToString())
                        {

                            if (itemValue == null)
                            {

                                continue;
                            }
                            //如果完成标记表示更新了加工参数
                            //获取所有的加工参数
                            if ((Boolean)itemValue == true)
                            {
                                //设置延迟2秒
                                //因为plc刷新频率
                                //个别情况获取不到值可以适当的延长等待时间
                                Thread.Sleep(2000);

                                //Console.WriteLine("Catch " + currentPC.MACHINECODDE + ":" + currentPC.MOLDNUMBER + ":" + currentPC.COLUMNCODE + " Finish");

                                List<ParameterConfig> resultList = new List<ParameterConfig>();

                                #region 获取该模块下的加工参数

                                List<ParameterConfig> getParaList = new List<ParameterConfig>();

                                //获取加工参数和公用参数
                                List<ParameterConfig> paraList = paraSlushConfigList
                                 .Where(o =>
                                     o.MACHINECODDE == machCode
                                     && o.MOLDNUMBER == moldNumber
                                     &&
                                     (
                                     o.COLUMNTYPE == EnumGeter.COLUMNTYPE.PARAMETER.GetHashCode().ToString()
                                     )
                                     )
                                 .ToList<ParameterConfig>();

                                //确定组信息
                                if (paraList.Count > 0)
                                {
                                    opcplcSlushConnection.KepGroup = opcplcSlushConnection.KepGroups.GetOPCGroup(currentPC.MACHINECODDE + ":" + currentPC.MOLDNUMBER.ToString() + ":GetData");
                                    opcplcSlushConnection.KepItems = opcplcSlushConnection.KepGroup.OPCItems;
                                }

                                //获取所有的加工参数
                                foreach (var parameter in paraList)
                                {

                                    #region 获取参数

                                    ParameterConfig paraConfig = GetResultParameterConfig(parameter);

                                    string item = parameter.MACHINECODDE + ":" + parameter.MOLDNUMBER + ":" + parameter.COLUMNCODE;

                                    var result = opcplcSlushConnection.ReadtagValue(parameterSlushValueDict[item]);

                                    if (result != null)
                                    {
                                        paraConfig.PARAVALUE = result;
                                    }

                                    resultList.Add(paraConfig);

                                    #endregion

                                    //Console.WriteLine(paraConfig.MACHINECODDE + ":" + paraConfig.MOLDNUMBER + ":" + paraConfig.COLUMNCODE + " " + ((result == null) ? " " : result.ToString()));
                                    WriteLog.Write(paraConfig.MACHINECODDE + ":" + paraConfig.MOLDNUMBER + ":" + paraConfig.COLUMNCODE + " " + ((result == null) ? " " : result.ToString()));

                                }

                                #endregion

                                #region 获取该模块下的公共参数

                                List<ParameterConfig> publicDataList = paraSlushConfigList
                                 .Where(o =>
                                     o.MACHINECODDE == machCode
                                     &&
                                     (
                                      o.COLUMNTYPE == EnumGeter.COLUMNTYPE.PUBLICDATA.GetHashCode().ToString()
                                     )
                                     )
                                 .ToList<ParameterConfig>();

                                if (publicDataList.Count > 0)
                                {
                                    opcplcSlushConnection.KepGroup = opcplcSlushConnection.KepGroups.GetOPCGroup(publicDataList[0].MACHINECODDE + ":" + publicDataList[0].MOLDNUMBER.ToString() + ":CommonPara");
                                    opcplcSlushConnection.KepItems = opcplcSlushConnection.KepGroup.OPCItems;

                                    foreach (var parameter in publicDataList)
                                    {

                                        #region 获取参数

                                        ParameterConfig paraConfig = GetResultParameterConfig(parameter);

                                        string item = parameter.MACHINECODDE + ":" + parameter.MOLDNUMBER + ":" + parameter.COLUMNCODE;

                                        var result = opcplcSlushConnection.ReadtagValue(parameterSlushValueDict[item]);

                                        if (result != null)
                                        {
                                            paraConfig.PARAVALUE = result;
                                        }

                                        resultList.Add(paraConfig);

                                        #endregion

                                        //Console.WriteLine(paraConfig.MACHINECODDE + ":" + paraConfig.MOLDNUMBER + ":" + paraConfig.COLUMNCODE + " " + ((result == null) ? " " : result.ToString()));
                                        WriteLog.Write(paraConfig.MACHINECODDE + ":" + paraConfig.MOLDNUMBER + ":" + paraConfig.COLUMNCODE + " " + ((result == null) ? " " : result.ToString()));
                                    }
                                }

                                #endregion

                                #region 将参数信息传递到web服务中

                                //如果第一次加载,
                                if (loadValue == 1)
                                {
                                    client.SubmitParameters(JsonConvertHelper.GetSerializes(resultList));
                                }

                                //第一次加载之后设置loadValue
                                loadValue = 1;

                                #endregion
                            }
                            else
                            {

                                if (currentPC.PROCESSTYPE == EnumGeter.ProcessType.tangsu.GetHashCode().ToString())
                                {
                                    //第一次加载时是false值,设置loadValue=1
                                    loadValue = 1;
                                }
                            }
                        }

                        #endregion

                    }
                    catch (Exception ex)
                    {
                        WriteLog.Write(ex.Message);
                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine("系统出现异常:" + ex.Message);
            }

        }


        /// <summary>
        /// 获取参数信息
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private static ParameterConfig GetResultParameterConfig(ParameterConfig parameter)
        {
            ParameterConfig paraConfig = new ParameterConfig();

            #region 属性复制

            paraConfig.COLUMNCODE = parameter.COLUMNCODE;
            paraConfig.COLUMNTYPE = parameter.COLUMNTYPE;
            paraConfig.DATATYPE = parameter.DATATYPE;
            paraConfig.DBNUMBER = parameter.DBNUMBER;
            paraConfig.DEALTYPE = parameter.DEALTYPE;
            paraConfig.MACHINECODDE = parameter.MACHINECODDE;
            paraConfig.MOLDNUMBER = parameter.MOLDNUMBER;
            paraConfig.OPERATETYPE = parameter.OPERATETYPE;
            paraConfig.PROCESSTYPE = parameter.PROCESSTYPE;

            #endregion

            return paraConfig;
        }
    }
}