using System;
using System.Diagnostics.Eventing.Reader;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using PSO2SERVER.Json;
using PSO2SERVER.Protocol;
using PSO2SERVER.Protocol.Handlers;
using PSO2SERVER.Protocol.Packets;

namespace PSO2SERVER.Models
{
    public class QuestDef
    {
        /// <summary>
        /// 任务日期
        /// </summary>
        [JsonProperty("date")]
        [JsonConverter(typeof(AsciiStringConverter))]
        public string Date { get; set; } = new string(' ', 32); // 0x20 length string

        /// <summary>
        /// 任务对象
        /// </summary>
        [JsonProperty("quest_obj")]
        public ObjectHeader QuestObj;

        /// <summary>
        /// 任务名称的ID
        /// </summary>
        [JsonProperty("name_id")]
        public uint NameId;

        /// <summary>
        /// 未知字段3（数组大小为27）
        /// </summary>
        [JsonProperty("unk3")]
        public uint[] Unk3 = new uint[27];

        /// <summary>
        /// 未知字段4
        /// </summary>
        [JsonProperty("unk4")]
        public ushort Unk4;

        /// <summary>
        /// 未知字段5
        /// </summary>
        [JsonProperty("unk5")]
        public byte Unk5;

        /// <summary>
        /// 未知字段6
        /// </summary>
        [JsonProperty("unk6")]
        public byte Unk6;

        /// <summary>
        /// 未知字段7（数组大小为20）
        /// </summary>
        [JsonProperty("unk7")]
        public uint[] Unk7 = new uint[20];

        /// <summary>
        /// 未知字段8（数组大小为3）
        /// </summary>
        [JsonProperty("unk8")]
        public ushort[] Unk8 = new ushort[3];

        /// <summary>
        /// 任务时长
        /// </summary>
        [JsonProperty("length")]
        public byte Length;

        /// <summary>
        /// 任务的队伍类型
        /// </summary>
        [JsonProperty("party_type")]
        [JsonConverter(typeof(QuestPartyTypeConverter))]
        public QuestPartyType PartyType;

        /// <summary>
        /// 可用的难度
        /// </summary>
        [JsonProperty("difficulties")]
        public QuestDifficultyType Difficulties;

        /// <summary>
        /// 已完成的难度
        /// </summary>
        [JsonProperty("difficulties_completed")]
        public QuestDifficultyType DifficultiesCompleted;

        /// <summary>
        /// 未知字段9
        /// </summary>
        [JsonProperty("unk9")]
        public byte Unk9;

        /// <summary>
        /// 所需等级
        /// </summary>
        [JsonProperty("req_level")]
        public byte ReqLevel;

        /// <summary>
        /// 所需副职业等级
        /// </summary>
        [JsonProperty("sub_class_req_level")]
        public byte SubClassReqLevel;

        /// <summary>
        /// 敌人等级
        /// </summary>
        [JsonProperty("enemy_level")]
        public byte EnemyLevel;

        /// <summary>
        /// 未知字段10
        /// </summary>
        [JsonProperty("unk10")]
        public byte Unk10;

        /// <summary>
        /// 任务类型
        /// </summary>
        [JsonProperty("quest_type")]
        public QuestType QuestType;

        /// <summary>
        /// 未知字段11（数组大小为6）
        /// </summary>
        [JsonProperty("unk11")]
        public byte[] Unk11 = new byte[6];

        /// <summary>
        /// 未知字段12
        /// </summary>
        [JsonProperty("unk12")]
        public ushort Unk12;

        /// <summary>
        /// 未知字段13（数组大小为2）
        /// </summary>
        [JsonProperty("unk13")]
        public uint[] Unk13 = new uint[2];

        /// <summary>
        /// 未知字段14
        /// </summary>
        [JsonProperty("unk14")]
        public ushort Unk14;

        /// <summary>
        /// 未知字段15（数组大小为2）
        /// </summary>
        [JsonProperty("unk15")]
        public byte[] Unk15 = new byte[2];

