using System;
using System.IO;
using ActorCore;
using GameData;
using MrWu.Debug;
using NetWorkMessage;
using Server.Core;

namespace Server.Net
{
    public static class MessageSerializeHelper
    {
        public static void Serialize(MessageObject message, MemoryBuffer stream)
        {
            MessagePackHelper.Serialize(message, stream);
        }

        public static MessageObject Deserialize(Type type, MemoryBuffer stream)
        {
            object o = MessagePackHelper.Deserialize(type, stream.GetMemory());
            return o as MessageObject;
        }

        //[fromActorId][ActorId][opcode][message]
        public static uint MessageToStream(MemoryBuffer stream, MessageObject message, int headOffset = 0)
        {
            uint opcode = OpcodeType.Instance.GetOpcode(message.GetType());

            stream.Seek(headOffset + Packet.MessageIndex, SeekOrigin.Begin);
            stream.SetLength(headOffset + Packet.OpcodeLength);

            //写入 Opcode
            stream.GetBuffer().WriteTo(headOffset, opcode);
            Debug.Log($"Position:{stream.Position} {headOffset}");
            Serialize(message, stream);
            Debug.Log($"序列化包后的大小:{stream.Position}");
            stream.Seek(0, SeekOrigin.Begin);
            return opcode;
        }

        public static (uint, MemoryBuffer) ToActorMemoryBuffer(TService service, ActorId fromActorId, ActorId actorId,
            object message)
        {
            MemoryBuffer memoryBuffer = service.Fetch();
            uint opcode = MessageToStream(memoryBuffer, (MessageObject)message, Packet.MessageIndex);
            Debug.Log($"当前Position:{memoryBuffer.Position} {memoryBuffer.Length}");
            memoryBuffer.GetBuffer().WriteTo(0, fromActorId);
            memoryBuffer.GetBuffer().WriteTo(Packet.ActorIdLength, actorId);
            memoryBuffer.Seek(0, SeekOrigin.Begin);
            Debug.Log($"当前Position:{memoryBuffer.Position} {memoryBuffer.Length}");
            ((MessageObject)message).Dispose();
            return (opcode, memoryBuffer);
        }

        //[opcode][内容]
        public static (uint, MemoryBuffer) ToRouterMemoryBuffer(TService service,IMessage message)
        {
            MemoryBuffer memoryBuffer = service.Fetch();
            uint opcode = OpcodeType.Instance.GetOpcode(message.GetType());
            
            //长度
            memoryBuffer.Seek(RouterPacket.RouterPacketLength, SeekOrigin.Begin); //给长度 预留位置
            
            //先写入包内容，因为它会清除前面的内容 MemoryStream 机制导致的
            Serialize((MessageObject)message, memoryBuffer);
            
            //写入 Opcode
            memoryBuffer.GetBuffer().WriteTo(0,opcode);
            memoryBuffer.Seek(0, SeekOrigin.Begin);
            return (opcode, memoryBuffer);
        }

        public static (ActorId, ActorId, IMessage) ToActorMessage(TService service, MemoryBuffer memoryBuffer)
        {
            IMessage message = null;
            ActorId formActorId = default;
            ActorId actorId = default;

            memoryBuffer.Seek(Packet.MessageIndex + Packet.OpcodeLength, SeekOrigin.Begin);
            byte[] buffer = memoryBuffer.GetBuffer();
            uint opcode = BitConverter.ToUInt32(buffer, Packet.MessageIndex);
            //Debug.Log($"解析出opcode:{opcode}");
            Type type = OpcodeType.Instance.GetType(opcode);
            if (type == null)
            {
                Debug.Error($"无法解析的消息类型：{opcode}");
            }
            else
            {
                //解析消息
                message = Deserialize(type, memoryBuffer);
                formActorId = buffer.ReadActorId(0);
                //Debug.Log($"formActorId:{formActorId}");
                actorId = buffer.ReadActorId(Packet.ActorIdLength);
                //Debug.Log($"actorId:{actorId}");
            }

            service.Recycle(memoryBuffer);

            return (formActorId, actorId, message);
        }

        // 4 总长度 4 路由包长 4 opcode 类型 具体数据 4 客户端包长 4 opcode 客户端包类型 客户端具体数据
        public static (uint, IMessage) ToRouterMessage(TService service, MemoryBuffer memoryBuffer)
        {
            IMessage message = null;
            byte[] buffer = memoryBuffer.GetBuffer();
            
            //路由总长度
            uint opcode = BitConverter.ToUInt32(buffer, 0);
            Type type = OpcodeType.Instance.GetType(opcode);
            if (type == null)
            {
                Debug.Error($"Router消息 无法解析的消息类型:{opcode}");
            }
            else
            {
                memoryBuffer.Seek(RouterPacket.RouterPacketLength, SeekOrigin.Begin);
                //序列化得到路由包
                message = Deserialize(type, memoryBuffer);
            }
            
            return (opcode, message);
        }
    }
}