import {
  world,
  system,
  ItemStack,
  Camera,
  EasingType,
  ItemLockMode,
  BlockVolume,
} from "@minecraft/server";
import {
  ModalFormData,
  ActionFormData,
  MessageFormData,
} from "@minecraft/server-ui";
import { utilities } from "./utils";
import openDoorFunction from "./Door/openDoorFunction";

let advertise = new MessageFormData()
  .title("System")
  .body("Are you sure you want to do that?")
  .button1("No")
  .button2("Yes");
let keycode = new ModalFormData()
  .title("Keypad")
  .textField("Enter your keycode ", "Key Code");
let keypadChoose = new ModalFormData()
  .title("Keypad")
  .textField("Enter your new keycode ", "Ex: test123");
let scbName = new ModalFormData()
  .title("Name")
  .textField("Choose a name ", "Ex: test123");
let turretModule = new ActionFormData()
  .title("Turret Module")
  .button("Turret §aOn", "assets/ui/turret_on")
  .button("Turret §cOff", "assets/ui/turret_off")
  .button("Only §9Monsters", "assets/ui/only_monsters")
  .button("Only §1Players", "assets/ui/only_players")
  .button("All", "assets/ui/all")
  .button("Remove All", "assets/ui/remove_all");
let turretSetting = new ActionFormData()
  .title("Turret Settings")
  .button("Turret §aOn", "assets/ui/turret_on")
  .button("Turret §cOff", "assets/ui/turret_off")
  .button("Only §9Monsters", "assets/ui/only_monsters")
  .button("Only §1Players", "assets/ui/only_players")
  .button("All", "assets/ui/all")
  .button("Remove", "assets/ui/remove");
let tablet = new ActionFormData()
  .title("Tablet")
  .button("Camera", "assets/ui/go_to_camera")
  .button("Drone", "assets/ui/go_to_camera")
  .button("Remove", "assets/ui/remove")
  .button("Remove All Cameras", "assets/ui/remove_all");
let tabletOn = new ActionFormData()
  .title("Tablet")
  .button("Camera", "assets/ui/go_to_camera")
  .button("Drone", "assets/ui/go_to_camera")
  .button("Return", "assets/ui/return");
let mineModule = new ActionFormData()
  .title("Mine Module")
  .button("Explode", "assets/ui/explode")
  .button("Explode All", "assets/ui/explode_all")
  .button("Remove", "assets/ui/remove")
  .button("Remove All", "assets/ui/remove_all");
const modules = ["scb:turret_module", "scb:remote_access_mine", "scb:tablet"];

const loots = [
  new ItemStack("scb:turret_item", 1),
  new ItemStack("scb:mine_inactive", 1),
  new ItemStack("scb:security_camera", 1),
];

//Modulos
const initPosMap = new Map();

