using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using NET;
using NET.TCP;

namespace NSC.Net.NetService.TCP
{
    /// <summary>
    /// 网络服务处理类
    /// 作者:黄顺权
    /// 日期:2015年01月08日
    /// </summary>
    public class TCPNetServer : IDisposable
    {
        private Service.SystemServiceEngine sysService = new Service.SystemServiceEngine();//系统服务处理引擎
        private ManualResetEvent _stopEvent = new ManualResetEvent(false);
        private ManualResetEvent _doneEvent = new ManualResetEvent(true);
        private static Dictionary<Socket, Task> _dictTask = new Dictionary<Socket, Task>();
        public delegate Common.Data.UserAuthority OnVerifyClientBegin(string clientsn);//客户端验证委托
        public event OnVerifyClientBegin VerifyClientBegin;//触发客户端验证事件
        public delegate NetServiceStruct OnApplicationServiceHandleBegin(NetServiceStruct data);//应用服务处理委托
        public event OnApplicationServiceHandleBegin ApplicationServiceHandleBegin;//触发应用服务事件
        public static int lineNum = 0;
        /// <summary>
        /// 远程终端节点信息
        /// </summary>
        public RemoteEndPoint EndPoint { get; set; }

        /// <summary>
        /// 创建基于TCP/IP协议的服务的新实例
        /// </summary>
        public TCPNetServer()
        {
            sysService.Load();
        }

        /// <summary>
        /// 启动监听器
        /// </summary>
        public void Start()
        {
            ThreadPool.SetMaxThreads(5000, 5000);
            if (!_doneEvent.WaitOne(0)) return; //如果服务已运行则退出
            new Thread(ListenProc).Start();
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public void Stop()
        {
            if (_doneEvent.WaitOne(0)) return; //如果服务已停止则退出
            _stopEvent.Set(); //通知结束
            _doneEvent.WaitOne();

            //等待所有子线程运行结束
            Task[] tasks;
            lock (_dictTask)
            {
                tasks = new Task[_dictTask.Count];
                _dictTask.Values.CopyTo(tasks, 0);
            }
            Task.WaitAll(tasks);
        }

        /// <summary>
        /// 监听线程处理方法
        /// </summary>
        private void ListenProc()
        {
            try
            {
                _doneEvent.Reset();
                _stopEvent.Reset();

                using (Socket sockListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    System.Net.IPEndPoint ep = new System.Net.IPEndPoint(EndPoint.IP, EndPoint.Port);
                    sockListener.Bind(ep);
                    sockListener.Listen(EndPoint.ConnectionLength);

                    while (true)
                    {
                        IAsyncResult iar = sockListener.BeginAccept(null, null);
                        WaitHandle[] events = { _stopEvent, iar.AsyncWaitHandle };
                        int eventIndex = WaitHandle.WaitAny(events);
                        if (eventIndex == 0)
                        {
                            break;
                        }
                        else if (eventIndex == 1)
                        {
                            Socket sockClient = sockListener.EndAccept(iar);
                            Task t = new Task(ProcRequest, sockClient);
                            lock (_dictTask)
                            {
                                _dictTask.Add(sockClient, t);
                            }
                            t.Start();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                    //记录异常
            }
            finally
            {
                _doneEvent.Set();
            }
        }

        /// <summary>
        /// 请求处理
        /// </summary>
        /// <param name="sock"></param>
        private void ProcRequest(object parameter)
        {
            NetServiceStruct data = null;//网络传输的数据
            MemoryStream buffer = null;//数据接收缓存
            string License = "";//授权码
            string ClientSN = "";//客户端标识
            bool Compress = false;//压缩标识
            int streamLength = 0;//数据部分的总长度
            Common.Data.UserAuthority userAuth = Common.Data.UserAuthority.User;//客户端的访问级别
            NetServiceStruct output = null;//返回的数据
            string serviceID = "";

            Socket socket = parameter as Socket;

            try
            {

                socket.SendTimeout = EndPoint.Timeout;
                socket.ReceiveTimeout = EndPoint.Timeout;
                socket.Blocking = true;

                //获取数据头部分
                TCPBase.ReceiveDataHead(socket, out streamLength, out License, out ClientSN, out Compress);

                //客户端授权验证
                userAuth = VerifyClientBegin == null ? Common.Data.UserAuthority.User : VerifyClientBegin(ClientSN);

                //接收消息
                using (buffer = TCPBase.ReceiveStream(socket, streamLength, Compress))
                {
                    //解码网络数据流
                    data = PacketsDecoder.ParseNetStream(buffer);
                }

                //异步执行时返回服务流水号
                if (data.SyncType == Common.Data.SyncType.Async)
                {
                    serviceID = ServiceDataBufferEngine.CreateNewServiceSN();

                    data.ServiceSN = serviceID;

                    //发送反馈
                    NET.TCP.TCPBase.SendStream(socket, License, ClientSN, PacketsEncoder.ConvertToStream(data));
                }

                //服务处理
                output = sysService.ServiceHandler(userAuth, data, true);//系统服务
                if (output == null)
                {
                    if (ApplicationServiceHandleBegin == null)
                    {
                        lock (_dictTask)
                        {
                            _dictTask.Remove(socket);
                        }
                        socket.Shutdown(SocketShutdown.Both);
                        socket.Close();
                        throw new Common.Exceptions.NoneServiceException();
                    }
                    else
                    {
                        output = ApplicationServiceHandleBegin(data);
                    }
                }
            }
            catch (Exception ex)
            {
                //返回异常消息
                output = new NetServiceStruct();
                output.ExceptionType = Common.Data.ExceptionType.Exception;
                output.Returns = new Dictionary<string, ParameterStruct>();
                output.Returns.Add("CommonException", new ParameterStruct(ex.Message));

            }

            output.FirmwareModel = data.FirmwareModel;
            output.FirmwareVersion = data.FirmwareVersion;
            output.ServiceName = data.ServiceName;
            output.ServiceSN = data.ServiceSN;
            output.SyncType = data.SyncType;

            if (data.SyncType == Common.Data.SyncType.Sync)
            {
                try
                {
                    //发送反馈
                    output.Params.Clear();
                    NET.TCP.TCPBase.SendStream(socket, License, ClientSN, PacketsEncoder.ConvertToStream(output));
                }
                catch (Exception ex)
                {
                    //记录异常
                }
            }
            else
            {
                ServiceDataBufferEngine.WriteServiceFile(serviceID, output);
            }
            lock (_dictTask)
            {
                _dictTask.Remove(socket);
            }
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            this.Stop();
        }
    }
}