import * as server from "@minecraft/server";
import { system, Player } from "@minecraft/server";
import { ItemStack } from "@minecraft/server";

//Files used
import {
  boats,
  ghostAbility,
  pirateAbility,
  removeFishingRod,
} from "./boats.js";
import { activateBoatAbility, activateBoatCooldown } from "./abilityManager.js";
import * as manager from "./abilityManager.js";

let pirateShoot = false;
let ghostShoot = false;

//Counting offsets
function toRadians(degrees) {
  return degrees * (Math.PI / 180);
}
function getOffsetRelativeToEntityRotation(boat, offset) {
  const yawRadians = toRadians(boat.getRotation().y);
  const pitchRadians = toRadians(boat.getRotation().x);
  const sinYaw = Math.sin(yawRadians);
  const cosYaw = Math.cos(yawRadians);
  const sinPitch = Math.sin(pitchRadians);
  const cosPitch = Math.cos(pitchRadians);
  const deltaX = cosYaw * offset.x - sinYaw * offset.z;
  const deltaZ = sinYaw * offset.x + cosYaw * offset.z;
  const deltaY =
    cosPitch * offset.y +
    sinPitch * Math.sqrt(offset.x * offset.x + offset.z * offset.z);
  return {
    x: boat?.location.x + cosPitch * deltaX,
    y: boat?.location.y + deltaY,
    z: boat?.location.z + cosPitch * deltaZ,
  };
}

const allBoats = [
  "pc:algaeboat",
  "pc:armoredboat",
  "pc:cargoboat",
  "pc:fireboat",
  "pc:fishingboat",
  "pc:flyingboat",
  "pc:ghostboat",
  "pc:glassbottomboat",
  "pc:gravityboat",
  "pc:harvesterboat",
  "pc:healingboat",
  "pc:iceboat",
  "pc:icebreakerboat",
  "pc:lighthouseboat",
  "pc:partyboat",
  "pc:pirateboat",
  "pc:reinforcedboat",
  "pc:rgbboat",
  "pc:speedboat",
  "pc:stealthboat",
  "pc:submarineboat",
  "pc:teleportationboat",
  "pc:tntboat",
  "pc:tradingboat",
  "pc:turtleboat",
];

//Script loaded
const world = server.world;
world.sendMessage("§aMain.js loaded!");

system.runInterval(() => {
  world.getAllPlayers().forEach((player) => {
    try {
      const playerPos = player?.location;
      const boat = player?.getComponent("riding")?.entityRidingOn;
      const boatId = player?.getComponent("riding")?.entityRidingOn?.typeId;

      if (boatId) {
        if (
          boatId !== "pc:lighthouseboat" &&
          boatId !== "pc:cargoboat" &&
          boatId !== "pc:flyingboat"
        ) {
          player?.runCommandAsync(
            `/execute as @s[tag=!fishingTime] at @s[tag=!fishingTime] run camera @s[tag=!fishingTime] set pc:boat`
          );
        }
        if (
          boatId === "pc:lighthouseboat" ||
          boatId === "pc:cargoboat" ||
          boatId === "pc:flyingboat"
        ) {
          player?.runCommandAsync(
            `/execute as @s at @s run camera @s set pc:big_boat`
          );
        }
        player?.runCommandAsync(
          `/execute as @e[type=pc:fireboat] at @s run effect @s fire_resistance 999999 255 true`
        );
      } else {
        removeFishingRod(player);
        player?.removeTag("fishingTime");
        player?.runCommandAsync(
          `/event entity @e[type=pc:seat_replacement, c=1, r=15] pc:despawns`
        );
        player?.runCommandAsync(
          "/event entity @e[type=pc:fishingboat, c=1, r=15] pc:set_normal_boat"
        );
        player?.runCommandAsync(`/camera @s clear`);
        return;
      }

      if (
        boatId === "pc:submarineboat" &&
        player.getRotation().x > -90 &&
        player.getRotation().x < 0
      ) {
        player?.runCommandAsync(
          `/execute as @e[type=pc:submarineboat, tag=submarineOn] at @s rotated as @p if block ^^^0.5 water run tp @s ^^^0.25 ~ ~`
        );
        player?.runCommandAsync(
          `/execute as @e[type=pc:submarineboat, tag=submarineOn] at @s rotated as @p if block ^^^0.5 seagrass run tp @s ^^^0.25 ~ ~`
        );
        player?.runCommandAsync(
          `/execute as @e[type=pc:submarineboat, tag=submarineOn] at @s rotated as @p if block ^^^0.5 kelp run tp @s ^^^0.25 ~ ~`
        );
      }
      if (boatId === "pc:flyingboat") {
        const blockBelow = boat?.dimension?.getBlock({
          x: boat?.location.x,
          y: boat?.location.y - 1,
          z: boat?.location.z,
        });
        if (!blockBelow) {
          return;
        }
        if (blockBelow?.typeId !== "minecraft:air") {
          boat.removeEffect("slow_falling");
        }
      }
    } catch (error) {}
    player?.runCommandAsync(
      `/execute as @e[type=pc:tnt] at @s unless block ~~-1~ air run event entity @s pc:instant_explosion`
    );
  });
});

