using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using PSO2SERVER.Models;
using PSO2SERVER.Zone;

namespace PSO2SERVER.Protocol
{
    public class PacketWriter : BinaryWriter
    {
        public PacketWriter()
            : base(new MemoryStream())
        {
        }

        public PacketWriter(Stream s)
            : base(s)
        {
        }

        public void WriteMagic(uint magic, uint xor, uint sub)
        {
            var encoded = (magic + sub) ^ xor;
            Write(encoded);
        }

        public void WriteAscii(string str, uint xor, uint sub)
        {
            if((str == null) || (str == "") || (str.Length == 0))
            {

                WriteMagic(0, xor, sub);
                //if (str.Length == 0)
                //{
                //}
            }
            else
            {
                // Magic, followed by string, followed by null terminator,
                // followed by padding characters if needed.
                var charCount = (uint) str.Length;
                var padding = 4 - (charCount & 3);

                WriteMagic(charCount + 1, xor, sub);
                Write(Encoding.ASCII.GetBytes(str));
                for (var i = 0; i < padding; i++)
                    Write((byte) 0);
            }
        }

        public void WriteAscii(AsciiString str, uint xor, uint sub)
        {
            if (str == null || str.Length == 0)
            {
                // 如果 AsciiString 为空或长度为 0，写入 magic，长度为 0
                WriteMagic(0, xor, sub);
            }
            else
            {
                // Magic, followed by string, followed by null terminator,
                // followed by padding characters if needed.
                var charCount = (uint)str.Length;
                var padding = (4 - (charCount + 1) % 4) % 4; // +1 用于计算 null 终结符的空间

                // 写入 Magic 值（charCount + 1：包括 null 终结符）
                WriteMagic(charCount + 1, xor, sub);

                // 写入字符串的字节数据
                Write(str.ToBytes());

                // 填充 null 字节以保证 4 字节对齐
                for (var i = 0; i < padding; i++)
                {
                    Write((byte)0);
                }
            }
        }

        public void WriteUtf16(string str, uint xor, uint sub)
        {
            if ((str == null) || (str == "") || (str.Length == 0))
            {
                WriteMagic(0, xor, sub);
            }
            else
            {
                // Magic, followed by string, followed by null terminator,
                // followed by a padding character if needed.
                var charCount = (uint) str.Length + 1;
                var padding = (charCount & 1);

                WriteMagic(charCount, xor, sub);
                Write(Encoding.GetEncoding("UTF-16").GetBytes(str));
                Write((ushort) 0);
                if (padding != 0)
                    Write((ushort) 0);
            }
        }

        public void WriteFixedLengthASCII(string str, int charCount)
        {
            var writeAmount = Math.Min(str.Length, charCount);
            var paddingAmount = charCount - writeAmount;

            if (writeAmount > 0)
            {
                var chopped = writeAmount != str.Length ? str.Substring(0, writeAmount) : str;

                Write(Encoding.GetEncoding("ASCII").GetBytes(chopped));
            }

            if (paddingAmount > 0)
            {
                for (var i = 0; i < paddingAmount; i++)
                    Write((byte) 0);
            }
        }

        public void WriteFixedLengthUtf16(string str, int charCount)
        {
            var writeAmount = Math.Min(str.Length, charCount);
            var paddingAmount = charCount - writeAmount;

            if (writeAmount > 0)
            {
                var chopped = writeAmount != str.Length ? str.Substring(0, writeAmount) : str;

                Write(Encoding.GetEncoding("UTF-16").GetBytes(chopped));
            }

            if (paddingAmount > 0)
            {
                for (var i = 0; i < paddingAmount; i++)
                    Write((ushort) 0);
            }
        }

        internal void WritePosition(PSOLocation location)
        {
            Write(Helper.FloatToHalfPrecision(location.RotX));
            Write(Helper.FloatToHalfPrecision(location.RotY));
            Write(Helper.FloatToHalfPrecision(location.RotZ));
            Write(Helper.FloatToHalfPrecision(location.RotW));
            Write(Helper.FloatToHalfPrecision(location.PosX));
            Write(Helper.FloatToHalfPrecision(location.PosY));
            Write(Helper.FloatToHalfPrecision(location.PosZ));
        }

