using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Equipment;
namespace MECF.Framework.Common.Communications
{
    public class AsynSocketServer : IDisposable
    {
        public delegate void ErrorHandler(string args);
        public event ErrorHandler OnErrorHappened;
        public delegate void MessageHandler(string message);
        public event MessageHandler OnDataChanged;
        public delegate void BinaryMessageHandler(byte[] message);
        public event BinaryMessageHandler OnBinaryDataChanged;
        private static Object _locker = new Object();
        public string NewLine { get; set; }
        public bool NeedLog { get; set; } = true;
        private string _ip;
        private int _port;
        private bool _isAscii;
        private static int _bufferSize = 1021;
        private ProtocolType _protocolType;
        public bool IsConnected { get { return (_serverSocket != null /*&& _serverSocket.Connected*/); }  }
        public AsynSocketServer(string ip, int port, bool isAscii,string newline = "\r", ProtocolType protocolType = ProtocolType.Tcp)
        {
            _ip = ip;
            _port = port;
            _isAscii = isAscii;
            _serverSocket = null;
            NewLine = newline;
            _protocolType = protocolType;
        }
        ~AsynSocketServer()
        {
            Dispose();
        }
        Socket _clientSocket;
        Socket _serverSocket;
        public void Start()
        {
            if (_serverSocket != null)
                return;
            //创建套接字
            IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(_ip), _port);
            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, _protocolType);
            //绑定端口和IP
            _serverSocket.Bind(ipe);
            //设置监听
            _serverSocket.Listen(10);
            //连接客户端
            AsyncAccept(_serverSocket);
        }
        /// 
        /// 连接到客户端
        /// 
        /// 
        private void AsyncAccept(Socket serverSocket)
        {
            serverSocket.BeginAccept(asyncResult =>
            {
                //获取客户端套接字
                _clientSocket = serverSocket.EndAccept(asyncResult);
                LOG.Info(string.Format("Received client {0} connect request", _clientSocket.RemoteEndPoint));
                AsyncReveive();
            }, null);
        }
        byte[] _buffer;
        /// 
        /// 接收消息
        /// 
        /// 
        private void AsyncReveive()
        {
            _buffer = new byte[_bufferSize];
            try
            {
                //开始接收消息
                _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                string reason = string.Format("TCP Socket recevice data failed:{0}", ex.Message);
                LOG.Error(string.Format("Communication  {0}:{1:D} {2}.", _ip, _port, reason));
                OnErrorHappened(reason);
            }
        }
        private void ReceiveCallback(IAsyncResult asyncResult)
        {
            int length = _clientSocket.EndReceive(asyncResult);
            if(length > 0)
            {
                if (_isAscii)
                {
                    string message = Encoding.ASCII.GetString(_buffer, 0, length);
                    if (NeedLog)
                        LOG.Info(string.Format("Client message:{0}", message));
                    OnDataChanged(message);
                }
                else
                {
                    byte[] recvBuff = new byte[length];
                    for (int i = 0; i < length; i++)
                    {
                        recvBuff[i] = _buffer[i];
                    }
                    if(NeedLog)                   
                        LOG.Info($"Client message: {string.Join(" ", recvBuff)}.");
                    OnBinaryDataChanged(recvBuff);
                }
            }
            else
            {
                //client disconnect, will....
            }
            //清空数据,重新开始异步接收
            _buffer = new byte[_bufferSize];
            _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _clientSocket);
        }
        /// 
        /// 发送消息
        /// 
        /// 
        /// 
        public void Write(string sendMessage)
        {
            if (_clientSocket == null || sendMessage == string.Empty) return;
            //数据转码
            byte[] data = new byte[1024];
            data = Encoding.ASCII.GetBytes(sendMessage);
            try
            {
                //开始发送消息
                _clientSocket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                {
                    //完成消息发送
                    int length = _clientSocket.EndSend(asyncResult);
                    //输出消息
                    if (NeedLog)
                        LOG.Info(string.Format("Communication {0}:{1:D} Send {2}.", _ip, _port, data));
                }, null);
            }
            catch (Exception e)
            {
                LOG.Write(e);
                string reason = string.Format("TCP连接发生错误:{0}", e.Message);
                LOG.Error(string.Format("Communication  {0}:{1:D} {2}.", _ip, _port, reason));
                OnErrorHappened(reason);
            }
        }
        public void Write(byte[] data)
        {
            if (_clientSocket == null || data.Count() == 0) return;
            try
            {
                //开始发送消息
                _clientSocket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                {
                    //完成消息发送
                    int length = _clientSocket.EndSend(asyncResult);
                    //输出消息
                    if (NeedLog)
                        LOG.Info(string.Format("Communication {0}:{1:D} Send {2}.", _ip, _port, data));
                }, null);
            }
            catch (Exception e)
            {
                LOG.Write(e);
                string reason = string.Format("TCP连接发生错误:{0}", e.Message);
                LOG.Error(string.Format("Communication  {0}:{1:D} {2}.", _ip, _port, reason));
                OnErrorHappened(reason);
            }
        }
        /// 
        public void Dispose()
        {
            try
            {
                if (_serverSocket != null)
                {
                    if (IsConnected)
                    {
                        _serverSocket.Shutdown(SocketShutdown.Both);
                    }
                    _serverSocket.Close();
                    _serverSocket.Dispose();
                    _serverSocket = null;
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                string reason = string.Format("释放socket资源失败:{0}", ex.Message);
                OnErrorHappened(reason);
            }
        }
    }
}