system.runInterval(() => {
  world.getAllPlayers().forEach((player) => {
    try {
      const boat = player?.getComponent("riding")?.entityRidingOn;
      const boatId = boat?.typeId;
      let boatPos = boat?.location;

      if (boatId === "pc:submarineboat") {
        // Check the block directly above the boat
        const blockAbove = boat?.dimension.getBlock({
          x: boat?.location.x,
          y: boat?.location.y + 2,
          z: boat?.location.z,
        });

        // Define blocks to ignore for emergence detection
        const ignoredBlocks = [
          "minecraft:kelp",
          "minecraft:seagrass",
          "minecraft:tall_seagrass",
        ];

        if (blockAbove && boat?.hasTag("submarineOn")) {
          if (
            blockAbove.typeId === "minecraft:water" &&
            !boat.hasTag("underwater")
          ) {
            // Boat goes underwater: add tag and play submerging sound
            boat.addTag("underwater");
            boat?.setProperty("pc:underwater", true);
            world
              ?.getDimension(boat?.dimension?.id)
              ?.playSound("pc.submerge", boatPos, { pitch: 1, volume: 50 });
          } else if (
            blockAbove.typeId !== "minecraft:water" &&
            !ignoredBlocks.includes(blockAbove.typeId) &&
            boat.hasTag("underwater")
          ) {
            // Boat emerges from water: remove tag and play emerging sound
            boat?.removeTag("underwater");
            boat?.setProperty("pc:underwater", false);
            world
              ?.getDimension(boat?.dimension?.id)
              ?.playSound("pc.emerge", boatPos, { pitch: 1, volume: 50 });
          }
        }
      }

      // Existing code for other boats and actions
    } catch (error) {
      console.error("Error processing player:", error);
    }
  });
});

// Subscribe to item use event to trigger boat abilities
world.afterEvents.itemUse.subscribe((e) => {
  const player = e?.source;
  const boat = player?.getComponent("riding")?.entityRidingOn;
  const boatId = player?.getComponent("riding")?.entityRidingOn?.typeId;
  if (!boatId) return;

  if (boatId === "pc:teleportationboat") {
    const dim = player?.dimension;
    const playerPos = player?.location;
    const boats = dim.getEntities({
      type: "pc:teleportationboat",
      closest: 1,
      location: playerPos,
    });
    if (!boats || boats.length === 0) return;

    boats.forEach((boat) => {
      let teleportationLoc = getOffsetRelativeToEntityRotation(boat, {
        x: 0,
        y: 0,
        z: 40,
      });
      let teleportationLoc2 = getOffsetRelativeToEntityRotation(boat, {
        x: 0,
        y: 1,
        z: 40,
      });

      let block = world.getDimension(dim.id).getBlock(teleportationLoc);
      let blockName = block?.typeId;
      let block2 = world.getDimension(dim.id).getBlock(teleportationLoc2);
      let blockName2 = block2?.typeId;

      if (
        (blockName === "minecraft:water" || blockName === "minecraft:air") &&
        blockName2 === "minecraft:air"
      ) {
        activateBoatAbility(player, boatId, boat); // ✅ Pokreni ability tek ako uslovi važe
      } else {
        world.sendMessage(
          `§cYou must be looking at water for this ability to work.`
        );
      }
    });
  } else {
    activateBoatAbility(player, boatId, boat);
  }
});

