using PSO2SERVER.Models;
using System;

namespace PSO2SERVER.Protocol.Packets
{
    class LoginDataPacket : Packet
    {
        public enum LoginStatus : uint
        {
            /// <summary>
            /// Login was successful.
            /// </summary>
            Success = 0,

            /// <summary>
            /// Login failed.
            /// </summary>
            Failure = 1,

            /// <summary>
            /// Undefined status.
            /// </summary>
            Undefined = 0xFFFFFFFF
        }

        public LoginStatus Status;
        public string Error;
        public ObjectHeader Player;
        public string BlockName = new string(' ', 0x20);
        public float Unk1 = 0;
        public uint Unk2 = 0;
        public uint LevelCap = 0;
        public uint LevelCap2 = 0;
        public uint Unk5 = 0;
        public float Unk6 = 0;
        public float Unk7 = 0;
        public uint Unk8 = 0;
        public float Unk9 = 0;
        public float Unk10 = 0;
        public uint Unk11 = 0;
        public float Unk12 = 0;
        public uint Unk13 = 0;
        public float[] Unk14 = new float[10]; // Length: 10
        public float[] Unk15 = new float[21]; // Length: 21
        public float Unk16 = 0;
        public float Unk17 = 0;
        public float[] Unk18 = new float[9]; // Length: 9
        public uint[] Unk19 = new uint[2];   // Length: 2
        public uint Unk20 = 0;
        public uint Unk21 = 0;
        public float[] Unk22 = new float[3];  // Length: 3
        public uint Unk23 = 0;
        public float Unk24 = 0;
        public float Unk25 = 0;
        public uint Unk26 = 0;
        public byte[] Unk27 = new byte[12];    // Length: 12
        public string Unk28 = new string(' ', 0x20);
        public uint Unk29 = 0;
        public string Unk30 = new string(' ', 0x20);
        public uint Unk31 = 0;

        public LoginDataPacket(string blockName, string error, uint userid)
        {
            Status = (userid == 0) ? LoginStatus.Failure : LoginStatus.Success;
            Error = error;
            Player = new ObjectHeader(userid, ObjectType.Player);
            BlockName = blockName;
            Unk1 = 0x42700000;
            Unk2 = 7;
            LevelCap = 0x0A;
            LevelCap2 = 1;
            Unk5 = 0x41200000;
            Unk6 = 0x40A00000;
            Unk7 = 11;
            Unk8 = 0x3F800000;
            Unk9 = 0x42960000;
            Unk10 = 40;
            Unk11 = 0x41200000;
            Unk12 = 1;
            Unk13 = 1120403456;

            //WHAT
            for (int i = 0; i < Unk14.Length; i++)
            {
                Unk14[i] = 1065353216;
            }

            //ARE
            for (int i = 0; i < Unk15.Length; i++)
            {
                Unk15[i] = 1120403456;
            }
        }

        public override byte[] Build()
        {
            var pkt = new PacketWriter();
            pkt.Write((uint)Status);
            pkt.WriteUtf16(Error, 0x8BA4, 0xB6);

            if (Player.ID == 0)
            {
                for (var i = 0; i < 0xEC; i++)
                    pkt.Write((byte)0);
            }
            else
            {
                Player.WriteObjectHeaderToStream(pkt);
                pkt.WriteFixedLengthUtf16(BlockName, 0x20);
                pkt.Write(Unk1);
                pkt.Write(Unk2);
                pkt.Write(LevelCap);
                pkt.Write(LevelCap2);
                pkt.Write(Unk5);
                pkt.Write(Unk6);
                pkt.Write(Unk7);
                pkt.Write(Unk8);
                pkt.Write(Unk9);
                pkt.Write(Unk10);
                pkt.Write(Unk11);
                pkt.Write(Unk12);
                pkt.Write(Unk13);

                foreach (var val in Unk14)
                {
                    pkt.Write(val);
                }

                foreach (var val in Unk15)
                {
                    pkt.Write(val);
                }

                pkt.Write(Unk16);
                pkt.Write(Unk17);

                foreach (var val in Unk18)
                {
                    pkt.Write(val);
                }

                foreach (var val in Unk19)
                {
                    pkt.Write(val);
                }

                pkt.Write(Unk20);
                pkt.Write(Unk21);

                foreach (var val in Unk22)
                {
                    pkt.Write(val);
                }

                pkt.Write(Unk23);
                pkt.Write(Unk24);
                pkt.Write(Unk25);
                pkt.Write(Unk26);
                pkt.Write(Unk27);
                pkt.WriteFixedLengthUtf16(Unk28, 0x20);
                pkt.Write(Unk29);
                pkt.WriteFixedLengthUtf16(Unk30, 0x20);
                pkt.Write(Unk31);
            }

            return pkt.ToArray();
        }

        public override PacketHeader GetHeader()
        {
            return new PacketHeader(0x11, 0x01, PacketFlags.PACKED);
        }
    }
}
