import { ItemStack, system } from "@minecraft/server";
import * as mc from "@minecraft/server";
import * as ui from "@minecraft/server-ui";

const GUIDEBOOK_ITEM = "pb_gat:book_main"; //id of your guidebook item
const GUIDEBOOK_TAG = "pb_gat_book"; //tag that gets applied to the player after first book drop
const SOUND_TURN_PAGE = "item.book.page_turn";
const SOUND_OPTIONS = { pitch: 1.0, volume: 5.0 };

export const MENUS = [
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /// MAIN MENU
  {
    menuID: "pb_gat:main",
    title: "§jGadgets & Trinkets Guidebook",
    body: "§rWelcome to §pGadgets & Trinkets§r Add-On!\n\nCheck out §pStarter Guide§r to get started.\n\nOr check out the §pContent§r section to learn more about Gadgets & Trinkets.\n\n",
    buttons: [
      {
        title: "§jStarter Guide",
        icon: "textures/pb/GaT/guide_icons/start",
        connectID: "pb_gat:starter",
      },
      {
        title: "§jAbout",
        icon: "textures/pb/GaT/guide_icons/about",
        connectID: "pb_gat:about",
      },
      {
        title: "§jExit",
        icon: "textures/pb/GaT/guide_icons/exit",
      },
    ],
    type: "form",
    openOnBlock: [],
    openOnEntity: [],
  },
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /// STARTER GUIDE
  {
    menuID: "pb_gat:starter",
    title: "§jStarter Guide",
    body: "§pGadgets & Trinkets§r adds over 100 different Gadgets and Trinkets, allowing for many new skills and abilities. \n\nThe Add-On is split into 2 distinct parts:\n-> §pGadgets§r, which are tools that can perform different tasks and can hold §pUpgrade Disks§r to allow them to perform differently.\n-> §pTrinkets§r are accessories that when stored in the §pTrinket Satchel§r will apply effects and buffs to the player.\n\nThe very first thing you will need to do is to craft a §pGAD Station§r, which will allow you to then craft items from this Add-On. Please check your Crafting Table for the recipe.\n\nSelect an option below to learn more about how to get started in that field:",
    buttons: [
      {
        title: "§jGadgets",
        icon: "textures/pb/GaT/guide_icons/gadgets",
        connectID: "pb_gat:starter_gadgets",
      },
      {
        title: "§jTrinkets",
        icon: "textures/pb/GaT/guide_icons/trinkets",
        connectID: "pb_gat:starter_trinkets",
      },
      {
        title: "§jReturn",
        icon: "textures/pb/GaT/guide_icons/return",
        connectID: "pb_gat:main",
      },
    ],
    type: "form",
    openOnBlock: [],
    openOnEntity: [],
  },
  // STARTER GUIDE - GADGETS
  {
    menuID: "pb_gat:starter_gadgets",
    title: "§jGetting Started With Gadgets",
    body: "To get started with Gadgets, you will need to craft a §pGadget Assembly Machine§r (G.A.T.). This is a §pMulti-Block§r structure, comprising 6 §pGadget Assembly Machine Blocks§r. These blocks can be crafted at the §pGAD Station§r and need to be placed in a 2 high, 6 wide configuration.\n\nWhen built correctly, you will see the structure form, which will now allow you to place materials inside to craft different gadgets.\n\nMost of the gadgets can hold upgrades inside, similarly to how Vanilla Bundles work. To create upgrades you will need to craft an §pUpgrade Puncher§r at the GAD Station. This will then allow you to insert materials to craft the upgrades.\n\nMore detailed information can be found in the §pGadgets Guide§r.",
    buttons: [
      {
        title: "§jRequest A Gadget Guide",
        icon: "textures/pb/GaT/items/books/gadgets",
        connectID: "pb_gat:give_guide_gadget",
      },
      {
        title: "§jReturn",
        icon: "textures/pb/GaT/guide_icons/return",
        connectID: "pb_gat:starter",
      },
    ],
    type: "form",
    openOnBlock: [],
    openOnEntity: [],
  },
  // GIVE GADGET GUIDE
  {
    menuID: "pb_gat:give_guide_gadget",
    title: "Gadget Guide Request",
    body: "You have been given a Gadget Guide, check at your feet if your inventory is full.\n\n",
    buttons: [
      {
        title: "§jReturn",
        icon: "textures/pb/GaT/guide_icons/return",
        connectID: "pb_gat:starter_gadgets",
      },
    ],
    type: "guide_button",
    guideID: "pb_gat:book_gadgets",
    openOnBlock: [],
    openOnEntity: [],
  },
  // STARTER GUIDE - TRINKETS
  {
    menuID: "pb_gat:starter_trinkets",
    title: "§jGetting Started With Trinkets",
    body: "To get started with trinkets, you will need to craft a §pTrinket Satchel§r at the §pGAD Station§r.\n\nThen, your first trinket will need to be crafted at the §pGAD Station§r, which will be the §pScout Scope§r. This trinket will allow for low-tier trinkets to drop from hostile mobs upon death.\n\nFor any trinket effect to be active, you need to have the trinket inside the trinket satchel. Only 1 trinket satchel will work at a time, checking your off-hand first, then your hotbar, and finally inside your inventory. If you have multiple trinket satchels in your inventory, only the first one found will be active.\n\nAs you collect trinkets from mobs, you can place them inside your trinket satchel to activate the trinkets effect.\n\nThe trinket satchel can only store 4 trinkets at a time, so you will need to prioritize which trinkets you want to have active for your situation.\n\nTrinkets can be stacked to increase their effects.\n\nAs you begin to collect more and more trinkets, you may want to craft yourself a §pTinker Table§r to allow you to merge compatible trinkets, allowing for more effects to be applied from a single trinket, saving room in your trinket satchel.\n\nMore detailed information can be found in the §pTrinkets Guide§r.",
    buttons: [
      {
        title: "§jRequest A Trinket Guide",
        icon: "textures/pb/GaT/items/books/trinkets",
        connectID: "pb_gat:give_guide_trinket",
      },
      {
        title: "§jReturn",
        icon: "textures/pb/GaT/guide_icons/return",
        connectID: "pb_gat:starter",
      },
    ],
    type: "form",
    openOnBlock: [],
    openOnEntity: [],
  },
  // GIVE TRINKET GUIDE
  {
    menuID: "pb_gat:give_guide_trinket",
    title: "Trinket Guide Request",
    body: "You have been given a Trinket Guide, check at your feet if your inventory is full.\n\n",
    buttons: [
      {
        title: "§jReturn",
        icon: "textures/pb/GaT/guide_icons/return",
        connectID: "pb_gat:starter_gadgets",
      },
    ],
    type: "guide_button",
    guideID: "pb_gat:book_trinkets",
    openOnBlock: [],
    openOnEntity: [],
  },
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /// ABOUT SECTION
  {
    menuID: "pb_gat:about",
    title: "§jAbout",
    body: "Version: §a1.0.0§r\n\n§pGadgets & Trinkets Add-On§r created by Pixelbiester.§r\n\nFollow us:\n§3Twitter§r §o@Pixelbiester\n§r§dInstagram§r §o@pixelbiesterofficial§r\n§cYoutube§r §oPixelBiester§r\n§eWebsite§r §opixelbiester.net§r\n§sDiscord§r §opixelbiester.net/discord§r\n\n",
    buttons: [
      {
        title: "§jReturn",
        icon: "textures/pb/GaT/guide_icons/return",
        connectID: "pb_gat:main",
      },
    ],
    type: "form",
    openOnBlock: [],
    openOnEntity: [],
  },
];

