using ProjectBase.Data.Logs;
using ProjectBase.Data.Redis;
using SIASUN.Autopilot.Model;
using System;
using System.Collections.Generic;
using System.Linq;


namespace SIASUN.Autopilot.Device.BeckHoff
{
    internal class BeckhoffOpcHelper : IOpcHelper
    {
        private Dictionary<string , AbsTwinCatOpc> dicTwincatOpc = null;
        private int PLC_COUNT = 0;
        private List<MoBeckhoffNode> _moList = new List<MoBeckhoffNode>();
        static RedisHelper redis = null;

        public void Opc_Init(List<MoBeckhoffNode> mlist)
        {
            try
            {
                _moList = mlist;//BLLFactory<BlBeckhoffNode>.Instance.GetAll();
                PLC_COUNT = _moList.Count;

                if (redis == null)
                    redis = new RedisHelper();

                if (dicTwincatOpc.Count > 0)
                    dicTwincatOpc.Clear();

                var nodelist = from mo in _moList select mo.NodeName;

                if (PLC_COUNT <= 0)
                    return;
                else
                    dicTwincatOpc = new Dictionary<string, AbsTwinCatOpc>(nodelist.Count());

                for (int i = 0; i < PLC_COUNT; i++)
                {
                    if (dicTwincatOpc.ContainsKey(_moList[i].NodeName))
                    {
                        Console.WriteLine($"id {i}, 重复变量：{_moList[i].NodeName} ;");
                        continue;
                    }
                    switch (_moList[i].DataType)
                    {
                        case "double":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<Double>(_moList[i]));
                            break;
                        case "int":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<Int16>(_moList[i]));
                            break;
                        case "uint":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<UInt16>(_moList[i]));
                            break;
                        case "dint":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<Int64>(_moList[i]));
                            break;
                        case "word":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<Int16>(_moList[i]));
                            break;
                        case "bool":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<Boolean>(_moList[i]));
                            break;
                        case "byte":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<Byte>(_moList[i]));
                            break;
                        case "real":
                            dicTwincatOpc.Add(_moList[i].NodeName, new TwinCatAds<float>(_moList[i]));
                            break;
                    };
                }
            }
            catch(Exception ex)
            {
                LogHelper.log.Error(ex);
            }          
        }

        public void Opc_disConnect()
        {
            try
            {
                foreach (var itemOpc in dicTwincatOpc)
                {
                    itemOpc.Value.DisConnectOpc();
                }
            }
            catch (Exception ex)
            {
                LogHelper.log.Error(ex);
            }
            finally
            {
                dicTwincatOpc.Clear();
            }
        }

        public bool Opc_AddNotification(string command)
        {
            try
            {
                if (dicTwincatOpc.ContainsKey(command))
                {
                    return dicTwincatOpc[command].CreateNotification();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"删除变量事件通知：{command} 错误:{ex.Message}");
            }
            return false;
        }

        public bool Opc_DelNotification(string command)
        {
            try
            {
                if (command.Equals("all"))
                {
                    foreach (var itemOpc in dicTwincatOpc)
                        itemOpc.Value.DeleteNotification();
                    return true;
                }
                else if (dicTwincatOpc.ContainsKey(command))
                {
                    return dicTwincatOpc[command].DeleteNotification();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"删除变量事件通知：{command} 错误:{ex.Message}");
            }
            return false;
        }

        public bool OpcConnectState()
        {
            try
            {
                foreach (var itemOpc in dicTwincatOpc)
                {
                    itemOpc.Value.IsConnectOpc();
                }
            }
            catch (Exception ex)
            {
                LogHelper.log.Error(ex);
            }
            finally
            {
                dicTwincatOpc.Clear();
            }
            return false;
        }

        public void SetOpcSend(string nodeName, string value)
        {
            try
            {
                var DataType = from mo in _moList where mo.NodeName == nodeName select mo.DataType;
                if (string.IsNullOrWhiteSpace(DataType.FirstOrDefault()))
                    throw new Exception($"no have this var :{nodeName}");
                dicTwincatOpc[nodeName].Set(value, DataType.FirstOrDefault());
            }
            catch(Exception ex)
            {
                LogHelper.log.Error(ex);
            }          
        }

        public string GetOpcRecv(string nodeName, out Type _type)
        {
            try
            {
                return dicTwincatOpc[nodeName].Get(out _type).ToString();
            }
            catch(Exception ex)
            {
                LogHelper.log.Error(ex);                             
            }
            _type = null;
            return string.Empty;
        }
    }
}