world.afterEvents.itemUse.subscribe((scb) => {
  const { itemStack: item, source: player } = scb;
  const turretsArray = world
    .getDimension("overworld")
    .getEntities()
    .filter(
      (entity) =>
        entity?.hasTag(`owner:${player.name}`) && entity?.typeId == "scb:turret"
    );
  const minesArray = world
    .getDimension("overworld")
    .getEntities()
    .filter(
      (entity) =>
        entity?.hasTag(`owner:${player.name}`) &&
        entity?.typeId == "scb:mine_entity"
    );
  const camerasArray = world
    .getDimension("overworld")
    .getEntities()
    .filter(
      (entity) =>
        entity?.hasTag(`owner:${player.name}`) &&
        entity?.typeId == "scb:camera_entity"
    );
  const dronesArray = world
    .getDimension("overworld")
    .getEntities()
    .filter(
      (entity) =>
        entity?.hasTag(`owner:${player.name}`) && entity?.typeId == "scb:drone"
    );

  /*Turret*/
  if (item?.typeId == modules[0]) {
    turretModule.show(player).then((scb) => {
      const { selection: slc } = scb;
      if (scb.canceled) return;
      for (const turret of turretsArray) {
        if (slc == 0) {
          turret.triggerEvent("scb:on");
        }
        if (slc == 1) {
          turret.triggerEvent("scb:off");
        }
        if (slc == 2) {
          turret.triggerEvent("scb:only_monsters");
        }
        if (slc == 3) {
          turret.triggerEvent("scb:only_players");
        }
        if (slc == 4) {
          turret.triggerEvent("scb:attack_all");
        }
      }
      if (slc == 5) {
        advertise.show(player).then((scb) => {
          if (scb.selection == 1) {
            if (scb.canceled) return;
            for (let i = 0; i < turretsArray.length; i++) {
              turretsArray[i].triggerEvent("scb:remove");
              turretsArray[i].dimension.spawnItem(
                loots[0],
                turretsArray[i].location
              );
            }
          }
        });
      }
    });
  }

  /*Mines*/
  if (item?.typeId == modules[1]) {
    mineModule.show(player).then((scb) => {
      const { selection: slc } = scb;
      if (scb.canceled) return;
      const mineList = utilities
        .getEntities(player.dimension, player.name, "scb:mine_entity")
        .map((entity) => utilities.getName(entity, player.name));
      if (slc == 0) {
        let choose = new ModalFormData()
          .dropdown("Select", mineList)
          .show(player)
          .then((scb) => {
            if (scb.canceled) return;
            for (const mine of minesArray) {
              if (mine?.hasTag(`mine:${mineList[scb.formValues]}`)) {
                mine.dimension.createExplosion(mine.location, 4, {
                  allowUnderwater: false,
                  causesFire: true,
                  breaksBlocks: true,
                });
                mine.triggerEvent("scb:despawn");
              }
            }
          });
      }
      if (slc == 1) {
        advertise.show(player).then((scb) => {
          if (scb.selection == 1) {
            if (scb.canceled) return;
            for (const mine of minesArray) {
              mine.dimension.createExplosion(mine.location, 4, {
                allowUnderwater: false,
                causesFire: true,
                breaksBlocks: true,
              });
              mine.triggerEvent("scb:despawn");
            }
          }
        });
      }
      if (slc == 2) {
        let choose = new ModalFormData()
          .dropdown("Select", mineList)
          .show(player)
          .then((scb) => {
            if (scb.canceled) return;
            for (const mine of minesArray) {
              if (mine?.hasTag(`mine:${mineList[scb.formValues]}`)) {
                try {
                  mine.dimension.setBlockType(mine.location, "minecraft:air");
                  player.dimension.spawnItem(loots[1], mine.location);
                  mine.triggerEvent("scb:despawn");
                } catch (e) {
                  console.warn(e.stack);
                }
              }
            }
          });
      }
      if (slc == 3) {
        advertise.show(player).then((scb) => {
          if (scb.selection == 1) {
            if (scb.canceled) return;
            for (const mine of minesArray) {
              mine.dimension.setBlockType(mine.location, "minecraft:air");
              player.dimension.spawnItem(loots[1], mine.location);
              mine.triggerEvent("scb:despawn");
            }
          }
        });
      }
    });
  }

  /*Cameras*/
  if (item?.typeId == modules[2]) {
    const inv = player.getComponent("inventory").container;
    const cameraList = utilities
      .getEntities(player.dimension, player.name, "scb:camera_entity")
      .map((entity) => utilities.getName(entity, player.name));
    const droneList = utilities
      .getEntities(player.dimension, player.name, "scb:drone")
      .map((entity) => utilities.getName(entity, player.name));
    if (!player?.hasTag("in_camera")) {
      tablet.show(player).then((scb) => {
        if (scb.canceled) return;
        const { selection: slc } = scb;
        //choose a camera
        if (slc == 0) {
          let choose = new ModalFormData()
            .dropdown("Select", cameraList)
            .show(player)
            .then((scb) => {
              if (scb.canceled) return;
              for (const camera of camerasArray) {
                if (camera?.hasTag(`camera:${cameraList[scb.formValues]}`)) {
                  const coordinates = camera.location;
                  const blockTablet = new ItemStack(modules[2], 1);
                  blockTablet.lockMode = ItemLockMode.slot;
                  blockTablet.lockMode = ItemLockMode.inventory;
                  blockTablet.keepOnDeath = true;
                  inv.setItem(player.selectedSlotIndex, blockTablet);
                  player.addTag("in_camera");
                  const runInt = system.runInterval(async () => {
                    if (player?.hasTag("in_camera")) {
                      await player.runCommandAsync(
                        `inputpermission set @s movement disabled`
                      );
                      const cameraRotation = player.getRotation();
                      player.camera.setCamera("minecraft:free", {
                        easeOptions: {
                          easeType: EasingType.Linear,
                          easeTime: 0.05,
                        },
                        location: {
                          x: coordinates.x,
                          y: coordinates.y + 1,
                          z: coordinates.z,
                        },
                        rotation: {
                          x: 0,
                          y: cameraRotation.y,
                        },
                      });
                    } else {
                      system.clearRun(runInt);
                      player.camera.clear();
                    }
                  });
                }
              }
            });
        }
        //choose a drone
        if (slc == 1) {
          let choose = new ModalFormData()
            .dropdown("Select", droneList)
            .show(player)
            .then((scb) => {
              if (scb.canceled) return;
              initPosMap.set(player, player.location);
              for (const drone of dronesArray) {
                if (drone?.hasTag(`drone:${droneList[scb.formValues]}`)) {
                  const blockTablet = new ItemStack(modules[2], 1);
                  blockTablet.lockMode = ItemLockMode.slot;
                  blockTablet.lockMode = ItemLockMode.inventory;
                  blockTablet.keepOnDeath = true;
                  inv.setItem(player.selectedSlotIndex, blockTablet);
                  player.addTag("in_camera");
                  player.sendMessage(
                    `§aFly: Look up\n§cStatic: Sneak\n§bDescend: Look down`
                  );
                  const runInt = system.runInterval(async () => {
                    if (drone?.hasTag(`drone:${droneList[scb.formValues]}`)) {
                      if (player?.hasTag("in_camera")) {
                        const coordinates = drone.location;
                        const cameraRotation = player.getRotation();
                        const plrV = player.getVelocity();
                        drone.addEffect("slow_falling", 20000000, {
                          showParticles: false,
                          amplifier: 0,
                        });
                        if (!player.isSneaking && cameraRotation.x < -30) {
                          drone.addEffect("levitation", 5, {
                            showParticles: false,
                            amplifier: 4,
                          });
                          player.onScreenDisplay.setActionBar("§aFlying");
                        } else if (
                          !player.isSneaking &&
                          cameraRotation.x > -30
                        ) {
                          player.onScreenDisplay.setActionBar("§bDecending");
                        } else if (player.isSneaking) {
                          drone.teleport(drone.location);
                          player.onScreenDisplay.setActionBar("§cStatic");
                        }
                        if (!plrV.x == 0 || !plrV.z == 0) {
                          player.teleport(initPosMap.get(player));
                        }
                        drone.applyImpulse({
                          x: plrV.x / 0.8,
                          y: 0,
                          z: plrV.z / 0.8,
                        });
                        await player.runCommandAsync(
                          `camera @s set minecraft:free ease 0.05 linear pos ${
                            coordinates.x
                          } ${coordinates.y + 1} ${coordinates.z} rot 0 ${
                            cameraRotation.y
                          }`
                        );
                        drone.setRotation(cameraRotation);
                      } else {
                        system.clearRun(runInt);
                        system.run(async () => {
                          player.camera.clear();
                          await player.runCommandAsync(
                            `inputpermission set @s movement enabled`
                          );
                        });
                      }
                    }
                  });
                }
              }
            });
        }
        if (slc == 2) {
          let choose = new ModalFormData()
            .dropdown("Select", cameraList)
            .show(player)
            .then((scb) => {
              if (scb.canceled) return;
              for (const camera of camerasArray) {
                if (camera?.hasTag(`camera:${cameraList[scb.formValues]}`)) {
                  try {
                    camera.dimension.setBlockType(
                      camera.location,
                      "minecraft:air"
                    );
                    player.dimension.spawnItem(loots[2], camera.location);
                    camera.triggerEvent("scb:despawn");
                  } catch (e) {
                    console.warn(e.stack);
                  }
                }
              }
            });
        }
        if (slc == 3) {
          advertise.show(player).then((scb) => {
            if (scb.canceled) return;
            if (scb.selection == 1) {
              for (const camera of camerasArray) {
                camera.dimension.setBlockType(camera.location, "minecraft:air");
                player.dimension.spawnItem(loots[2], camera.location);
                camera.triggerEvent("scb:despawn");
              }
            }
          });
        }
      });
    } else {
      tabletOn.show(player).then(async (scb) => {
        if (scb.canceled) return;
        player.removeTag("in_camera");
        await player.runCommandAsync(`inputpermission set @s movement enabled`);
        inv.setItem(player.selectedSlotIndex, new ItemStack(modules[2]));
        const { selection: slc } = scb;
        if (slc == 0) {
          let choose = new ModalFormData()
            .dropdown("Select", cameraList)
            .show(player)
            .then((scb) => {
              if (scb.canceled) return;
              for (const camera of camerasArray) {
                if (camera?.hasTag(`camera:${cameraList[scb.formValues]}`)) {
                  const coordinates = camera.location;
                  player.addTag("in_camera");
                  const runInt = system.runInterval(async () => {
                    if (
                      player?.hasTag("in_camera") &&
                      !player?.hasTag("cameraStop")
                    ) {
                      await player.runCommandAsync(
                        `inputpermission set @s movement disabled`
                      );
                      const cameraRotation = player.getRotation();
                      await player.runCommandAsync(
                        `camera @s set minecraft:free ease 0 linear pos ${
                          coordinates.x
                        } ${coordinates.y + 1} ${coordinates.z} rot 0 ${
                          cameraRotation.y
                        }`
                      );
                    } else {
                      system.clearRun(runInt);
                      system.run(async () => {
                        player.camera.clear();
                        await player.runCommandAsync(
                          `inputpermission set @s movement enabled`
                        );
                      });
                    }
                  });
                }
              }
            });
        }
        if (slc == 1) {
          let choose = new ModalFormData()
            .dropdown("Select", droneList)
            .show(player)
            .then((scb) => {
              if (scb.canceled) return;
              initPosMap.set(player, player.location);
              for (const drone of dronesArray) {
                if (drone?.hasTag(`drone:${droneList[scb.formValues]}`)) {
                  const blockTablet = new ItemStack(modules[2], 1);
                  blockTablet.lockMode = ItemLockMode.slot;
                  blockTablet.lockMode = ItemLockMode.inventory;
                  blockTablet.keepOnDeath = true;
                  inv.setItem(player.selectedSlotIndex, blockTablet);
                  player.addTag("in_camera");
                  player.sendMessage(
                    `§aFly: Look up\n§cStatic: Sneak\n§bDescend: Look down`
                  );
                  const runInt = system.runInterval(async () => {
                    if (drone?.hasTag(`drone:${droneList[scb.formValues]}`)) {
                      if (player?.hasTag("in_camera")) {
                        await player.runCommandAsync(
                          `inputpermission set @s movement enabled`
                        );
                        const coordinates = drone.location;
                        const cameraRotation = player.getRotation();
                        const plrV = player.getVelocity();
                        drone.addEffect("slow_falling", 20000000, {
                          showParticles: false,
                          amplifier: 0,
                        });
                        if (!player.isSneaking && cameraRotation.x < -30) {
                          drone.addEffect("levitation", 5, {
                            showParticles: false,
                            amplifier: 4,
                          });
                          player.onScreenDisplay.setActionBar("§aFlying");
                        } else if (
                          !player.isSneaking &&
                          cameraRotation.x > -30
                        ) {
                          player.onScreenDisplay.setActionBar("§bDecending");
                        } else if (player.isSneaking) {
                          drone.teleport(drone.location);
                          player.onScreenDisplay.setActionBar("§cStatic");
                        }
                        if (!plrV.x == 0 || !plrV.z == 0) {
                          player.teleport(initPosMap.get(player));
                        }
                        drone.applyImpulse({
                          x: plrV.x / 1.3,
                          y: 0,
                          z: plrV.z / 1.3,
                        });
                        await player.runCommandAsync(
                          `camera @s set minecraft:free ease 0 linear pos ${
                            coordinates.x
                          } ${coordinates.y + 1} ${coordinates.z} rot 0 ${
                            cameraRotation.y
                          }`
                        );
                        drone.setRotation(cameraRotation);
                      } else {
                        system.clearRun(runInt);
                        system.run(async () => {
                          player.camera.clear();
                          await player.runCommandAsync(
                            `inputpermission set @s movement enabled`
                          );
                        });
                      }
                    }
                  });
                }
              }
            });
        }
        if (slc == 2) {
          const returnTablet = new ItemStack(modules[2], 1);
          inv.setItem(player.selectedSlotIndex, returnTablet);
          player.addTag("cameraStop");
          player.removeTag("in_camera");
          player.camera.clear();
          await player.runCommandAsync(
            `inputpermission set @s movement enabled`
          );
          system.runTimeout(() => {
            player.removeTag("cameraStop");
          }, 20);
        }
      });
    }
  }
});