//FUNCTIONAL MENUS
function configMenu(player) {
  let form = new ui.ModalFormData();
  form.title("Config");
  form.slider("A Slider", 50, 100, 1, 100);
  form.slider("Another Slider", 0, 100, 1, 0);
  form.submitButton("§jReturn");

  form.show(player).then((result) => {
    if (result.canceled) return;
  });
}

guidebookModule();
interactionModule();

function openMenu(player, menuID) {
  player.playSound(SOUND_TURN_PAGE, SOUND_OPTIONS);

  const menu_data = MENUS.find((f) => f.menuID == menuID);
  if (menu_data == undefined) return;
  //exceptions for functional menus
  if (menu_data.type == "function") {
    if (menu_data.menuID == "pb_gat:config") configMenu(player); //register your functional menus here
    return;
  }

  if (menu_data.type == "guide_button") {
    const guideItemId = menu_data.guideID;
    const itemStack = new ItemStack(guideItemId, 1);

    // Spawn the item at the player's location
    player.dimension.spawnItem(itemStack, player.location);
  }
  //construct menu from array
  const menu = new ui.ActionFormData();
  menu.title(menu_data.title);
  menu.body(menu_data.body);
  menu_data.buttons.forEach((button) => {
    menu.button(button.title, button.icon);
  });

  menu.show(player).then((result) => {
    if (result.canceled) return;

    let response = result.selection;
    openMenu(player, menu_data.buttons[response].connectID);
  });
}

