import { world, system, ItemStack, Player, GameMode } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";

// Book item
world.afterEvents.itemStartUseOn.subscribe(async (e) => {
   if (!e.itemStack) return;
   // world.sendMessage(`used item type ${e.itemStack.typeId}`);
   await system.waitTicks(1);
   if (e.itemStack.typeId !== "oct_eg:guidebook") return;
   const bookEntity = e.block.dimension.getEntities({
      location: e.block.location,
      type: "oct_eg:guidebook",
      closest: 1,
   })[0];
   if (!bookEntity) return;

   // Set property
   const lastPageOpened = e.source.getDynamicProperty("oct_eg:guidebook_last_page_index") ?? 0;
   bookEntity.setProperty("oct_eg:pg_id", lastPageOpened);
});
world.afterEvents.playerInteractWithEntity.subscribe((e) => {
   if (e.target.typeId !== "oct_eg:guidebook") return;
   if (e.player.isSneaking) {
      showSettings(e.player, e.target);
      return;
   }
});

world.afterEvents.entityHitEntity.subscribe((e) => {
   if (!(e.damagingEntity instanceof Player) || !e.damagingEntity.isSneaking || e.hitEntity.typeId !== "oct_eg:guidebook")
      return;
   const guidebook = new ItemStack("oct_eg:guidebook", 1);
   let playerList = [];
   let interactedPlayer = null;
   e.hitEntity.dimension.getPlayers({ location: e.hitEntity.location, maxDistance: 10 }).forEach((player) => {
      if (
         player
            .getEntitiesFromViewDirection({ maxDistance: 10, type: "oct_eg:guidebook" })
            .find((val) => val.entity === e.hitEntity)
      )
         playerList.push(player);
   });

   if (playerList.length === 0) {
      e.hitEntity.dimension.spawnItem(guidebook, e.hitEntity.location);
      e.hitEntity.remove();
      return;
   }

   interactedPlayer = playerList[0];
   if (playerList.length > 1) {
      let closestDistance = 11;

      for (let x = 0; x < playerList.length; x++) {
         if (getDistance(playerList[x].location, e.hitEntity.location) < closestDistance) {
            interactedPlayer = playerList[x];
            closestDistance = getDistance(playerList[x].location, e.hitEntity.location);
         }
      }
   }

   const inven = interactedPlayer.getComponent("inventory").container;

   if (inven.emptySlotsCount === 0) {
      interactedPlayer.dimension.spawnItem(guidebook, interactedPlayer.location);
      e.hitEntity.remove();
      return;
   }

   interactedPlayer.playSound("random.pop", { volume: 0.5, pitch: 0.8 + 0.5 * Math.random() });
   inven.addItem(guidebook);

   // Set last page index to player dp
   interactedPlayer.setDynamicProperty("oct_eg:guidebook_last_page_index", e.hitEntity.getProperty("oct_eg:pg_id") - 1);

   // Remove entity
   e.hitEntity.remove();

   function getDistance(pos1, pos2) {
      return Math.sqrt((pos1.x - pos2.x) ** 2 + (pos1.y - pos2.y) ** 2 + (pos1.z - pos2.z) ** 2);
   }
});
world.afterEvents.playerJoin.subscribe((e) => {
   const interval = system.runInterval(() => {
      const player = world.getAllPlayers().find((val) => val.id === e.playerId);
      if (player?.isValid) {
         if (!player.getDynamicProperty("oct_eg:joined")) {
            player.setDynamicProperty("oct_eg:joined", true);
            if (player.getComponent("inventory").container.emptySlotsCount === 0) {
               player.dimension.spawnItem(new ItemStack("oct_eg:guidebook", 1), player.location);
            } else {
               player.getComponent("inventory").container.addItem(new ItemStack("oct_eg:guidebook", 1));
            }
         }
         system.clearRun(interval);
      }
   });
});

// Forms
const buttonIconPaths = {
   settings: "textures/octovon/eg/forms/button_icon_settings",
   exit: "textures/octovon/eg/forms/button_icon_exit",
   back: "textures/octovon/eg/forms/button_icon_back",
   changelog: "textures/octovon/eg/forms/button_icon_changelog",
   skip: "textures/octovon/eg/forms/button_icon_skip",
};
/** @param {Player} player
 * @param {Entity} bookEntity
 */
function showSettings(player, bookEntity) {
   const form = new ActionFormData();
   form.title({ rawtext: [{ translate: "forms.guidebook.title" }] });
   form.button({ rawtext: [{ translate: "forms.guidebook.button.select_page" }] }, buttonIconPaths.skip);
   form.button({ rawtext: [{ translate: "forms.guidebook.button.addon_settings" }] }, buttonIconPaths.settings);
   form.button({ rawtext: [{ translate: "forms.guidebook.button.changelog" }] }, buttonIconPaths.changelog);
   form.button({ rawtext: [{ translate: "forms.guidebook.button.close" }] }, buttonIconPaths.exit);
   form.show(player).then((response) => {
      if (response.canceled) return;

      switch (response.selection) {
         case 0:
            showSelectPage(player, bookEntity);
            break;
         case 1:
            showAddonSettings(player, bookEntity, player.getGameMode() == GameMode.creative);
            break;
         case 2:
            showChangelog(player, bookEntity);
            break;
         case 3:
            break;
      }
      return;
   });
}

/** @param {Player} player
 * @param {Entity} bookEntity
 */