        public void WriteAccountHeader(uint AccountId)
        {
            Write(AccountId);
            Write((uint) 0);
            Write((ushort)ObjectType.Player);
            Write((ushort) 0);
        }

        public unsafe void WriteStruct<T>(T structure) where T : struct
        {
            int size = Marshal.SizeOf(structure);
            //Logger.Write($"写入 {size} 字节,结构体: {structure}");

            var strArr = new byte[size];

            fixed (byte* ptr = strArr)
            {
                Marshal.StructureToPtr(structure, (IntPtr)ptr, false);
            }

            Write(strArr);
        }

        // 新增的 WriteStructArray 方法
        public unsafe void WriteStructArray<T>(T[] structures) where T : struct
        {
            int totalSize = Marshal.SizeOf(typeof(T)) * structures.Length;
            var strArr = new byte[totalSize];

            fixed (byte* ptr = strArr)
            {
                for (int i = 0; i < structures.Length; i++)
                {
                    byte* currentPtr = ptr + (i * Marshal.SizeOf(typeof(T)));
                    Marshal.StructureToPtr(structures[i], (IntPtr)currentPtr, false);
                }
            }

            Write(strArr);
        }

        public byte[] ToArray()
        {
            var ms = (MemoryStream) BaseStream;
            return ms.ToArray();
        }

        public void WriteBytes(byte b, uint count)
        {
            for(int i = 0; i < count; i++)
            {
                Write(b);
            }
        }

        public void WriteByteArray(byte[] b)
        {
            Write(b);
        }

        public void WriteUintArray(uint[] array)
        {
            foreach (var item in array)
            {
                Write(item);
            }
        }

        public void WriteIntArray(int[] array)
        {
            foreach (var item in array)
            {
                Write(item);
            }
        }

        public void WriteFloatArray(float[] array)
        {
            foreach (var item in array)
            {
                Write(item);
            }
        }

        public void WriteObjectHeader(ObjectHeader obj)
        {
            Write(obj.ID);
            Write(obj.padding);
            Write((ushort)obj.ObjectType);
            Write(obj.MapID);
        }

        public void WriteObjectHeaderArray(ObjectHeader[] objlist)
        {
            foreach (var obj in objlist)
            {
                WriteObjectHeader(obj);
            }
        }

        public void WriteObjectHeaderList(List<ObjectHeader> objlist)
        {
            foreach (var obj in objlist)
            {
                WriteObjectHeader(obj);  // 直接写入每个 ObjectHeader 对象
            }
        }

        // 支持 Guid 类型
        public void WriteGuid(Guid guid)
        {
            Write(guid.ToByteArray());
        }

        // 支持 DateTime 类型
        public void WriteDateTime(DateTime dateTime)
        {
            var timestamp = new DateTimeOffset(dateTime).ToUnixTimeSeconds();
            Write(timestamp);
        }

        // 支持 List<T>
        public void WriteList<T>(List<T> list) where T : struct
        {
            foreach (var item in list)
            {
                WriteStruct(item);
            }
        }

        // 支持 2D 数组
        public void Write2DIntArray(int[,] array)
        {
            for (int i = 0; i < array.GetLength(0); i++)
            {
                for (int j = 0; j < array.GetLength(1); j++)
                {
                    Write(array[i, j]);
                }
            }
        }

        // 支持 2D 数组
        public void Write2DUIntArray(uint[,] array)
        {
            for (int i = 0; i < array.GetLength(0); i++)
            {
                for (int j = 0; j < array.GetLength(1); j++)
                {
                    Write(array[i, j]);
                }
            }
        }

        // 写入 Half 类型（16 位浮动点数）
        public void WriteHalf(Half value)
        {
            Write(Half.GetBytes(value));  // 写入 2 个字节
        }
    }
}