using PSO2SERVER.Database;
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
using System.Text;
using static PSO2SERVER.Models.CharacterStruct;

namespace PSO2SERVER.Protocol.Packets
{
    public class CharacterListPacket : Packet
    {
        public uint Characters_count { get; set; } = 0;
        public uint unk1 { get; set; } = 0;
        // Available characters
        public List<Character> Characters { get; set; } = new List<Character>();

        // Equipped items (List of 10 Items for each character)
        public List<PSO2Items[]> EquippedItems { get; set; } = new List<PSO2Items[]>();

        // Character play times (30 times)
        public List<uint> PlayTimes { get; set; } = new List<uint>();

        // Character deletion flags (flag, deletion timestamp) (30 pairs of (u32, u32))
        public List<(uint flag, uint timestamp)> DeletionFlags { get; set; } = new List<(uint, uint)>();

        // Character ship transfer flags (30 pairs of (u32, u32))
        public List<(uint flag, uint timestamp)> TransferFlags { get; set; } = new List<(uint, uint)>();

        // Account accessory flag (unknown)
        public ushort AccountAccessory { get; set; }

        // Login survey flag
        public uint LoginSurvey { get; set; }

        // Ad flag
        public uint Ad { get; set; }

        // Ninji note: This packet may be followed by extra data,
        // after a fixed-length array of character data structures.
        // Needs more investigation at some point.
        // --- 
        // CK note: Extra data is likely current equipment, playtime, etc.
        // All of that data is currently unaccounted for at the moment.
        //忍者注意:这个包后面可能有额外的数据，
        //在固定长度的字符数据结构数组之后。
        //需要更多的调查。
        // ---
        // CK注:额外的数据可能是当前设备，游戏时间等。
        //所有这些数据目前都是未知的。

        private int AccountId;

        public CharacterListPacket(int AccountId)
        {
            Characters = new List<Character>();
            EquippedItems = new List<PSO2Items[]>();
            PlayTimes = new List<uint>();
            DeletionFlags = new List<(uint, uint)>();
            TransferFlags = new List<(uint, uint)>();
            AccountAccessory = 0;
            LoginSurvey = 0;
            Ad = 0;
            this.AccountId = AccountId;
        }

        #region implemented abstract members of Packet

        public override byte[] Build()
        {
            using (var db = new ServerEf())
            {
                var chars = db.Characters
                    .Where(w => w.AccountID == AccountId)
                    .OrderBy(o => o.CharacterID) // TODO: 按照最后游玩的角色排序
                    .Select(s => s);

                foreach (var ch in chars)
                {
                    Characters.Add(ch);

                    //PSO2Items[] items = new PSO2Items[10];

                    //for (var i = 0; i < 10; i++)
                    //{
                    //    items[i] = new PSO2Items
                    //    {
                    //        uuid = (ulong)i,
                    //        id = new ItemId
                    //        {
                    //            ItemType = 3,
                    //            Id = 1,
                    //            Subid = 0,
                    //        },
                    //        data = new Items
                    //        {
                    //            Consumable = new PSO2ItemConsumable
                    //            {
                    //                flags = 0,
                    //                amount = 10,
                    //            },
                    //        }
                    //    };
                    //}

                    //ch.EquipedItems = items;

                    //EquippedItems.Add(ch.EquipedItems);

                    //ch.Playe_time = 0xFFFFFFFF;

                    //PlayTimes.Add(ch.Playe_time);

                    //var deletionFlags = (0, 0);

                    //DeletionFlags.Add(((uint flag, uint timestamp))deletionFlags);

                    //var transferFlags = (0, 0);

                    //TransferFlags.Add(((uint flag, uint timestamp))transferFlags);

                }

                Characters_count = (uint)Characters.Count();
            }

            var rest_count = 30 - Characters_count;

            for (var i = 0; i < rest_count; i++)
            {
                Characters.Add(Characters[0]);

                //EquippedItems.Add(EquippedItems[0]);

                //PlayTimes.Add(0x12345678);

                //var deletionFlags = (1, 3);

                //DeletionFlags.Add(((uint flag, uint timestamp))deletionFlags);

                //var transferFlags = (2, 4);

                //TransferFlags.Add(((uint flag, uint timestamp))transferFlags);
            }

            var pkt = new PacketWriter();

            pkt.Write(Characters_count); // 写入玩家数量
            pkt.Write(unk1);
            foreach (var ch in Characters)
            {
                pkt.Write((uint)0);
                pkt.Write(ch.BuildCharacterByteArray());//4
            }

            pkt.Write(File.ReadAllBytes("packets/charlist_rest.bin"));
            //pkt.Write((uint)EquippedItems.Count()); // 写入物品数量
            //foreach (var itemsArray in EquippedItems)
            //{
            //    foreach (var item in itemsArray)
            //    {
            //        pkt.Write(item.ToByteArray());
            //    }
            //}
            //// Write PlayTimes
            //foreach (var playTime in PlayTimes)
            //{
            //    pkt.Write(playTime);
            //}

            //pkt.WriteBytes(0, 32);

            //// Write DeletionFlags
            //foreach (var flag in DeletionFlags)
            //{
            //    pkt.Write(flag.flag);
            //    pkt.Write(flag.timestamp);
            //}
            //// Write TransferFlags
            //foreach (var flag in TransferFlags)
            //{
            //    pkt.Write(flag.flag);
            //    pkt.Write(flag.timestamp);
            //}

            //// Write AccountAccessory
            //pkt.Write(AccountAccessory);

            //pkt.WriteBytes(0, 6);

            //// Write LoginSurvey
            //pkt.Write(LoginSurvey);

            //// Write Ad
            //pkt.Write(Ad);

            //pkt.WriteBytes(0, 4);

            //pkt.WriteBytes(0, 4);

            return pkt.ToArray();
        }

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

        #endregion
    }
}