context: using System.Diagnostics.CodeAnalysis;
  using WowPacketParser.Enums;
  using WowPacketParser.Loading;
  using WowPacketParser.Misc;
  using WowPacketParser.Parsing;
  using WowPacketParser.Store;
  using WowPacketParser.Store.Objects;
  
  namespace WowPacketParserModule.V6_0_2_19033.Parsers
  {
      [SuppressMessage("ReSharper", "UseObjectOrCollectionInitializer")]
      public static class QuestHandler
      {
          private static void ReadQuestRewards(Packet packet)
          {
              packet.ReadInt32("ChoiceItemCount");
  
              for (var i = 0; i < 6; ++i)
              {
                  packet.ReadInt32("ItemID", i);
                  packet.ReadInt32("Quantity", i);
              }
  
              packet.ReadInt32("ItemCount");
  
              for (var i = 0; i < 4; ++i)
              {
                  packet.ReadInt32("ItemID", i);
                  packet.ReadInt32("ItemQty", i);
              }
  
              packet.ReadInt32("Money");
              packet.ReadInt32("Xp");
              packet.ReadInt32("Title");
              packet.ReadInt32("Talents");
              packet.ReadInt32("FactionFlags");
  
              for (var i = 0; i < 5; ++i)
              {
                  packet.ReadInt32("FactionID", i);
                  packet.ReadInt32("FactionValue", i);
                  packet.ReadInt32("FactionOverride", i);
              }
  
              packet.ReadInt32("SpellCompletionDisplayID");
              packet.ReadInt32("SpellCompletionID");
  
              for (var i = 0; i < 4; ++i)
              {
                  packet.ReadInt32("CurrencyID", i);
                  packet.ReadInt32("CurrencyQty", i);
              }
  
              packet.ReadInt32("SkillLineID");
              packet.ReadInt32("FactiNumSkillUpsonFlags");
  
              packet.ResetBitReader();
  
              packet.ReadBit("bit44");
          }
  
          public static void ReadGossipText(Packet packet, params object[] indexes)
          {
              packet.ReadUInt32("QuestID", indexes);
              packet.ReadUInt32("QuestType", indexes);
              packet.ReadUInt32("QuestLevel", indexes);
  
              for (int i = 0; i < 2; i++)
                  packet.ReadUInt32("QuestFlags", indexes, i);
  
              packet.ResetBitReader();
  
              packet.ReadBit("Repeatable", indexes);
  
              var bits13 = packet.ReadBits(9);
              packet.ReadWoWString("QuestTitle", bits13, indexes);
          }
  
          [Parser(Opcode.CMSG_QUERY_QUEST_INFO)]
          public static void HandleQuestQuery(Packet packet)
          {
              packet.ReadInt32("Entry");
              packet.ReadPackedGuid128("Guid");
          }
  
          [Parser(Opcode.CMSG_QUEST_GIVER_QUERY_QUEST)]
          public static void HandleQuestGiverQueryQuest(Packet packet)
          {
              packet.ReadPackedGuid128("QuestGiverGUID");
              packet.ReadUInt32("QuestID");
              packet.ReadBit("RespondToGiver");
          }
  
          [Parser(Opcode.CMSG_QUEST_GIVER_COMPLETE_QUEST)]
          public static void HandleQuestGiverCompleteQuest(Packet packet)
          {
              packet.ReadPackedGuid128("QuestGiverGUID");
              packet.ReadUInt32("QuestID");
              packet.ReadBit("FromScript");
          }
  
          [Parser(Opcode.CMSG_QUEST_GIVER_CHOOSE_REWARD)]
          public static void HandleQuestChooseReward(Packet packet)
          {
              packet.ReadPackedGuid128("QuestGiverGUID");
              packet.ReadInt32("QuestID");
              packet.ReadInt32("ItemChoiceID");
          }
  
          [Parser(Opcode.CMSG_QUEST_GIVER_ACCEPT_QUEST)]
          public static void HandleQuestgiverAcceptQuest(Packet packet)
          {
              packet.ReadPackedGuid128("QuestGiverGUID");
              packet.ReadUInt32<QuestId>("QuestID");
              packet.ReadBit("StartCheat");
          }
  
          [Parser(Opcode.CMSG_QUEST_GIVER_REQUEST_REWARD)]
          public static void HandleQuestRequestReward(Packet packet)
          {
              packet.ReadPackedGuid128("QuestGiverGUID");
              packet.ReadUInt32<QuestId>("QuestID");
          }
  
          [Parser(Opcode.CMSG_QUEST_POI_QUERY)]
          public static void HandleQuestPOIQuery(Packet packet)
          {
              packet.ReadUInt32("MissingQuestCount");
  
              for (var i = 0; i < 50; i++)
                  packet.ReadInt32<QuestId>("MissingQuestPOIs", i);
          }
  
          [Parser(Opcode.SMSG_QUEST_POI_QUERY_RESPONSE)]
          public static void HandleQuestPoiQueryResponse(Packet packet)
          {
              packet.ReadInt32("NumPOIs");
              int int4 = packet.ReadInt32("QuestPOIData");
  
              for (int i = 0; i < int4; ++i)
              {
                  int questId = packet.ReadInt32("QuestID", i);
  
                  if (ClientVersion.RemovedInVersion(ClientVersionBuild.V6_2_0_20173))
                      packet.ReadUInt32("NumBlobs", i);
  
                  int int2 = packet.ReadInt32("QuestPOIBlobData", i);
  
                  for (int j = 0; j < int2; ++j)
                  {
                      QuestPOI questPoi = new QuestPOI
                      {
                          QuestID = questId,
                          ID = j,
                          BlobIndex = packet.ReadInt32("BlobIndex", i, j),
                          ObjectiveIndex = packet.ReadInt32("ObjectiveIndex", i, j),
                          QuestObjectiveID = packet.ReadInt32("QuestObjectiveID", i, j),
                          QuestObjectID = packet.ReadInt32("QuestObjectID", i, j),
                          MapID = packet.ReadInt32("MapID", i, j),
                          WorldMapAreaId = packet.ReadInt32("WorldMapAreaID", i, j),
                          Floor = packet.ReadInt32("Floor", i, j),
                          Priority = packet.ReadInt32("Priority", i, j),
                          Flags = packet.ReadInt32("Flags", i, j),
                          WorldEffectID = packet.ReadInt32("WorldEffectID", i, j),
                          PlayerConditionID = packet.ReadInt32("PlayerConditionID", i, j)
                      };
  
                      if (ClientVersion.RemovedInVersion(ClientVersionBuild.V6_2_0_20173))
                          packet.ReadInt32("NumPoints", i, j);
  
                      questPoi.WoDUnk1 = packet.ReadInt32("WoDUnk1", i, j);
  
                      int int13 = packet.ReadInt32("QuestPOIBlobPoint", i, j);
                      for (int k = 0; k < int13; ++k)
                      {
                          QuestPOIPoint questPoiPoint = new QuestPOIPoint
                          {
                              QuestID = questId,
                              Idx1 = j,
                              Idx2 = k,
                              X = packet.ReadInt32("X", i, j, k),
                              Y = packet.ReadInt32("Y", i, j, k)
                          };
                          Storage.QuestPOIPoints.Add(questPoiPoint, packet.TimeSpan);
                      }
  
                      Storage.QuestPOIs.Add(questPoi, packet.TimeSpan);
                  }
              }
          }
  
          [HasSniffData]
          [Parser(Opcode.SMSG_QUERY_QUEST_INFO_RESPONSE)]
          public static void HandleQuestQueryResponse(Packet packet)
          {
              packet.ReadInt32("Entry");
  
              Bit hasData = packet.ReadBit("Has Data");
              if (!hasData)
                  return; // nothing to do
  
              var id = packet.ReadEntry("Quest ID");
  
              QuestTemplate quest = new QuestTemplate
              {
                  ID = (uint)id.Key
              };
  
              quest.QuestType = packet.ReadInt32E<QuestType>("QuestType");
              quest.QuestLevel = packet.ReadInt32("QuestLevel");
              quest.QuestPackageID = packet.ReadUInt32("QuestPackageID");
              quest.MinLevel = packet.ReadInt32("QuestMinLevel");
              quest.QuestSortID = (QuestSort)packet.ReadUInt32("QuestSortID");
              quest.QuestInfoID = packet.ReadInt32E<QuestInfo>("QuestInfoID");
              quest.SuggestedGroupNum = packet.ReadUInt32("SuggestedGroupNum");
              quest.RewardNextQuest = packet.ReadUInt32("RewardNextQuest");
              quest.RewardXPDifficulty = packet.ReadUInt32("RewardXPDifficulty");
  
              quest.RewardXPMultiplier = packet.ReadSingle("RewardXPMultiplier");
  
              quest.RewardMoney = packet.ReadInt32("RewardMoney");
              quest.RewardMoneyDifficulty = packet.ReadUInt32("RewardMoneyDifficulty");
  
              quest.RewardMoneyMultiplier = packet.ReadSingle("RewardMoneyMultiplier");
  
              quest.RewardBonusMoney = packet.ReadUInt32("RewardBonusMoney");
              quest.RewardDisplaySpell = packet.ReadUInt32("RewardDisplaySpell");
              quest.RewardSpellWod = packet.ReadUInt32("RewardSpell");
              quest.RewardHonorWod = packet.ReadUInt32("RewardHonor");
  
              quest.RewardKillHonor = packet.ReadSingle("RewardKillHonor");
  
              quest.StartItem = packet.ReadUInt32("StartItem");
              quest.Flags = packet.ReadUInt32E<QuestFlags>("Flags");
              quest.FlagsEx = packet.ReadUInt32E<QuestFlags2>("FlagsEx");
  
              quest.RewardItem = new uint?[4];
              quest.RewardAmount = new uint?[4];
              quest.ItemDrop = new uint?[4];
              quest.ItemDropQuantity = new uint?[4];
              for (int i = 0; i < 4; ++i)
              {
                  quest.RewardItem[i] = packet.ReadUInt32("RewardItems", i);
                  quest.RewardAmount[i] = packet.ReadUInt32("RewardAmount", i);
                  quest.ItemDrop[i] = packet.ReadUInt32("ItemDrop", i);
                  quest.ItemDropQuantity[i] = packet.ReadUInt32("ItemDropQuantity", i);
              }
  
              quest.RewardChoiceItemID = new uint?[6];
              quest.RewardChoiceItemQuantity = new uint?[6];
              quest.RewardChoiceItemDisplayID = new uint?[6];
              for (int i = 0; i < 6; ++i) // CliQuestInfoChoiceItem
              {
                  quest.RewardChoiceItemID[i] = packet.ReadUInt32("RewardChoiceItemID", i);
                  quest.RewardChoiceItemQuantity[i] = packet.ReadUInt32("RewardChoiceItemQuantity", i);
                  quest.RewardChoiceItemDisplayID[i] = packet.ReadUInt32("RewardChoiceItemDisplayID", i);
              }
  
              quest.POIContinent = packet.ReadUInt32("POIContinent");
  
              quest.POIx = packet.ReadSingle("POIx");
              quest.POIy = packet.ReadSingle("POIy");
  
              quest.POIPriorityWod = packet.ReadInt32("POIPriority");
              quest.RewardTitle = packet.ReadUInt32("RewardTitle");
              quest.RewardTalents = packet.ReadUInt32("RewardTalents");
              quest.RewardArenaPoints = packet.ReadUInt32("RewardArenaPoints");
              quest.RewardSkillLineID = packet.ReadUInt32("RewardSkillLineID");
              quest.RewardNumSkillUps = packet.ReadUInt32("RewardNumSkillUps");
              quest.QuestGiverPortrait = packet.ReadUInt32("PortraitGiver");
              quest.QuestTurnInPortrait = packet.ReadUInt32("PortraitTurnIn");
  
              quest.RewardFactionID = new uint?[5];
              quest.RewardFactionValue = new int?[5];
              quest.RewardFactionOverride = new int?[5];
              for (int i = 0; i < 5; ++i)
              {
                  quest.RewardFactionID[i] = packet.ReadUInt32("RewardFactionID", i);
                  quest.RewardFactionValue[i] = packet.ReadInt32("RewardFactionValue", i);
                  quest.RewardFactionOverride[i] = packet.ReadInt32("RewardFactionOverride", i);
              }
  
              quest.RewardFactionFlags = packet.ReadUInt32("RewardFactionFlags");
  
              quest.RewardCurrencyID = new uint?[4];
              quest.RewardCurrencyCount = new uint?[4];
              for (int i = 0; i < 4; ++i)
              {
                  quest.RewardCurrencyID[i] = packet.ReadUInt32("RewardCurrencyID");
                  quest.RewardCurrencyCount[i] = packet.ReadUInt32("RewardCurrencyQty");
              }
  
              quest.SoundAccept = packet.ReadUInt32("AcceptedSoundKitID");
              quest.SoundTurnIn = packet.ReadUInt32("CompleteSoundKitID");
              quest.AreaGroupID = packet.ReadUInt32("AreaGroupID");
              quest.TimeAllowed = packet.ReadUInt32("TimeAllowed");
              uint int2946 = packet.ReadUInt32("CliQuestInfoObjective");
              quest.AllowableRacesWod = packet.ReadInt32("AllowableRaces");
  
              for (int i = 0; i < int2946; ++i)
              {
                  var objectiveId = packet.ReadEntry("Id", i);
  
                  QuestObjective questInfoObjective = new QuestObjective
                  {
                      ID = (uint)objectiveId.Key,
                      QuestID = (uint)id.Key
                  };
                  questInfoObjective.Type = packet.ReadByteE<QuestRequirementType>("Quest Requirement Type", i);
                  questInfoObjective.StorageIndex = packet.ReadSByte("StorageIndex", i);
                  questInfoObjective.ObjectID = packet.ReadInt32("ObjectID", i);
                  questInfoObjective.Amount = packet.ReadInt32("Amount", i);
                  questInfoObjective.Flags = packet.ReadUInt32("Flags", i);
                  questInfoObjective.UnkFloat = packet.ReadSingle("Float5", i);
  
                  int int280 = packet.ReadInt32("VisualEffects", i);
                  for (int j = 0; j < int280; ++j)
                  {
                      QuestVisualEffect questVisualEffect = new QuestVisualEffect
                      {
                          ID = questInfoObjective.ID,
                          Index = (uint) j,
                          VisualEffect = packet.ReadInt32("VisualEffectId", i, j)
                      };
  
                      Storage.QuestVisualEffects.Add(questVisualEffect, packet.TimeSpan);
                  }
  
                  packet.ResetBitReader();
  
                  uint bits6 = packet.ReadBits(8);
                  questInfoObjective.Description = packet.ReadWoWString("Description", bits6, i);
  
                  if (BinaryPacketReader.GetLocale() != LocaleConstant.enUS && questInfoObjective.Description != string.Empty)
                  {
                      QuestObjectivesLocale localesQuestObjectives = new QuestObjectivesLocale
                      {
                          ID = (uint)objectiveId.Key,
                          QuestId = (uint)id.Key,
                          StorageIndex = questInfoObjective.StorageIndex,
                          Description = questInfoObjective.Description
                      };
  
                      Storage.LocalesQuestObjectives.Add(localesQuestObjectives, packet.TimeSpan);
                  }
  
                  Storage.QuestObjectives.Add(questInfoObjective, packet.TimeSpan);
              }
  
              packet.ResetBitReader();
  
              uint bits26 = packet.ReadBits(9);
              uint bits154 = packet.ReadBits(12);
              uint bits904 = packet.ReadBits(12);
              uint bits1654 = packet.ReadBits(9);
              uint bits1789 = packet.ReadBits(10);
              uint bits2045 = packet.ReadBits(8);
              uint bits2109 = packet.ReadBits(10);
              uint bits2365 = packet.ReadBits(8);
              uint bits2429 = packet.ReadBits(11);
  
              quest.LogTitle = packet.ReadWoWString("LogTitle", bits26);
              quest.LogDescription = packet.ReadWoWString("LogDescription", bits154);
              quest.QuestDescription = packet.ReadWoWString("QuestDescription", bits904);
              quest.AreaDescription = packet.ReadWoWString("AreaDescription", bits1654);
              quest.QuestGiverTextWindow = packet.ReadWoWString("PortraitGiverText", bits1789);
              quest.QuestGiverTargetName = packet.ReadWoWString("PortraitGiverName", bits2045);
              quest.QuestTurnTextWindow = packet.ReadWoWString("PortraitTurnInText", bits2109);
              quest.QuestTurnTargetName = packet.ReadWoWString("PortraitTurnInName", bits2365);
              quest.QuestCompletionLog = packet.ReadWoWString("QuestCompletionLog", bits2429);
  
              if (BinaryPacketReader.GetLocale() != LocaleConstant.enUS)
              {
                  LocalesQuest localesQuest = new LocalesQuest
                  {
                      ID = (uint)id.Key,
                      Locale = BinaryPacketReader.GetClientLocale(),
                      LogTitle            = quest.LogTitle,
                      LogDescription      = quest.LogDescription,
                      QuestDescription    = quest.QuestDescription,
                      AreaDescription     = quest.AreaDescription,
                      PortraitGiverText   = quest.QuestGiverTextWindow,
                      PortraitGiverName   = quest.QuestGiverTargetName,
                      PortraitTurnInText  = quest.QuestTurnTextWindow,
                      PortraitTurnInName  = quest.QuestTurnTargetName,
                      QuestCompletionLog  = quest.QuestCompletionLog
                  };
  
                  Storage.LocalesQuests.Add(localesQuest, packet.TimeSpan);
              }
  
              Storage.QuestTemplates.Add(quest, packet.TimeSpan);
          }
  
          [Parser(Opcode.CMSG_QUERY_QUEST_COMPLETION_NPCS)]
          public static void HandleQueryQuestCompletionNpcs(Packet packet)
          {
              var count = packet.ReadUInt32("Count");
  
              for (var i = 0; i < count; i++)
                  packet.ReadInt32<QuestId>("QuestID", i);
          }
  
          [Parser(Opcode.SMSG_QUEST_GIVER_QUEST_DETAILS)]
          public static void HandleQuestgiverDetails(Packet packet)
          {
              packet.ReadPackedGuid128("QuestGiverGUID");
              packet.ReadPackedGuid128("InformUnit");
  
              int id = packet.ReadInt32("QuestID");
              QuestDetails questDetails = new QuestDetails
              {
  
gt:                 ID = (uint)id