using PSO2SERVER.Database;
using PSO2SERVER.Models;
using PSO2SERVER.Zone;
using System.Runtime.InteropServices;
using static PSO2SERVER.Models.CharacterStruct;
using static PSO2SERVER.Protocol.Packets.CharacterSpawnPacket;

namespace PSO2SERVER.Protocol.Packets
{
    public class CharacterSpawnPacket : Packet
    {
        public enum CharacterSpawnType : byte
        {
            /// Spawned character is not related to the receiver.
            Other = 0x27,
            /// Spawned character is related to the receiver.
            Myself = 0x2F,

            Undefined = 0xFF,
        }

        private readonly Character _character;
        public byte IsItMe = (byte)CharacterSpawnType.Myself;
        public uint IsGM = 0;
        public PSOLocation Position;

        public CharacterSpawnPacket(Character character, PSOLocation locatiion)
        {
            _character = character;
            Position = locatiion;
        }

        public CharacterSpawnPacket(Character character, PSOLocation locatiion, bool isme, uint isgm)
        {
            _character = character;
            IsItMe = isme ? (byte)CharacterSpawnType.Myself : (byte)CharacterSpawnType.Other;
            Position = locatiion;
            IsGM = isgm;
        }

        #region implemented abstract members of Packet

        public override byte[] Build()
        {
            var writer = new PacketWriter();

            // Accounts header
            writer.WriteAccountHeader((uint)_character.Account.AccountId);

            // Spawn position
            writer.WritePosition(Position);

            writer.Write((ushort)0);
            writer.WriteFixedLengthASCII("Character", 32);
            writer.Write((ushort)1); // 0x44
            writer.Write((ushort)0); // 0x46
            writer.Write((uint)602); // 0x48
            writer.Write((uint)1); // 0x4C
            writer.Write((uint)53); // 0x50
            writer.Write((uint)0); // 0x54

            // Character spawn type.
            writer.Write(IsItMe); // 0x58
            writer.Write((byte)0x00);
            writer.Write((ushort)0x00);

            ////writer.write((ushort)0x022f); // 0x5c
            //writer.write((byte)0x2f); // 0x5c
            //writer.write((byte)0x02);
            ////writer.write((ushort)0x0132); // 0x5e
            //writer.write((byte)0x32);
            //writer.write((byte)0x01);

            // Character data.
            writer.Write((uint)_character.AccountID);
            writer.Write((uint)_character.CharacterID);
            writer.Write((uint)_character.Unk1);//4
            writer.Write((uint)_character.VoiceType);//4
            writer.Write((ushort)_character.Unk2);//2
            writer.Write(_character.VoicePitch);//2
            writer.WriteFixedLengthUtf16(_character.Name, 16);
            writer.Write((uint)_character.Unk3); // 0x90
            writer.WriteStruct(_character.Looks);
            JobParam jobParam = _character.Jobs;
            jobParam.mainClass = ClassType.Luster;
            jobParam.subClass = ClassType.Phantom;
            jobParam.entries.Luster.level = 100;
            writer.WriteStruct(jobParam);
            writer.WriteFixedLengthUtf16(_character.Account.Nickname, 16);
            writer.WriteBytes(0, 116);

            writer.Write((uint)0); // 0x204
            writer.Write(IsGM); // gmflag?


            for (var i = 0; i < 0x60; i++)
                writer.Write((byte)0);

            //for (var i = 0; i < 0x40; i++)
            //    writer.Write((byte)0);

            return writer.ToArray();
        }

        public override PacketHeader GetHeader()
        {
            return new PacketHeader(0x08, 0x04, PacketFlags.None);
        }

        #endregion
    }
}