//Vinculacion
world.afterEvents.playerInteractWithEntity.subscribe(async (scb) => {
  const { player, target: entity, itemStack: item } = scb;
  const loc = entity.location;
  const keyCodeTag = entity.getTags().some((tag) => tag.includes("keycode:"));
  //turret
  if (entity?.typeId == "scb:turret" && entity?.hasTag(`owner:${player.name}`)) {
    turretSetting.show(player).then((scb) => {
      if (scb.canceled) return;
      const { selection: slc } = scb;
      if (slc == 0) {
        entity.triggerEvent("scb:on");
      }
      if (slc == 1) {
        entity.triggerEvent("scb:off");
      }
      if (slc == 2) {
        entity.triggerEvent("scb:only_monsters");
      }
      if (slc == 3) {
        entity.triggerEvent("scb:only_players");
      }
      if (slc == 4) {
        entity.triggerEvent("scb:attack_all");
      }
      if (slc == 5) {
        advertise.show(player).then((scb) => {
          if (scb.canceled) return;
          if (scb.selection == 1) {
            entity.triggerEvent("scb:remove");
            entity.dimension.spawnItem(loots[0], loc);
          }
        });
      }
    });
  }
  //mine
  if (
    entity?.typeId == "scb:mine_entity" &&
    !entity?.hasTag(`owner:${player.name}`)
  ) {
    scbName.show(player).then((scb) => {
      if (scb.canceled) return;
      const { formValues } = scb;
      if (!formValues[0] == undefined || !formValues[0] == "") {
        entity.addTag(`owner:${player.name}`);
        entity.addTag(`mine:${formValues[0]}`);
        entity.triggerEvent("scb:remove_interact");
      }
    });
  }
  //camera
  if (
    entity?.typeId == "scb:camera_entity" &&
    !entity?.hasTag(`owner:${player.name}`)
  ) {
    scbName.show(player).then((scb) => {
      if (scb.canceled) return;
      const { formValues } = scb;
      if (!formValues[0] == undefined || !formValues[0] == "") {
        entity.addTag(`owner:${player.name}`);
        entity.addTag(`camera:${formValues[0]}`);
        entity.triggerEvent("scb:remove_interact");
        entity.addTag(`coords:${loc.x}:${loc.y}:${loc.z}`);
      }
    });
  }
  //drone
  if (entity?.typeId == "scb:drone" && !entity?.hasTag(`owner:${player.name}`)) {
    scbName.show(player).then((scb) => {
      if (scb.canceled) return;
      const { formValues } = scb;
      if (!formValues[0] == undefined || !formValues[0] == "") {
        entity.addTag(`owner:${player.name}`);
        entity.addTag(`drone:${formValues[0]}`);
      }
    });
  }
  if (
    entity?.typeId == "scb:drone" &&
    entity?.hasTag(`owner:${player.name}`) &&
    player.isSneaking
  ) {
    entity.dimension.spawnItem(new ItemStack("scb:dron_item"), entity.location);
    entity.triggerEvent("scb:despawn");
  }
  //chest
  if (entity?.typeId.includes("chest_keypad") && !keyCodeTag) {
    keypadChoose.show(player).then((scb) => {
      if (scb.canceled) return;
      const { formValues } = scb;
      if (!formValues[0] == undefined || !formValues[0] == "") {
        entity.addTag(`keycode:${formValues[0]}`);
        player.sendMessage(`§b KeyCode added: ${formValues[0]}`);
      }
    });
  }
  if (entity?.typeId.includes("chest_keypad") && keyCodeTag) {
    if (!entity?.hasTag("in_cooldown")) {
      keycode.show(player).then((scb) => {
        if (scb.canceled) return;
        const { formValues } = scb;
        console.warn(formValues[0]);
        if (formValues[0] !== "") {
          const correctValue = entity
            .getTags()
            .find((tag) => tag === `keycode:${formValues[0]}`);
          try {
            if (entity?.hasTag(correctValue)) {
              entity.addTag("in_cooldown");
              player.sendMessage("§a Chest Open");
              system.runTimeout(() => {
                entity.removeTag("in_cooldown");
              }, 100);
            }
          } catch (e) {
            player.sendMessage(`§c Error`);
          }
        }
      });
    }
  }
  if (entity?.typeId == "scb:keypad_entity" && !keyCodeTag) {
    keypadChoose.show(player).then((scb) => {
      if (scb.canceled) return;
      const { formValues } = scb;
      if (!formValues[0] == undefined || !formValues[0] == "") {
        entity.addTag(`keycode:${formValues[0]}`);
        player.sendMessage(`§b KeyCode added: ${formValues[0]}`);
      }
    });
  }
  if (entity?.typeId == "scb:keypad_entity" && keyCodeTag) {
    if (!entity?.hasTag("in_cooldown")) {
      keycode.show(player).then(async (scb) => {
        if (scb.canceled) return;
        const { formValues } = scb;
        if (formValues[0] !== "") {
          const correctValue = entity
            .getTags()
            .find((tag) => tag === `keycode:${formValues[0]}`);
          try {
            if (entity?.hasTag(correctValue)) {
              entity.addTag("in_cooldown");
              player.sendMessage("§a Welcome again");
              const doors = entity.dimension.getEntities({
                location: entity.location,
                maxDistance: 3,
                type: "scb:scanner_door",
              });
              doors.forEach((door) => {
                openDoorFunction(door);
              });
              system.runTimeout(() => {
                doors.forEach((door) => {
                  openDoorFunction(door);
                });
                entity?.removeTag("in_cooldown");
              }, 40);
            }
          } catch (e) {
            console.warn(e.stack);
            player.sendMessage(`§c Error`);
          }
        }
      });
    }
  }
  if (
    entity.typeId == "scb:scanner_door" &&
    entity?.hasTag("owner:" + player.name) &&
    item?.typeId == "scb:remover"
  ) {
    entity.dimension.spawnItem(
      new ItemStack("scb:reinforced_door_item"),
      entity.location
    );
    const air = new BlockVolume(entity.location, {
      x: entity.location.x,
      y: entity.location.y + 1,
      z: entity.location.z,
    });
    entity.dimension.fillBlocks(air, "minecraft:air");
    entity.remove();
  }
  if (entity.isValid() && entity?.hasTag("in_cooldown") && item?.typeId == "scb:remover") {
    if (entity?.typeId == "scb:keypad_entity") {
      await entity.runCommandAsync(`function keypad`);
    }
    if (entity?.typeId.includes("reinforced_chest")) {
      entity.dimension.spawnItem(
        new ItemStack(entity?.typeId, 1),
        entity?.location
      );
      await entity?.runCommandAsync(`function remove_chests`);
    }
  }
});