world.afterEvents.entityHurt.subscribe((e) => {
  const attacker = e?.damageSource?.damagingEntity;
  if (!attacker) {
    return;
  }
  const target = e?.hurtEntity;
  if (!target) {
    return;
  }
  try {
    if (target.typeId === "pc:reinforcedboat" && target?.hasTag("active")) {
      const attackerLoc = attacker?.location;
      world
        .getDimension(attacker?.dimension?.id)
        .createExplosion(attackerLoc, 3, {
          allowUnderwater: true,
          breaksBlocks: true,
          causesFire: true,
        });
    }
  } catch {}
});

system.runInterval(() => {
  world.getAllPlayers().forEach((player) => {
    try {
      const boatId = player?.getComponent("riding")?.entityRidingOn?.typeId;
      if (!boatId) {
        return;
      }
      //Testing if riding pirate boat
      if (
        boatId === "pc:pirateboat" &&
        !player.hasComponent("minecraft:is_tamed")
      ) {
        player?.triggerEvent("inside_pirate_boat");
      } else if (
        boatId !== "pc:pirateboat" &&
        player.hasComponent("minecraft:is_tamed")
      ) {
        player?.triggerEvent("outside_pirate_boat");
      }

      // Check if the player is in a specific boat, e.g., "pc:pirateboat"
      if (
        boatId === "pc:pirateboat" &&
        player?.hasTag("pirateShoot") &&
        !pirateShoot &&
        !pirateAbility
      ) {
        const dim = player?.dimension;
        const playerPos = player?.location;
        const boats = dim.getEntities({
          type: "pc:pirateboat",
          closest: 1,
          location: playerPos,
        });
        if (!boats || boats.length === 0) {
          return; // No entities found
        }
        boats.forEach((boat) => {
          let boatPos = boat?.location;
          if (!pirateShoot) {
            boat.playAnimation("animation.pirateboat.left.plotun", {
              blendOutTime: 60,
            });
            world
              ?.getDimension(boat?.dimension?.id)
              ?.playSound("pc.cannon_shot_left", boatPos, {
                pitch: 1,
                volume: 100,
              });
            let yaw = boat.getRotation().y;
            // Convert yaw to radians
            let yawRadians = yaw * (Math.PI / 180);
            // Calculate the impulse direction based on the boat's yaw (moving to the left)
            let impulseX = Math.cos(yawRadians) * 2;
            let impulseZ = Math.sin(yawRadians) * 2;
            let boatDim = boat?.dimension.id;
            let fireballSpawn1 = getOffsetRelativeToEntityRotation(boat, {
              x: 7,
              y: 2,
              z: 1.2,
            });
            let projectile1 = world
              .getDimension(boatDim)
              .spawnEntity("pc:cannonball", fireballSpawn1);
            projectile1?.clearVelocity();
            projectile1?.applyImpulse({
              x: impulseX,
              y: 0,
              z: impulseZ,
            });
            let fireballSpawn2 = getOffsetRelativeToEntityRotation(boat, {
              x: 7,
              y: 2,
              z: -1,
            });
            let projectile2 = world
              .getDimension(boatDim)
              .spawnEntity("pc:cannonball", fireballSpawn2);
            projectile2?.clearVelocity();
            projectile2?.applyImpulse({
              x: impulseX,
              y: 0,
              z: impulseZ,
            });
            let fireballSpawn3 = getOffsetRelativeToEntityRotation(boat, {
              x: 7,
              y: 2,
              z: -3.5,
            });
            let projectile3 = world
              .getDimension(boatDim)
              .spawnEntity("pc:cannonball", fireballSpawn3);
            projectile3?.clearVelocity();
            projectile3?.applyImpulse({
              x: impulseX,
              y: 0,
              z: impulseZ,
            });
            pirateShoot = true;
            player?.removeTag("pirateShoot");
            system.runTimeout(() => {
              pirateShoot = false;
              player?.removeTag("pirateShoot");
            }, 200);
          }
        });
        activateBoatCooldown(player, boatId); // Still use the cooldown system
      } else {
        if (player?.hasTag("pirateShoot")) {
          world.sendMessage("§cPlease wait to use the ability again.");
        }
      }

      //Testing if riding ghost_boat
      if (
        boatId === "pc:ghostboat" &&
        !player.hasComponent("minecraft:is_saddled")
      ) {
        //world.sendMessage(`This works`)
        player?.triggerEvent("inside_ghost_boat");
      } else if (
        boatId !== "pc:ghostboat" &&
        player.hasComponent("minecraft:is_saddled")
      ) {
        //world.sendMessage(`This works 2`)
        player?.triggerEvent("outside_ghost_boat");
      }

      // Check if the player is in a specific boat, e.g., "pc:ghostboat"
      if (
        boatId === "pc:ghostboat" &&
        player?.hasTag("ghostShoot") &&
        !ghostShoot &&
        !ghostAbility
      ) {
        const dim = player?.dimension;
        const playerPos = player?.location;
        const boats = dim.getEntities({
          type: "pc:ghostboat",
          closest: 1,
          location: playerPos,
        });
        if (!boats || boats.length === 0) {
          return; // No entities found
        }
        boats.forEach((boat) => {
          let boatPos = boat?.location;
          if (!ghostShoot) {
            boat.playAnimation("animation.ghostboat.left.plotun", {
              blendOutTime: 60,
            });
            world
              ?.getDimension(boat?.dimension?.id)
              ?.playSound("pc.cannon_shot_left", boatPos, {
                pitch: 1,
                volume: 100,
              });
            let yaw = boat.getRotation().y;
            // Convert yaw to radians
            let yawRadians = yaw * (Math.PI / 180);
            // Calculate the impulse direction based on the boat's yaw (moving to the left)
            let impulseX = Math.cos(yawRadians) * 2;
            let impulseZ = Math.sin(yawRadians) * 2;
            let boatDim = boat?.dimension.id;
            let fireballSpawn1 = getOffsetRelativeToEntityRotation(boat, {
              x: 7,
              y: 2,
              z: 1.2,
            });
            let projectile1 = world
              .getDimension(boatDim)
              .spawnEntity("pc:cannonball", fireballSpawn1);
            projectile1?.clearVelocity();
            projectile1?.applyImpulse({
              x: impulseX,
              y: 0,
              z: impulseZ,
            });
            let fireballSpawn2 = getOffsetRelativeToEntityRotation(boat, {
              x: 7,
              y: 2,
              z: -1,
            });
            let projectile2 = world
              .getDimension(boatDim)
              .spawnEntity("pc:cannonball", fireballSpawn2);
            projectile2?.clearVelocity();
            projectile2?.applyImpulse({
              x: impulseX,
              y: 0,
              z: impulseZ,
            });
            let fireballSpawn3 = getOffsetRelativeToEntityRotation(boat, {
              x: 7,
              y: 2,
              z: -3.5,
            });
            let projectile3 = world
              .getDimension(boatDim)
              .spawnEntity("pc:cannonball", fireballSpawn3);
            projectile3?.clearVelocity();
            projectile3?.applyImpulse({
              x: impulseX,
              y: 0,
              z: impulseZ,
            });
            ghostShoot = true;
            player?.removeTag("ghostShoot");
            system.runTimeout(() => {
              ghostShoot = false;
              player?.removeTag("ghostShoot");
            }, 200);
          }
        });
        activateBoatCooldown(player, boatId); // Still use the cooldown system
      } else {
        if (player?.hasTag("ghostShoot")) {
          world.sendMessage("§cPlease wait to use the ability again.");
        }
      }
    } catch {}
  });
}, 10); // Runs every second

