using System;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace PSO2SERVER.Models
{
    public struct PacketHeader
    {
        public UInt32 Size;
        public byte Type;
        public byte Subtype;
        public byte Flags1;
        public byte Flags2;

        public PacketHeader(int size, byte type, byte subtype, byte flags1, byte flags2)
        {
            this.Size = (uint)size;
            this.Type = type;
            this.Subtype = subtype;
            this.Flags1 = flags1;
            this.Flags2 = flags2;
        }

        public PacketHeader(int size, byte type, byte subtype, PacketFlags flags1, PacketFlags flags2) : this(size, type, subtype, (byte)flags1, (byte)flags1)
        {
        }

        public PacketHeader(byte type, byte subtype) : this(type, subtype, (byte)0)
        {
        }

        public PacketHeader(byte type, byte subtype, byte flags1) : this(0, type, subtype, flags1, 0)
        {
        }

        public PacketHeader(byte type, byte subtype, PacketFlags packetFlags) : this(type, subtype, (byte)packetFlags)
        {
        }

        // ToBytes 方法的实现
        public byte[] ToBytes()
        {
            byte[] bytes = new byte[sizeof(UInt32) + sizeof(byte) * 4]; // 计算结构体的总大小
            int index = 0;

            // 将结构体每个字段转换为字节
            Array.Copy(BitConverter.GetBytes(Size), 0, bytes, index, sizeof(UInt32));
            index += sizeof(UInt32);

            bytes[index++] = Type;
            bytes[index++] = Subtype;
            bytes[index++] = Flags1;
            bytes[index++] = Flags2;

            return bytes;
        }
    }

    /// Packet flags.
    [Flags]
    public enum PacketFlags : byte
    {
        /// 0x00
        None = 0x00,
        /// Set when the packet contains variable length data. 0x04
        PACKED = 1 << 2,
        /// 0x10
        FLAG_10 = 1 << 4,
        /// Set when the [`Packet::Movement`] has all fields set. 0x20
        FULL_MOVEMENT = 1 << 5,
        /// Set for all (?) of (0x04) packets. 0x40
        OBJECT_RELATED = 1 << 6,
        /// 0x44
        PACKED_OBJECT_RELATED = PACKED | OBJECT_RELATED
    }
}