        // 任务相关的其他字段
        // public QuestThing[] Unk15 = new QuestThing[16];

        /// <summary>
        /// 未知字段16（大小为0x320字节）
        /// </summary>
        [JsonProperty("unk16")]
        public byte[] Unk16 = new byte[0x320];

        // 从数据流中读取数据并填充到当前结构体
        public void ReadFromStream(PacketReader reader)
        {
            //TODO
        }

        // 将当前结构体的数据写入到数据流
        public void WriteToStream(PacketWriter pkt)
        {
            pkt.WriteFixedLengthASCII(Date, 0x20);
            pkt.WriteObjectHeader(QuestObj);
            pkt.Write(NameId);
            pkt.WriteIntArray(Unk3);
            pkt.Write(Unk4);
            pkt.Write(Unk5);
            pkt.Write(Unk6);
            pkt.WriteIntArray(Unk7);
            pkt.WriteShortArray(Unk8);
            pkt.Write(Length);
            pkt.Write((byte)PartyType);
            pkt.Write((byte)Difficulties);
            pkt.Write((byte)DifficultiesCompleted);
            pkt.Write(Unk9);
            pkt.Write(ReqLevel);
            pkt.Write(SubClassReqLevel);
            pkt.Write(EnemyLevel);
            pkt.Write(Unk10);
            pkt.Write((byte)QuestType);
            pkt.Write(Unk11);
            pkt.Write(Unk12);
            pkt.WriteIntArray(Unk13);
            pkt.Write(Unk14);
            pkt.Write(Unk15);
            pkt.Write(Unk16);
        }
    }

    public class QuestDiff
    {
        /// <summary>
        /// PartyQuest date.
        /// </summary>
        [JsonProperty("date")]
        [JsonConverter(typeof(AsciiStringConverter))]
        public string Date { get; set; } = new string(' ', 32); // 0x20 length string

        /// <summary>
        /// PartyQuest object.
        /// </summary>
        [JsonProperty("quest_obj")]
        public ObjectHeader QuestObj { get; set; }

        /// <summary>
        /// ID of the quest name.
        /// </summary>
        [JsonProperty("name_id")]
        public uint NameId { get; set; }

        /// <summary>
        /// Planet ID.
        /// </summary>
        [JsonProperty("planet")]
        public byte Planet { get; set; }

        /// <summary>
        /// Area ID.
        /// </summary>
        [JsonProperty("area")]
        public byte Area { get; set; }

        /// <summary>
        /// Unknown field.
        /// </summary>
        [JsonProperty("unk1")]
        public byte Unk1 { get; set; }

        /// <summary>
        /// Unknown field.
        /// </summary>
        [JsonProperty("unk2")]
        public byte Unk2 { get; set; }

        /// <summary>
        /// Difficulty list.
        /// </summary>
        [JsonProperty("diffs")]
        public QuestDifficultyEntry[] Diffs { get; set; } = new QuestDifficultyEntry[8];

        // 从数据流中读取数据并填充到当前结构体
        public void ReadFromStream(PacketReader reader)
        {
            //TODO
        }