world.afterEvents.itemUse.subscribe((e) => {
  if (allBoats.includes(e?.itemStack?.typeId)) {
    const player = e?.source;
    const playerLocation = player?.location;
    const blockFromRay = player?.dimension.getBlockFromRay(
      { x: playerLocation.x, y: playerLocation.y + 1.4, z: playerLocation.z },
      player.getViewDirection(),
      { includeLiquidBlocks: true }
    )?.block;
    const blockFromRayId = blockFromRay.typeId;
    const blockLocation = blockFromRay.location;
    const blockFromRayDistance =
      Math.hypot(
        playerLocation.x - blockLocation.x,
        playerLocation.y - blockLocation.y,
        playerLocation.z - blockLocation.z
      ) <= 7;
    const blockId = blockFromRay.typeId;
    const blockAboveId = blockFromRay.above(1).typeId;
    //world.sendMessage(`fromRayLocation ${JSON.stringify(blockFromRay.location)} fromRayId ${blockFromRay.typeId} distanceFromPlayer ${blockFromRayDistance}`)
    if (
      blockId == "minecraft:water" ||
      blockId == "minecraft:flowing_water" ||
      blockAboveId == "minecraft:water" ||
      blockAboveId == "minecraft:flowing_water" ||
      blockFromRayId == "minecraft:flowing_water" ||
      (blockFromRayId == "minecraft:water" && blockFromRayDistance)
    ) {
      e?.source?.runCommandAsync(
        `/summon ${e?.itemStack?.typeId} ${blockFromRay?.location?.x} ${blockFromRay?.location?.y} ${blockFromRay?.location?.z}`
      );
      e?.source?.runCommandAsync(`/clear @s ${e?.itemStack?.typeId} 0 1`);
    }
  }
});
world.afterEvents.entityHitEntity.subscribe((e) => {
  const player = e?.damagingEntity;
  const entity = e?.hitEntity;

  if (!entity || !player) return;

  if (
    allBoats.includes(entity?.typeId) &&
    player.typeId === "minecraft:player"
  ) {
    try {
      // Ensure dynamic properties are initialized
      if (!entity?.getDynamicProperty("hits")) {
        entity?.setDynamicProperty("hits", 0);
      }
      if (!entity?.getDynamicProperty("lastHitTime")) {
        entity?.setDynamicProperty("lastHitTime", 0);
      }
      if (!entity?.getDynamicProperty("isLocked")) {
        entity?.setDynamicProperty("isLocked", false);
      }

      let isLocked = entity?.getDynamicProperty("isLocked");
      if (isLocked) return; // Exit if the entity is locked

      let currentTime = system.currentTick;
      let hits = entity?.getDynamicProperty("hits") || 0;
      let lastHitTime = entity?.getDynamicProperty("lastHitTime") || 0;

      // Check if more than 2 seconds (40 ticks per second in Minecraft) have passed since the last hit
      if (currentTime - lastHitTime > 40 * 2) {
        // Reset hits if more than 2 seconds have elapsed
        hits = 0;
      }

      // Increment hit count and update last hit time
      hits++;
      entity?.setDynamicProperty("hits", hits);
      entity?.setDynamicProperty("lastHitTime", currentTime);

      // Play hit animation
      let entityName = entity?.typeId.replace("pc:", "");
      entity?.playAnimation(`animation.${entityName}.shake`); // Replace with your animation name

      if (hits > 3) {
        // Lock the entity to prevent further updates
        entity?.setDynamicProperty("isLocked", true);

        // Play remove animation and execute removal command
        entity?.playAnimation(`animation.${entityName}.remove`); // Replace with your animation name
        world
          ?.getDimension(entity?.dimension?.id)
          .spawnItem(new ItemStack(entity?.typeId, 1), entity?.location);
        system.runTimeout(() => {
          try {
            entity.triggerEvent("pc:despawns"); // Remove the entity, or replace with another removal logic
          } catch {}
        }, 3);
      } else {
        // If hit count is below 3, set a timer to reset hits after 2 seconds
        system.runTimeout(() => {
          try {
            if (entity?.getDynamicProperty("hits") === hits) {
              entity?.setDynamicProperty("hits", 0);
            }
          } catch {}
        }, 20 * 2); // 2 seconds delay
      }
    } catch {}
  }
});

world.afterEvents.playerSpawn.subscribe((e) => {
  const player = e?.player;
  if (e?.initialSpawn && !player?.getDynamicProperty("gotBook")) {
    player?.setDynamicProperty("gotBook", true);
    const inventory = player?.getComponent("inventory")?.container;
    inventory?.addItem(new ItemStack("pc:guidebook_item", 1));
  }
  e?.player?.setProperty("pc:standing_seat", false);
});