function showAddonSettings(player, bookEntity, isCreative) {
   if (isCreative) {
      const form = new ModalFormData();
      const pvpDamageScalling = world.getDynamicProperty("oct_eg:pvpDamageScallingPercent");
      form.title({ rawtext: [{ translate: "forms.guidebook.settings.title" }] });
      form.slider(
         { rawtext: [{ translate: `forms.guidebook.settings.pvp_damage_scaling` }] },
         0,
         100,
         10,
         pvpDamageScalling
      );
      form.toggle({ rawtext: [{ translate: "forms.guidebook.settings.pvp_gamerule" }] }, world.gameRules.pvp.valueOf());
      form.submitButton({ rawtext: [{ translate: "forms.guidebook.settings.submit" }] });
      form.show(player).then((response) => {
         if (response.canceled) return;
         // PvP toggle
         world.gameRules.pvp = response.formValues[1];

         // Scaling
         const newScalingValue = response.formValues[0];
         world.setDynamicProperty("oct_eg:pvpDamageScallingPercent", newScalingValue);

         // Send message
         world.sendMessage({ rawtext: [{ translate: `forms.guidebook.settings_changed_message` }] });
         return;
      });
   } else {
      const form = new ActionFormData();
      const pvpDamageScalling = world.getDynamicProperty("oct_eg:pvpDamageScallingPercent");
      form.title({ rawtext: [{ translate: "forms.guidebook.settings.title" }] });
      form.body({
         rawtext: [
            { translate: "forms.guidebook.settings.body_creative" },
            { translate: "forms.guidebook.settings.pvp_damage_scaling" },
            { text: `: ${pvpDamageScalling}\%\n\n` },
            { translate: "forms.guidebook.settings.pvp_gamerule" },
            { text: `\n\n§lAllow PvP: ${world.gameRules.pvp}\n\n` },
         ],
      });
      form.button({ rawtext: [{ translate: "forms.guidebook.button.back" }] }, buttonIconPaths.back);
      form.button({ rawtext: [{ translate: "forms.guidebook.button.close" }] }, buttonIconPaths.exit);
      form.show(player).then((response) => {
         if (response.canceled) return;
         switch (response.selection) {
            case 0:
               showSettings(player, bookEntity);
               break;
            case 1:
               break;
         }
         return;
      });
   }
}

/** @param {Player} player
 * @param {Entity} bookEntity
 */
function showChangelog(player, bookEntity) {
   const form = new ActionFormData();
   form.title({ rawtext: [{ translate: "forms.guidebook.changelog.title" }] });
   form.body({ rawtext: [{ translate: "forms.guidebook.changelog.body" }] });
   form.button({ rawtext: [{ translate: "forms.guidebook.button.back" }] }, buttonIconPaths.back);
   form.button({ rawtext: [{ translate: "forms.guidebook.button.close" }] }, buttonIconPaths.exit);
   form.show(player).then((response) => {
      if (response.canceled) return;
      if (response.selection === 0) showSettings(player, bookEntity);
      return;
   });
}

/** @param {Player} player
 * @param {Entity} bookEntity
 */
function showSelectPage(player, bookEntity) {
   const form = new ActionFormData();
   form.title({ rawtext: [{ translate: "forms.guidebook.select_page.title" }] });
   form.button({ rawtext: [{ translate: "forms.guidebook.select_page.chapter" }] });
   form.button({ rawtext: [{ translate: "forms.guidebook.select_page.page" }] });
   form.button({ rawtext: [{ translate: "forms.guidebook.button.back" }] }, buttonIconPaths.back);
   form.button({ rawtext: [{ translate: "forms.guidebook.button.close" }] }, buttonIconPaths.exit);
   form.show(player).then((response) => {
      if (response.canceled) return;
      switch (response.selection) {
         case 0:
            showSelectPageChapter(player, bookEntity);
            break;
         case 1:
            showSelectPagePage(player, bookEntity);
            break;
         case 2:
            showSettings(player, bookEntity);
            break;
         case 3:
            break;
      }
      return;
   });
}

function showSelectPageChapter(player, bookEntity) {
   const form = new ModalFormData();
   form.title({ rawtext: [{ translate: "forms.guidebook.select_page.chapter.title" }] });

   // Chapters
   const chapters = [];
   const numChapters = 11;
   for (let i = 0; i < numChapters; i++) {
      chapters.push({ rawtext: [{ translate: `forms.guidebook.select_page.chapter.${i + 1}` }] });
   }
   form.dropdown({ rawtext: [{ translate: "forms.guidebook.select_page.chapter.dropdown_title" }] }, chapters, 0);
   form.show(player).then((response) => {
      if (response.canceled) return;
      // Set book chapter
      // These correspond a chapter to its first page
      const chapterPages = {
         0: 1, // Introduction
         1: 2, // Getting Started
         2: 4, // Pyro
         3: 7, // Hydro
         4: 10, // Geo
         5: 13, // Anemo
         6: 16, // Electro
         7: 19, // Necro
         8: 22, // Ender
         9: 25, // Other
         10: 26, // Closing
      };
      const pageId = chapterPages[response.formValues[0] ?? 1];
      //world.sendMessage(`Selected chapter: ${response.formValues[0]}, page: ${pageId}`);
      bookEntity.setProperty("oct_eg:pg_id", pageId - 1);
      return;
   });
}

function showSelectPagePage(player, bookEntity) {
   const form = new ModalFormData();
   form.title({ rawtext: [{ translate: "forms.guidebook.select_page.page.title" }] });
   form.slider({ rawtext: [{ translate: "forms.guidebook.select_page.page.page_number" }] }, 1, 52, 1, 1);
   form.submitButton({ rawtext: [{ translate: "forms.guidebook.select_page.page.submit" }] });
   form.show(player).then((response) => {
      if (response.canceled) return;
      // Set book page
      const pageId = Math.floor((response.formValues[0] - 1) / 2);
      bookEntity.setProperty("oct_eg:pg_id", pageId);
      return;
   });
}
