using HighWayIot.Log4net;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
using TcpClient = TouchSocket.Sockets.TcpClient;

namespace HighWayIot.TouchSocket
{
    public class TouchSocketTcpClient
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static LogHelper _logHelper = LogHelper.Instance;

        /// <summary>
        /// 懒加载
        /// </summary>
        private static readonly Lazy<TouchSocketTcpClient> lazy = new Lazy<TouchSocketTcpClient>(() => new TouchSocketTcpClient());

        public static TouchSocketTcpClient Instance => lazy.Value;

        /// <summary>
        /// 所有的客户端
        /// </summary>
        public Dictionary<string, TcpClient> Clients = new Dictionary<string, TcpClient>();

        public int ClientsCount = 0; 

        public Action<byte[], string> GetMessageAction;

        public bool CreateTcpClient(string ip, string port)
        {
            TcpClient tcpClient = new TcpClient();

            tcpClient.Connecting = (client, e) =>
            {
                return EasyTask.CompletedTask;
            };//有客户端正在连接
            tcpClient.Connected = (client, e) =>
            {
                return EasyTask.CompletedTask;
            };//有客户端成功连接
            tcpClient.Closing = (client, e) =>
            {
                return EasyTask.CompletedTask;
            };//有客户端正在断开连接，只有当主动断开时才有效。
            tcpClient.Closed = (client, e) =>
            {
                return EasyTask.CompletedTask;
            };//有客户端断开连接
            tcpClient.Received = (client, e) =>
            {
                GetMessageAction.Invoke(e.ByteBlock.Span.ToArray(), client.IP);
                return EasyTask.CompletedTask;
            }; //接收信号

            tcpClient.SetupAsync(new TouchSocketConfig()
                .SetRemoteIPHost($"{ip}:{port}")
                .ConfigureContainer(a =>
                {
                    a.AddConsoleLogger();//添加一个日志注入
                })
                .ConfigurePlugins(a =>
                {
                    a.UseTcpReconnection()
                    .UsePolling(TimeSpan.FromSeconds(1));
                })
            );

            Result result = Result.Default; //不断尝试重连
            do
            {
                _logHelper.Info($"连接{ip}:{port}");
                result = tcpClient.TryConnect();
                Task.Delay(1000).Wait();
            }
            while (!result.IsSuccess);
            _logHelper.Info($"{ip}:{port}连接成功 {++ClientsCount}");
            if (Clients.ContainsKey(ip))
            {
                Clients.Remove(ip);
                Clients.Add(ip, tcpClient);
            }
            else
            {
                Clients.Add(ip, tcpClient);
            }

            return true;
        }

        /// <summary>
        /// 信息发送
        /// </summary>
        /// <param name="message">Bytes</param>
        /// <returns></returns>
        public bool Send(string ip, byte[] message)
        {
            try
            {
                if (Clients.ContainsKey(ip))
                {
                    Clients[ip].SendAsync(message);
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                _logHelper.Error("发送数据发生错误" + e);
                return false;
            }
        }

        /// <summary>
        /// 客户端释放
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public bool DisposeClient(string ip)
        {
            try
            {
                if (Clients.ContainsKey(ip))
                {
                    Clients[ip].Close();
                    Clients[ip].Dispose();
                    Clients.Remove(ip);
                }
                else
                {
                    return false;
                }
                return true;
            }
            catch (Exception e)
            {
                _logHelper.Error("释放客户端发生错误" + e);
                return false;
            }
        }

    }
}
