import { world, system } from "@minecraft/server";

const COOLDOWN_IN_TICKS = 24; // 1.2 seconds * 20 ticks per second

class chanters {
    static players = new Map();

    constructor(player) {
        this.player = player;
        this.cooldown = 0;
    }

    canThrow() {
        return this.cooldown <= 0;
    }

    throw(playerViewDirection, head) {
        if (!this.canThrow()) return false;

        let projectile = world.getDimension(this.player.dimension.id).spawnEntity("jam:projectile_wand_1", offsetPositionInDirection(head, playerViewDirection, 3));
        projectile.clearVelocity();
        projectile.applyImpulse({ x: playerViewDirection.x * 2, y: playerViewDirection.y * 2, z: playerViewDirection.z * 2 });
        this.player.runCommand("/clear @s jam:item_wand_1 0 1");
        
        // Set cooldown
        this.cooldown = COOLDOWN_IN_TICKS;
        return true;
    }

    tick() {
        if (this.cooldown > 0) {
            this.cooldown--;
        }
    }

    static getPlayerThrower(player) {
        if (!this.players.has(player.id)) {
            this.players.set(player.id, new chanters(player));
        }
        return this.players.get(player.id);
    }
}

// Set up tick event for cooldown management
system.runInterval(() => {
    for (let thrower of chanters.players.values()) {
        thrower.tick();
    }
}, 1);

export function itemUseController(event) {
    const typeId = event.source.typeId;
    if (typeId !== "minecraft:player") {
        return;
    }
    const holdingItem = event.source.getComponent("equippable").getEquipment("Mainhand");

    if (holdingItem == undefined) {
        return;
    } else {
        if (holdingItem.typeId == "jam:item_wand_1") {
            // Check if player has the alive tag
            if (!event.source.hasTag("alive")) {
                event.source.runCommand('title @s actionbar §c§lYou can only use this item when the game starts!');
                return;
            }
            
            const thrower = chanters.getPlayerThrower(event.source);
            if (thrower.canThrow()) {
                let playerViewDirection = event.source.getViewDirection();
                const head = event.source.getHeadLocation();
                thrower.throw(playerViewDirection, head);
            }
        }
    }
}

function offsetPositionInDirection(position, viewDirection, offset) {
  // Ensure the view direction vector is normalized
  const normalizedViewDirection = normalizeVector3(viewDirection);

  // Calculate the offset in each axis based on the normalized view direction
  const offsetX = normalizedViewDirection.x * offset;
  const offsetY = normalizedViewDirection.y * offset;
  const offsetZ = normalizedViewDirection.z * offset;

  // Create a new Vector3 representing the offset position
  // const offsetPosition = new Vector3(position.x + offsetX, position.y + offsetY, position.z + offsetZ);

  const offsetPosition = {
    x: position.x + offsetX,
    y: position.y + offsetY,
    z: position.z + offsetZ,
  };

  return offsetPosition;
}

function normalizeVector3(vector) {
  const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
  if (length !== 0) {
    return {
      x: vector.x / length,
      y: vector.y / length,
      z: vector.z / length,
    };
  } else {
    return {
      x: 0,
      y: 0,
      z: 0,
    };
    // Avoid division by zero
  }
}
