using System;
using System.Runtime.InteropServices;
using PSO2SERVER.Protocol.Packets;

namespace PSO2SERVER.Models
{
    public enum QuestType : byte
    {
        Unk0 = 0,             // 0x00
        Extreme = 1,          // 0x01
        ARKS = 3,             // 0x03
        LimitedTime = 4,      // 0x04
        ExtremeDebug = 5,     // 0x05
        Blank1 = 6,           // 0x06
        NetCafe = 8,          // 0x08
        WarmingDebug = 9,     // 0x09
        Blank2 = 10,          // 0x0A
        Advance = 11,         // 0x0B
        Expedition = 12,      // 0x0C
        FreeDebug = 13,       // 0x0D
        ArksDebug = 14,       // 0x0E
        Challenge = 16,       // 0x10
        Urgent = 17,          // 0x11
        UrgentDebug = 18,     // 0x12
        TimeAttack = 19,      // 0x13
        TimeDebug = 20,       // 0x14
        ArksDebug2 = 21,      // 0x15
        ArksDebug3 = 22,      // 0x16
        ArksDebug4 = 23,      // 0x17
        ArksDebug5 = 24,      // 0x18
        ArksDebug6 = 25,      // 0x19
        ArksDebug7 = 26,      // 0x1A
        ArksDebug8 = 27,      // 0x1B
        ArksDebug9 = 28,      // 0x1C
        ArksDebug10 = 29,     // 0x1D
        Blank3 = 30,          // 0x1E
        Recommended = 32,     // 0x20
        Ultimate = 33,        // 0x21
        UltimateDebug = 34,   // 0x22
        AGP = 35,             // 0x23
        Bonus = 36,           // 0x24
        StandardTraining = 37,// 0x25
        HunterTraining = 38,  // 0x26
        RangerTraining = 39,  // 0x27
        ForceTraining = 40,   // 0x28
        FighterTraining = 41, // 0x29
        GunnerTraining = 42,  // 0x2A
        TechterTraining = 43, // 0x2B
        BraverTraining = 44,  // 0x2C
        BouncerTraining = 45, // 0x2D
        SummonerTraining = 46,// 0x2E
        AutoAccept = 47,      // 0x2F
        Ridroid = 48,         // 0x30
        CafeAGP = 49,         // 0x31
        BattleBroken = 50,    // 0x32
        BusterDebug = 51,     // 0x33
        Poka12 = 52,          // 0x34
        StoryEP1 = 55,        // 0x37
        Buster = 56,          // 0x38
        HeroTraining = 57,    // 0x39
        Amplified = 58,       // 0x3A
        DarkBlastTraining = 61,// 0x3D
        Endless = 62,         // 0x3E
        Blank4 = 64,          // 0x40
        PhantomTraining = 65, // 0x41
        AISTraining = 66,     // 0x42
        DamageCalculation = 68,// 0x44
        EtoileTraining = 69,  // 0x45
        Divide = 70,          // 0x46
        Stars1 = 71,          // 0x47
        Stars2 = 72,          // 0x48
        Stars3 = 73,          // 0x49
        Stars4 = 74,          // 0x4A
        Stars5 = 75,          // 0x4B
        Stars6 = 76,          // 0x4C
    }


    [Flags]
    public enum AvailableQuestType : ulong
    {
        EXTREME = 1UL << 1,
        STORY_EP1 = 1UL << 2,
        ARKS = 1UL << 3,
        LIMITED_TIME = 1UL << 4,
        EXTREME_DEBUG = 1UL << 5,
        BLANK1 = 1UL << 6,
        STORY_EP2 = 1UL << 7,

        NET_CAFE = 1UL << 8,
        WARMING_DEBUG = 1UL << 9,
        BLANK2 = 1UL << 10,
        ADVANCE = 1UL << 11,
        EXPEDITION = 1UL << 12,
        FREE_DEBUG = 1UL << 13,
        ARKS_DEBUG = 1UL << 14,
        STORY_DEBUG = 1UL << 15,

        CHALLENGE = 1UL << 16,
        URGENT = 1UL << 17,
        URGENT_DEBUG = 1UL << 18,
        TIME_ATTACK = 1UL << 19,
        TIME_DEBUG = 1UL << 20,
        ARKS_DEBUG2 = 1UL << 21,
        ARKS_DEBUG3 = 1UL << 22,
        ARKS_DEBUG4 = 1UL << 23,