        // 将当前结构体的数据写入到数据流
        public void WriteToStream(PacketWriter pkt)
        {
            pkt.WriteFixedLengthASCII(Date, 0x20);
            pkt.WriteObjectHeader(QuestObj);
            pkt.Write(NameId);
            pkt.Write(Planet);
            pkt.Write(Area);
            pkt.Write(Unk1);
            pkt.Write(Unk2);
            pkt.WriteStructArray(Diffs);
        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public unsafe struct QuestDefiniton
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dateOrSomething;
        public ObjectHeader quest_obj;
        public uint questNameid;
        //27个uint
        public uint field_30;
        public uint field_34;
        public uint field_38;
        public uint field_3C;
        public uint field_40;
        public uint field_44;
        public uint field_48;
        public uint field_4C;
        public uint field_50;
        public uint field_54;
        public uint field_58;
        public uint field_5C;
        public uint field_60;
        public uint field_64;
        public uint field_68;
        public uint field_6C;
        public uint field_70;
        public uint field_74;
        public uint field_78;
        public uint field_7C;
        public uint field_80;
        public uint field_84;
        public uint field_88;
        public uint field_8C;
        public uint field_90;
        public uint field_94;
        public uint field_98;

        public UInt16 field_9C;
        public byte field_9E;
        public byte field_9F;
        //20个uint
        public uint field_A0;
        public uint field_A4;
        public uint field_A8;
        public uint field_AC;
        public uint field_B0;
        public uint field_B4;
        public uint field_B8;
        public uint field_BC;
        public uint field_C0;
        public uint field_C4;
        public uint field_C8;
        public uint field_CC;
        public uint field_D0;
        public uint field_D4;
        public uint field_D8;
        public uint field_DC;
        public uint field_E0;
        public uint field_E4;
        public uint field_E8; // Maybe a flags
        public uint field_EC;

        public ushort field_F0;
        public ushort field_F2;
        public QuestBitfield1 questBitfield1;

        /// Length of the quest.
        public QuestEstimatedTime playTime;

        /// Party type of the quest.
        public QuestPartyType partyType;

        /// Available difficulties.
        public QuestDifficultyType difficulties;

        /// Completed difficulties.
        public QuestDifficultyType difficultiesCompleted;

        public byte field_FA;
        /// Required level.
        public byte req_level;
        /// Required sub level.
        public byte sub_class_req_level;
        /// Enemy level.
        public byte enemy_level;

        public byte field_FE;

        /// Type of the quest.
        public QuestType quest_type;

        public byte field_100;
        public byte field_101;
        public byte field_102;
        public byte field_103;
        public byte field_104;
        public byte field_105;

        public ushort field_106;

        public uint field_108;
        public uint field_10C;

        public ushort field_110;

        public byte field_112;
        public byte field_113;

        public fixed byte field_114[0x320];
    }

    public class PartyQuest
    {
        public int seed { get; set; }
        public string name { get; set; }
        public QuestDefiniton questDef { get; set; }
        public QuestData Quest { get; set; }
        public ushort Diff { get; set; } = 0;

        public PartyQuest()
        {
        }

        public PartyQuest(string name)
        {
            this.name = name;
        }

        public PartyQuest(string name, QuestData quest)
        {
            this.name = name;
            Quest = quest;
        }
    }

    public struct QuestThing
    {
        public uint field_0;
        public uint field_4;
        public byte field_8;
        public byte field_9;
        public ushort field_A;
    }

    //Size: 308 bytes, confirmed in unpacker
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public unsafe struct QuestDifficulty
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
        public string dateOrSomething;
        public ObjectHeader quest_obj;
        public uint name_id;
        public byte area;
        public byte planet;
        public byte unk1;
        public byte unk2;
        public QuestDifficultyEntry difficulty1;
        public QuestDifficultyEntry difficulty2;
        public QuestDifficultyEntry difficulty3;
        public QuestDifficultyEntry difficulty4;
        public QuestDifficultyEntry difficulty5;
        public QuestDifficultyEntry difficulty6;
        public QuestDifficultyEntry difficulty7;
        public QuestDifficultyEntry difficulty8;
    }

    //Size: 32, confirmed in ctor TODO
    public struct QuestDifficultyEntry
    {
        public byte ReqLevel;
        public byte SubClassReqLevel;
        public byte MonsterLevel;
        public byte Unk1;
        public uint AbilityAdj;
        public uint DmgLimit;
        public uint TimeLimit;
        public uint TimeLimit2;
        public uint SuppTarget;
        public uint Unk2;
        public uint Enemy1;
        public uint Unk3;
        public uint Enemy2;
        public uint Unk4;
    }
}