import * as mc from "@minecraft/server"
import * as racoAPI from "./raco-API"

mc.world.beforeEvents.playerBreakBlock.subscribe((data) => {
    const player = data.player;
    const block = data.block;
    const item = data.itemStack;

    // Verifica se o item na mão é uma "breeze_rod"
    if (item?.typeId == 'minecraft:breeze_rod') {
        data.cancel = true
        let currentPoints = []
        if (racoAPI.isJSONParsable(player?.getDynamicProperty('vtng_rt:points'))) {
            currentPoints = JSON.parse(player?.getDynamicProperty('vtng_rt:points'))
        }
        currentPoints.push(block.center())
        player.setDynamicProperty('vtng_rt:points', JSON.stringify(currentPoints))
        //console.warn(player?.getDynamicProperty('vtng_rt:points'))
        mc.system.run(() => {
            block.dimension.spawnParticle('vtng_rt:redstone_out', block.center())
        })
    }
});


mc.system.afterEvents.scriptEventReceive.subscribe((data)=>{
    const id = data.id
    const player = data.sourceEntity
    if (id == 'vtng_rt:cat'){
        //mc.system.runInterval(()=>{
            if (racoAPI.isJSONParsable(player?.getDynamicProperty('vtng_rt:points'))){
                const inputPoints = JSON.parse(player?.getDynamicProperty('vtng_rt:points'))
                const smoothCurve3 = generateClosedBezierCurve(inputPoints, 0.3) 
                function teleportAndSpawnParticles(smoothCurve, player, index = 0) {
                    if (index < smoothCurve.length) {
                        const thisPoint = smoothCurve[index];
                        
                        // Teleportar o jogador para o ponto
                        //console.warn(thisPoint)
                        player.teleport(thisPoint);
                
                        // Criar a partícula no ponto
                        player.dimension.spawnParticle('vtng_rt:train_particle', thisPoint);
                
                        // Chamar novamente a função após 1 tick (aproximadamente 50ms)
                        mc.system.runTimeout(() => {
                            teleportAndSpawnParticles(smoothCurve, player, index + 1);
                        }, 1); // 1 tick, ou seja, 50ms (depende da configuração de ticks no Minecraft)
                    }
                }
                
                // Exemplo de uso:
                teleportAndSpawnParticles(smoothCurve3, player);
                
            }
        //},5)
    } else if (id == 'vtng_rt:remove'){
        player.clearDynamicProperties()
    }
})












class Vector3 {
    constructor(x, y, z) {
      this.x = x;
      this.y = y;
      this.z = z;
    }
  
    // Função para calcular a distância entre dois vetores
    distanceTo(other) {
      return Math.sqrt(
        (this.x - other.x) ** 2 +
        (this.y - other.y) ** 2 +
        (this.z - other.z) ** 2
      );
    }
  
    // Interpolação linear entre dois vetores
    lerp(other, t) {
      return new Vector3(
        this.x + t * (other.x - this.x),
        this.y + t * (other.y - this.y),
        this.z + t * (other.z - this.z)
      );
    }
  
    // Soma de vetores escalados
    addScaled(other, scale) {
      return new Vector3(
        this.x + scale * other.x,
        this.y + scale * other.y,
        this.z + scale * other.z
      );
    }
  }
  
  // Função para gerar uma curva Bézier fechada
  function generateClosedBezierCurve(points, spacing) {
    if (points.length < 3) {
      throw new Error("É necessário pelo menos 3 pontos para criar uma curva fechada.");
    }
  
    const result = [];
    const totalPoints = points.length;
  
    // Geração dos pontos de controle para a curva Bézier
    const controlPoints = [];
    for (let i = 0; i < totalPoints; i++) {
      const prev = points[(i - 1 + totalPoints) % totalPoints]; // Ponto anterior
      const current = points[i]; // Ponto atual
      const next = points[(i + 1) % totalPoints]; // Próximo ponto
  
      // Calcula os pontos de controle baseados na direção do segmento
      const tangent = next.addScaled(prev, -1).addScaled(current, -1); // Vetor tangente
      const control1 = current.addScaled(tangent, 1 / 6); // Primeiro ponto de controle
      const control2 = current.addScaled(tangent, -1 / 6); // Segundo ponto de controle
  
      controlPoints.push({ control1, control2 });
    }
  
    // Geração dos pontos da curva para cada segmento
    for (let i = 0; i < totalPoints; i++) {
      const p0 = points[i];
      const p1 = controlPoints[i].control2;
      const p2 = controlPoints[(i + 1) % totalPoints].control1;
      const p3 = points[(i + 1) % totalPoints];
  
      const segmentPoints = [];
      for (let t = 0; t <= 1; t += 0.01) {
        const t2 = t * t;
        const t3 = t2 * t;
  
        // Fórmula da curva Bézier cúbica
        const x =
          (1 - t) ** 3 * p0.x +
          3 * (1 - t) ** 2 * t * p1.x +
          3 * (1 - t) * t2 * p2.x +
          t3 * p3.x;
        const y =
          (1 - t) ** 3 * p0.y +
          3 * (1 - t) ** 2 * t * p1.y +
          3 * (1 - t) * t2 * p2.y +
          t3 * p3.y;
        const z =
          (1 - t) ** 3 * p0.z +
          3 * (1 - t) ** 2 * t * p1.z +
          3 * (1 - t) * t2 * p2.z +
          t3 * p3.z;
  
        segmentPoints.push(new Vector3(x, y, z));
      }
  
      // Adiciona os pontos gerados ao resultado, respeitando o espaçamento
      if (result.length === 0) {
        result.push(segmentPoints[0]);
      }
  
      for (let j = 1; j < segmentPoints.length; j++) {
        const lastPoint = result[result.length - 1];
        const currentPoint = segmentPoints[j];
  
        if (lastPoint.distanceTo(currentPoint) >= spacing) {
          result.push(currentPoint);
        }
      }
    }
  
    return result;
  }