//basic guidebook dropping and opening functionality
function guidebookModule() {
  //drop guidebook on player first spawn only
  mc.world.afterEvents.playerSpawn.subscribe((eventData) => {
    if (eventData.player.hasTag(GUIDEBOOK_TAG)) {
    } else {
      mc.world
        .getDimension(eventData.player.dimension.id)
        .spawnItem(
          new mc.ItemStack(GUIDEBOOK_ITEM, 1),
          eventData.player.location
        );
      eventData.player.addTag(GUIDEBOOK_TAG);
      system.runTimeout(() => {
        eventData.player.sendMessage(
          `§p->§r Thank you for downloading §pGadgets & Trinkets§r! A guidebook has been added to help you get started. If your inventory is full, it will appear at your feet.`
        );
        eventData.player.playSound("random.levelup", {
          pitch: 0.9,
          volume: 0.6,
          location: eventData.player.location,
        });
      }, 60);
    }
  });

  //guidebook entity check
  mc.world.beforeEvents.playerInteractWithEntity.subscribe((eventData) => {
    const player = eventData.player;
    const item = eventData.itemStack;
    const entity = eventData.target;
    if (item == undefined) return;
    if (item.type.id != GUIDEBOOK_ITEM) return;

    let menu;
    MENUS.forEach((menudata) => {
      if (menudata.openOnEntity.includes(entity.typeId)) menu = menudata;
    });

    if (menu == undefined) return;
    eventData.cancel = true;
    mc.system.runTimeout(() => {
      openMenu(player, menu.menuID);
    }, 0);
  });
}

//activate this for block and entity interactions checks
function interactionModule() {
  //guidebook block check
  mc.world.beforeEvents.playerInteractWithBlock.subscribe((eventData) => {
    const player = eventData.player;
    const item = eventData.itemStack;
    const block = eventData.block;
    if (item == undefined) return;
    if (item.type.id != GUIDEBOOK_ITEM) return;

    let menu;
    MENUS.forEach((menudata) => {
      if (menudata.openOnBlock.includes(block.typeId)) menu = menudata;
    });

    if (menu == undefined) return;
    eventData.cancel = true;
    mc.system.runTimeout(() => {
      openMenu(player, menu.menuID);
    }, 0);
  });

  //guidebook activation listener
  mc.world.afterEvents.itemUse.subscribe((eventData) => {
    let player = eventData.source;
    let itemUse = eventData.itemStack;
    if (itemUse === undefined) return;
    if (itemUse.typeId == GUIDEBOOK_ITEM)
      mc.system.runTimeout(() => {
        openMenu(player, "pb_gat:main");
      }, 1);
  });
}
