using System;
using System.IO;
using MrWu.Debug;

namespace Server.Net
{
    public enum ParserState{
        PacketSize,
        PacketBody,
    }
    
    public class PacketParser
    {
        /// <summary>
        /// 收包Buffer
        /// </summary>
        private readonly CircularBuffer buffer;

        /// <summary>
        /// 当前要解的包大小
        /// </summary>
        private int packetSize;

        private ParserState state;
        private readonly AService service;

        private readonly byte[] cache = new byte[4];

        public const int ActorPacketSizeLength = 4;
        public const int RouterPacketSizeLength = 4;

        public MemoryBuffer MemoryBuffer;

        public PacketParser(CircularBuffer buffer, AService service)
        {
            this.buffer = buffer;
            this.service = service;
        }

        /// <summary>
        /// 解包到memoryBuffer
        /// </summary>
        /// <param name="memoryBuffer"></param>
        /// <returns></returns>
        public bool Parse(out MemoryBuffer memoryBuffer)
        {
            while (true)
            {
                switch (this.state)
                {
                    //解析包头
                    case ParserState.PacketSize:
                        //Actor 消息
                        if (this.service.ServiceType == ServiceType.Actor)
                        {
                            if (this.buffer.Length < ActorPacketSizeLength)
                            {
                                memoryBuffer = null;
                                return false;
                            }

                            this.buffer.Read(this.cache, 0, ActorPacketSizeLength);
                            this.packetSize = BitConverter.ToInt32(this.cache, 0);
                            

                            //todo 检查包大小是否正常
                            if (this.packetSize > ushort.MaxValue * 16 || this.packetSize < Packet.MinPacketSize)
                            {
                                throw new Exception($"recv packet size error, 接收包大小错误! {this.packetSize}");
                            }
                        }
                        else
                        { //路由来的消息
                            if (this.buffer.Length < RouterPacketSizeLength)
                            {
                                memoryBuffer = null;
                                return false;
                            }

                            this.buffer.Read(this.cache, 0, RouterPacketSizeLength);
                            this.packetSize = BitConverter.ToUInt16(this.cache, 0);

                            if (this.packetSize < Packet.OpcodeLength || this.packetSize > ushort.MaxValue)
                            {
                                throw new Exception($"recv packet size error,Router 消息大小错误! {this.packetSize}");
                            }
                        }

                        this.state = ParserState.PacketBody;
                        break;
                    //解析包体
                    case ParserState.PacketBody:
                        if (this.buffer.Length < this.packetSize)
                        {
                            memoryBuffer = null;
                            return false;
                        }

                        memoryBuffer = this.service.Fetch(this.packetSize);
                        this.buffer.Read(memoryBuffer, this.packetSize);

                        memoryBuffer.Seek(0, SeekOrigin.Begin);
                        this.state = ParserState.PacketSize;
                        return true;
                    default: //不存在的情况
                        throw new ArgumentOutOfRangeException();
                }
            }
        }
    }
}