using Microsoft.Extensions.Logging;
using SlnMesnac.Config;
using SlnMesnac.Plc.Factory;
using System;
using System.Collections.Generic;

namespace SlnMesnac.Plc
{
    /// <summary>
    /// PLC连接池
    /// </summary>
    public class PlcPool
    {
        private ILogger<PlcPool> _logger;
        private readonly AppConfig _appConfig;

        private Dictionary<string, PlcAbsractFactory> keyValuePairs = new Dictionary<string, PlcAbsractFactory>();

        private readonly InovanceFactory _inovance;
        private readonly MelsecBinaryFactory _melsecBinary;
        private readonly OmronNJFactory _omronNj;
        private readonly SiemensFactory _siemens;

        public PlcPool(ILogger<PlcPool> logger, InovanceFactory inovance, MelsecBinaryFactory melsecBinary, OmronNJFactory omronNj, SiemensFactory siemens, AppConfig appConfig)
        {
            _logger = logger;
            _inovance = inovance;
            _melsecBinary = melsecBinary;
            _omronNj = omronNj;
            _siemens = siemens;
            _appConfig = appConfig;
        }
        public void Init()
        {
            if (!HslCommunication.Authorization.SetAuthorizationCode("1839541f-8fb4-42c4-a13f-733b027fe5af"))
            {
                _logger.LogInformation("HslCommunication激活失败，可用时长24小时");
            }
            _logger.LogInformation("HslCommunication 11.8.1.0激活成功");

            if (_appConfig.plcConfig != null)
            {
                foreach (var item in _appConfig.plcConfig)
                {
                    if (item.isFlage)
                    {
                        AddPlc(item.plcType, item.plcIp, item.plcPort, item.plcKey);
                    }
                }

                // 开启心跳监测
                if (keyValuePairs.Count > 0)
                {
                    StartHeart();
                }
            }
            else
            {
                _logger.LogInformation("PLC配置信息为空");
            }
        }


        public void StartHeart()
        {
            // 设备状态刷新定时器
            System.Timers.Timer timer = new System.Timers.Timer(1000 * 3);
            timer.Elapsed += new System.Timers.ElapsedEventHandler(SendHeart);
            timer.AutoReset = true;
            timer.Enabled = true;
            timer.Start();
        }
        /// <summary>
        /// PLC状态刷新
        /// </summary>
        public void SendHeart(object sender, System.Timers.ElapsedEventArgs e)
        {
            foreach (var item in keyValuePairs)
            {
                item.Value.IsConnected = item.Value.readHeartByAddress("M100");
                keyValuePairs[item.Key] = item.Value;
            }
        }

        /// <summary>
        /// 添加PLC连接
        /// </summary>
        /// <param name="plcType"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="key"></param>
        public void AddPlc(string plcType, string ip, int port, string key)
        {
            try
            {
                PlcAbsractFactory _plc = null;
                switch (plcType)
                {
                    case "InovancePlc":
                        _plc = _inovance;
                        break;
                    case "MelsecBinaryPlc":
                        _plc = _melsecBinary;
                        break;
                    case "OmronNJPlc":
                        _plc = _omronNj;
                        break;
                    case "SiemensPlc":
                        _plc = _siemens;
                        break;
                    default:
                        break;
                }
                var connectResult = _plc.Connect(ip, port);
                if (connectResult)
                {
                    _logger.LogInformation($"PLC：{ip}:{port};连接成功，时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                    if (!keyValuePairs.ContainsKey(key))
                    {
                        keyValuePairs.Add(key, _plc);
                    }
                    else
                    {
                        keyValuePairs[key] = _plc;
                    }
                }
                else
                {
                    _logger.LogInformation($"PLC：{ip}:{port};连接失败，时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                    if (!keyValuePairs.ContainsKey(key))
                    {
                        keyValuePairs.Add(key, _plc);
                    }
                    else
                    {
                        keyValuePairs[key] = _plc;
                    }
                }
            }
            catch (Exception e)
            {
                _logger.LogError($"PLC初始化连接异常：{e.Message}");
            }
        }

        /// <summary>
        /// 获取PLC
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public PlcAbsractFactory GetPlcByKey(string key)
        {
            try
            {
                if (keyValuePairs.ContainsKey(key))
                {
                    return keyValuePairs[key];
                }
                else
                {
                    return null;
                }

            }
            catch (Exception e)
            {
                _logger.LogError($"根据PLC Key获取连接信息异常:{e.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取所有PLC信息
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, PlcAbsractFactory> GetAll()
        {
            return keyValuePairs;
        }

        /// <summary>
        /// 关闭所有连接
        /// </summary>
        /// <returns></returns>
        public bool disConnectAll()
        {
            bool result = false;
            try
            {
                foreach (var kv in keyValuePairs)
                {
                    if (kv.Value != null)
                    {
                        kv.Value.DisConnect();
                    }
                }
                result = true;
            }
            catch (Exception ex)
            {
                _logger.LogError("关闭PLC连接异常", ex);
            }

            return result;
        }
    }
}
