using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Slice;
using CommonNetwork_ICE.Common;
using CommonServer.Server;
using CommonServer_ICE.Session;
using CommonServer.Protocol;
using CommonLang.Protocol;
using CommonNetwork_ICE.Util;
using CommonServer_ICE.Server;
using CommonLang.Log;

namespace CommonServer_ICE.Msg
{
    /// <summary>
    /// ICE UDP通信消息委托处理类:根据服务器消息接收类的委托,处理客户端发来的ICE网络消息
    /// </summary>
    internal class ServerMsgHandlerUdpDelegate : ServerMsgHandler
    {
        private static Logger log = LoggerFactory.GetLogger("ServerMsgHandlerUdpDelegate");
        private IceConnectServer server;

        public ServerMsgHandlerUdpDelegate(IceConnectServer server)
        {
            this.server = server;
        }

        /// <summary>
        /// 获取通讯类型
        /// </summary>
        public override IceConnectServer getServer()
        {
            return server;
        }

        /// <summary>
        /// 处理收到客户端发来的关键数据包
        /// </summary>
        /// <param name="recvPort">发送方侦听端口</param>
        /// <param name="message">数据包</param>
        /// <param name="ip">发送方IP</param>
        /// <param name="port">发送方端口</param>
        public override void RecvData(int recvPort, TransMessage message, string ip, int port)
        {
            log.Trace("收到客户端发来数据,地址IP【" + ip + "】,端口【" + port + "】,发送方侦听端口【" + recvPort + "】,编号:" + message.serial);
            IceServerIoSession session;
            if (SessionManager.hasSession(ip, port, recvPort))
            {
                session = (IceServerIoSession)SessionManager.getSession(ip, port, recvPort);
                if (!session.IsConnected)
                {
                    log.Error("会话已经关闭,当前消息忽略。客户端地址IP【" + ip + "】,端口【" + port + "】,发送方侦听端口【" + recvPort + "】");
                    return;
                }
            }
            else
            {
                log.Error("非法的数据发送,客户端地址IP【" + ip + "】,端口【" + port + "】,发送方侦听端口【" + recvPort + "】");
                return;
            }
            // 如果是之前客户端未收到服务器端的确认响应重发过来的消息,不处理此消息,重新发送响应
            // 如果发过来的序列号等于当前最后收到的序列号,只发送响应序列号
            if (message.type == Constants.PACKET_HINGE)
            {
                bool repeatMsg = true;
                if (message.serial > session.RecvLastSerial)
                {
                    // 更新关键包序列号
                    session.RecvLastSerial = message.serial;
                    repeatMsg = false;
                }
                try
                {
                    session.Sender.SendAck(recvPort, message.serial);
                }
                catch (Exception e)
                {
                    session.HandleException(e);
                }
                // 重发的消息不处理
                if (repeatMsg)
                {
                    return;
                }
            }
            // 消息转码
            IMessage iMessage;
            try
            {
                session.Codec.doDecode(message, out iMessage);
                session.Receive(iMessage);
            }
            catch (Exception e)
            {
                session.HandleException(e);
                return;
            }
        }

        /// <summary>
        /// 处理收到客户端发来的关键数据包确认序列号
        /// </summary>
        /// <param name="recvPort">发送方侦听端口</param>
        /// <param name="serial">序列号</param>
        /// <param name="ip">发送方IP</param>
        /// <param name="port">发送方端口</param>
        public override void SendDataRecvAck(int recvPort, long serial, string ip, int port)
        {
            log.Trace("收到客户端发来关键数据包响应,地址IP【" + ip + "】,端口【" + port + "】,发送方侦听端口【" + recvPort + "】,编号:" + serial);
            IceServerIoSession session;
            if (SessionManager.hasSession(ip, port, recvPort))
            {
                session = (IceServerIoSession)SessionManager.getSession(ip, port, recvPort);
                // 更新关键包序列号
                session.SendedRecvLastSerial = serial;
            }
            else
            {
                log.Error("非法的数据发送响应,客户端地址IP【" + ip + "】,端口【" + port + "】,发送方侦听端口【" + recvPort + "】");
                return;
            }
        }
    }
}