#if COMBAT_SERVER

using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Com.Fort23.Protocol.Protobuf;
using Fort23.UTool;
using Utility;
using Task = System.Threading.Tasks.Task;

namespace Core.KCPTool
{
    public class TCPServer : IServer
    {
        private byte[] buffData = new byte[6553];
        private Socket socket;

        //记录半包数据
        private bool isBufferData;
        private byte[] lastBuffData;
        private int lastCount;

        private short lastXueLieHao;
        //数据结束

        //尾包
        private byte[] weiBaoBuffData;


        // private Thread _udpClientThread;

        private byte[] buffer = new byte[2048];


        public Map<long, IServerConnection> KcpServerConnections = new Map<long, IServerConnection>();
        private List<CombatSynchronizeRequest> CombatSynchronizeRequests = new List<CombatSynchronizeRequest>();
        private List<IServerConnection> awaitConnections = new List<IServerConnection>();
        private IServerManager iServerManager;

        public TCPServer(int port, IServerManager iServerManager)
        {
            LogTool.Log("创建TCP链接端口"+port+"__");
            this.iServerManager = iServerManager;
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(new IPEndPoint(IPAddress.Any, port));
            socket.Listen();
            AcceptAsync();
        }

        public void AddCombatSynchronizeRequest(CombatSynchronizeRequest combatSynchronizeRequest)
        {
            lock (CombatSynchronizeRequests)
            {
                CombatSynchronizeRequests.Add(combatSynchronizeRequest);
            }
        }

        public CombatSynchronizeRequest[] GetCombatSynchronizeRequest(bool isClear)
        {
            if (CombatSynchronizeRequests.Count <= 0)
            {
                return null;
            }

            lock (CombatSynchronizeRequests)
            {
                CombatSynchronizeRequest[] allData = CombatSynchronizeRequests.ToArray();
                CombatSynchronizeRequests.Clear();
                return allData;
            }
        }

        private byte[] AssembleData(SendDataType sendDataType, byte[] buffer)
        {
            byte[] sendBuff = new byte[buffer.Length + 5];
            sendBuff[0] = (byte)sendDataType;
            byte[] zcd = SocketTool.IntToByte(buffer.Length);
            sendBuff[1] = zcd[0];
            sendBuff[2] = zcd[1];
            sendBuff[3] = zcd[2];
            sendBuff[4] = zcd[3];
            Array.Copy(buffer, 0, sendBuff, 5, buffer.Length);
            return sendBuff;
        }

        public bool SendToPlayer(SendDataType sendDataType, CombatSynchronizeType combatSynchronizeType, byte[] buffer,
            long playerId)
        {
            if (KcpServerConnections.Count <= 0)
            {
                return true;
            }

            long t = System.DateTime.Now.Ticks;


            byte[] sendBuff = AssembleData(sendDataType, buffer);
            long t2 = System.DateTime.Now.Ticks;
            bool isOk = false;


            lock (KcpServerConnections)
            {
                for (KcpServerConnections.Begin(); KcpServerConnections.Next();)
                {
                    if (KcpServerConnections.Value.isConnected)
                    {
                        isOk = true;
                    }

                    if (playerId != -1 && KcpServerConnections.Value.playerId != playerId)
                    {
                        continue;
                    }

                    KcpServerConnections.Value.SendData(sendBuff, sendBuff.Length);
                }
            }

            return isOk;
        }


        public IServerConnection GetConnection(int connectionId)
        {
            lock (KcpServerConnections)
            {
                for (KcpServerConnections.Begin(); KcpServerConnections.Next();)
                {
                    if (connectionId != -1 && KcpServerConnections.Value.connectionID != connectionId)
                    {
                        continue;
                    }

                    return KcpServerConnections.Value;
                }
            }

            return null;
        }

        public async void SendGameFrame(int gameFrame, IServerConnection kcpServerConnection)
        {
            // if (gameFrame > 0)
            {
                LogTool.Log("重传数据开始" + gameFrame);
                int maxCount = iServerManager.GetSendBufferSize();
                for (int i = gameFrame; i < maxCount; i++)
                {
                    byte[] _sendBufferdata = iServerManager.GetSendBuffer(i);
                    if (_sendBufferdata != null)
                    {
                        _sendBufferdata = AssembleData(SendDataType.Data,_sendBufferdata);
                        kcpServerConnection.SendData(_sendBufferdata, _sendBufferdata.Length);
                        await Task.Delay(1);
                    }
                }
            }
        }

        public void AddServerConnection(long playerId, int gameFrame, IServerConnection kcpServerConnection)
        {
            lock (KcpServerConnections)
            {
                if (KcpServerConnections.TryGetValue(playerId, out var connection))
                {
                    LogTool.Log("移除成功TCP" + playerId);
                    connection.Dispose();
                    KcpServerConnections.Remove(playerId);
                }

                KcpServerConnections.Add(playerId, kcpServerConnection);
            }

            lock (awaitConnections)
            {
                awaitConnections.Remove(kcpServerConnection);
            }

            LogTool.Log("握手成功TCP" + playerId);
            iServerManager.AddServerConnection(this, kcpServerConnection);
            byte[] data = SocketTool.LongToByte(playerId);
            SendToPlayer(SendDataType.ShakeHands, CombatSynchronizeType.PrepareStart, data, playerId);
        }

        public void RemoveServerConnection(long playerId)
        {
            lock (KcpServerConnections)
            {
                if (KcpServerConnections.TryGetValue(playerId, out IServerConnection serverConnection))
                {
                    LogTool.Log("移除成功TCP" + playerId);
                    serverConnection.Dispose();
                    KcpServerConnections.Remove(playerId);
                }
            }
        }

        public IServerConnection GetConnection(long playerId)
        {
            lock (KcpServerConnections)
            {
                for (KcpServerConnections.Begin(); KcpServerConnections.Next();)
                {
                    if (playerId != -1 && KcpServerConnections.Value.playerId != playerId)
                    {
                        continue;
                    }

                    return KcpServerConnections.Value;
                }
            }

            return null;
        }

        public void ConnectionUpdate()
        {
        }

        private async void AcceptAsync()
        {
            try
            {
                if (socket == null)
                {
                    return;
                }

                Socket newSocket = await socket.AcceptAsync();
                int code = newSocket.RemoteEndPoint.GetHashCode();
                TCPServerConnection tcpServerConnection = new TCPServerConnection(this, newSocket);
                tcpServerConnection.connectionID = code;
                awaitConnections.Add(tcpServerConnection);


                AcceptAsync();
            }
            catch (Exception e)
            {
                LogTool.Error(e);
            }
        }

        public void Dispose()
        {
            socket?.Dispose();
            socket = null;

            for (KcpServerConnections.Begin(); KcpServerConnections.Next();)
            {
                KcpServerConnections.Value.Dispose();
            }

            KcpServerConnections.Clear();
            CombatSynchronizeRequests.Clear();
            awaitConnections.Clear();
        }
    }
}

#endif