        ARKS_DEBUG5 = 1UL << 24,
        ARKS_DEBUG6 = 1UL << 25,
        ARKS_DEBUG7 = 1UL << 26,
        ARKS_DEBUG8 = 1UL << 27,
        ARKS_DEBUG9 = 1UL << 28,
        ARKS_DEBUG10 = 1UL << 29,
        BLANK3 = 1UL << 30,
        STORY_EP3 = 1UL << 31,

        RECOMMENDED = 1UL << 32,
        ULTIMATE = 1UL << 33,
        ULTIMATE_DEBUG = 1UL << 34,
        AGP = 1UL << 35,
        BONUS = 1UL << 36,
        UNK1 = 1UL << 37,
        STANDARD_TRAINING = 1UL << 38,
        HUNTER_TRAINING = 1UL << 39,

        RANGER_TRAINING = 1UL << 40,
        FORCE_TRAINING = 1UL << 41,
        FIGHTER_TRAINING = 1UL << 42,
        GUNNER_TRAINING = 1UL << 43,
        TECHTER_TRAINING = 1UL << 44,
        BRAVER_TRAINING = 1UL << 45,
        BOUNCER_TRAINING = 1UL << 46,
        SUMMONER_TRAINING = 1UL << 47,

        AUTO_ACCEPT = 1UL << 48,
        RIDROID = 1UL << 49,
        NET_CAFE_AGP = 1UL << 50,
        BATTLE_BROKEN = 1UL << 51,
        BUSTER_DEBUG = 1UL << 52,
        POKA12 = 1UL << 53,
        UNK2 = 1UL << 54,
        UNK3 = 1UL << 55,

        BUSTER = 1UL << 56,
        HERO_TRAINING = 1UL << 57,
        AMPLIFIED = 1UL << 58,
        UNK4 = 1UL << 59,
        UNK5 = 1UL << 60,
        DARK_BLAST_TRAINING = 1UL << 61,
        ENDLESS = 1UL << 62,
        UNK6 = 1UL << 63,

        BLANK4 = 1UL << 64,
        PHANTOM_TRAINING = 1UL << 65,
        AIS_TRAINING = 1UL << 66,
        UNK7 = 1UL << 67,
        DAMAGE_CALC = 1UL << 68,
        ETOILE_TRAINING = 1UL << 69,
        DIVIDE = 1UL << 70,
        STARS1 = 1UL << 71,

        STARS2 = 1UL << 72,
        STARS3 = 1UL << 73,
        STARS4 = 1UL << 74,
        STARS5 = 1UL << 75,
        STARS6 = 1UL << 76,
        UNK8 = 1UL << 77
    }

    [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 QuestThing field_114_1;
        //public QuestThing field_114_2;
        //public QuestThing field_114_3;
        //public QuestThing field_114_4;
        //public QuestThing field_114_5;
        //public QuestThing field_114_6;
        //public QuestThing field_114_7;
        //public QuestThing field_114_8;
        //public QuestThing field_114_9;
        //public QuestThing field_114_10;
        //public QuestThing field_114_11;
        //public QuestThing field_114_12;
        //public QuestThing field_114_13;
        //public QuestThing field_114_14;
        //public QuestThing field_114_15;
        //public QuestThing field_114_16;
        public fixed byte field_114[0x320];
    }

    public enum QuestEstimatedTime : byte
    {
        Short = 1,
        Medium,
        Long
    }

    public class Quest
    {
        public int seed;
        public string name;
        public QuestDefiniton questDef;


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

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

    [Flags]
    public enum QuestDifficultyType : byte
    {
        NORMAL = 1 << 0,    // 1 0x01 (0000 0001)
        HARD = 1 << 1,      // 2 0x02 (0000 0010)
        VERY_HARD = 1 << 2, // 4 0x04 (0000 0100)
        SUPER_HARD = 1 << 3, // 8 0x08 (0000 1000)
        EX_HARD = 1 << 4,    // 16 0x10 (0001 0000)
        ULTRA_HARD = 1 << 5,  // 32 0x20 (0010 0000)
        Dummy2 = 1 << 6,  // 64 0x40 (0100 0000)
        Dummy3 = 1 << 7  // 128 0x80 (1000 0000)
    }

    public enum QuestPartyType : byte
    {
        SoloQuest,
        /// Only one party can join (up to 4 players).
        SinglePartyQuest,
        /// Multiple parties can join (up to 12 players).
        MultiPartyQuest,
    }

    [Flags]
    public enum QuestBitfield1 : ushort
    {
        MatterObjectiveQuest = 0x0001,
        ClientOrderOnQuest = 0x0008,
        NewQuest = 0x0100,
        ClientOrder = 0x0800,
        UnknownLevel = 0x1000
    }

    //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;
    }
}