using ProjectManagementSystem.Device.Function;
using RRQMCore.ByteManager;
using RRQMCore.Log;
using RRQMSocket;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ProjectManagementSystem.Device.CasunBox
{
    public class BoxCommunicationTCP : BoxCommunicationBase
    {
        private string ipHost;
        private SimpleTcpService tcpService;
        
        public BoxCommunicationTCP(string ipAddress, int port)
        {
            ipHost = $"{ipAddress}:{port}";
        }

        public override void Start()
        {
            tcpService = new SimpleTcpService();
            //订阅事件
            tcpService.ClientConnected += Service_ClientConnected;//订阅连接事件
            tcpService.ClientDisconnected += Service_ClientDisconnected;//订阅断开连接事件
            tcpService.CreateSocketCliect += Service_CreatSocketCliect;
            tcpService.Received += this.OnReceived;

            //注入配置
            var config = new ServiceConfig();
            config.SetValue(ServiceConfig.ListenIPHostsProperty, new IPHost[] { new IPHost(ipHost) })
                .SetValue(ServiceConfig.LoggerProperty, new LogerBox(this.LogMsg))//设置内部日志记录器
                .SetValue(ServiceConfig.ThreadCountProperty, 4)//设置多线程数量
                .SetValue(TcpServiceConfig.ClearIntervalProperty, 300)//300秒无数据交互将被清理
                .SetValue(ServiceConfig.BufferLengthProperty, 1024);//设置缓存池大小，该数值在框架中经常用于申请ByteBlock，所以该值会影响内存池效率。

            //载入配置                                                       
            tcpService.Setup(config);

            try
            {
                //启动
                tcpService.Start();
                foreach (var item in tcpService.ListenIPHosts)
                {
                    LogMsg($"TCP服务端{item}已启动");
                }

                var address = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault(d => ipHost.Contains(d.ToString()));
                if (address == null)
                {
                    LogMsg($"注意：TCP监听IP不属于本机IP");
                }
                base.Start();
            }
            catch (Exception ex)
            {
                LogMsg($"TCP服务端启动异常", ex);
            }

        }

        public override void Stop()
        {
            if (this.tcpService != null)
            {
                this.tcpService.Stop();
            }
        }

        public List<SimpleSocketClient> GetSimpleSocketClient(Predicate<SimpleSocketClient> predicate)
        {
            List<SimpleSocketClient> simpleSockets = new List<SimpleSocketClient>();
            var IDs = tcpService.SocketClients.GetIDs();
            foreach (var id in IDs)
            {
                if (tcpService.TryGetSocketClient(id, out SimpleSocketClient client)
                    && client.Online
                    && predicate(client))
                {
                    simpleSockets.Add(client);
                }
            }
            return simpleSockets;
        }

        private List<SimpleSocketClient> GetSimpleSocketClient(int route)
        {
            var clientNames = m_boxInfoDict.Values
                .Where(d => d.Route == route)
                .Select(d => d.Name)
                .ToArray();

            var clientList = clientNames.Length > 0 ?
                GetSimpleSocketClient(d => clientNames.Contains(d.Name)) :
                GetSimpleSocketClient(d => true);

            return clientList;
        }

        public override void SendCommand(BoxCommandBase command)
        {
            var clientList = GetSimpleSocketClient(command.Route);
            byte[] data = command.Serialization();
            foreach (SimpleSocketClient client in clientList)
            {
                try
                {
                    client.Send(data);
                    LogMsg($"客户端{client.Name}: TCP发送数据: {Tools.Byte2HexString(data)}");
                }
                catch (Exception ex)
                {
                    LogMsg($"客户端{client.Name}: TCP发送数据异常: {Tools.Byte2HexString(data)}", ex);
                }
            }
        }

        private void Service_ClientConnected(object sender, MesEventArgs e)
        {
            var client = sender as SimpleSocketClient;
            if (client != null)
            {
                LogMsg($"客户端{client.Name}已连接，总连接数:{tcpService.SocketClients.Count}");
            }
        }

        private void Service_ClientDisconnected(object sender, MesEventArgs e)
        {
            var client = sender as SimpleSocketClient;
            if (client != null)
            {
                LogMsg($"客户端{client.Name}已断开，总连接数:{tcpService.SocketClients.Count}");
            }
        }

        private void Service_CreatSocketCliect(SimpleSocketClient arg1, CreateOption arg2)
        {
            arg1.SetDataHandlingAdapter(new BoxDataHandlingAdapter());
        }

        private void OnReceived(SimpleSocketClient client, ByteBlock byteBlock, object obj)
        {
            byte[] data = new byte[byteBlock.Length];
            Buffer.BlockCopy(byteBlock.Buffer, 0, data, 0, data.Length);

            RecivedData(data, d =>
            {
                d.Name = client.Name;
                LogMsg($"客户端{client.Name}: TCP接收数据: {Tools.Byte2HexString(data)} 校验{d.CheckXOR}");
            });
        }

    }

    public class LogerBox : ILog
    {
        private Action<string, Exception> action;

        public LogerBox(Action<string, Exception> act)
        {
            action = act;
        }

        public void Debug(LogType logType, object source, string message, Exception exception)
        {
            action(message, exception);
        }

        public void Debug(LogType logType, object source, string message)
        {
            action(message, null);
        }
    }
}

