import { EquipmentSlot, MolangVariableMap, Player } from "@minecraft/server";
import { afterEvents, namespace as ns, world } from "./eternal/constants";
import { runInterval, runTimeout } from "./eternal/utils";

// Glider checker
runInterval(() => {
  const players = world.getPlayers();
  for (const player of players) {
    if (player.isUsingGlider && !player.isOnGround && !player.isInWater) {
      const vd = player.viewDirection;

      let verticalMovement;
      if (vd.y > 0) {
        verticalMovement = -vd.y / 2 - 0.2;
      } else {
        verticalMovement = vd.y / 2;
      }

      const speedMultiplier = -vd.y + 1.0;

      player.applyKnockback(vd.x, vd.z, speedMultiplier, verticalMovement);

      player.addEffect("minecraft:slow_falling", 10, { showParticles: false });

      const particleLocation = player.getFacingOffset(5);
      const mvm = new MolangVariableMap();
      mvm.setFloat("speed", player.speed);
      mvm.setVector3("direction", player.velocity);
      try {
        player.dimension.spawnParticle(`${ns}:glider_lines`, particleLocation, mvm);
        player.dimension.spawnParticle(`${ns}:glider_lines_2`, particleLocation, mvm);
      } catch (error) { }

      player.movementComponent.resetToDefaultValue();
      const baseSpeed = player.speed;
      player.speed = baseSpeed * speedMultiplier;

      if (!player.isPlayingGliderAnimation) {
        player.isPlayingGliderAnimation = true;

        runTimeout(() => {
          if (player.isUsingGlider) {
            player.playAnimation("animation.ecbl_bc.glider.gliding", {
              stopExpression: "false",
              blendOutTime: 0.3,
            });
          }
        });
      }
    } else if (player.isPlayingGliderAnimation || player.isInWater) {
      player.stopGliding();
    }
  }
});

// Glider damaging
runInterval(() => {
  for (const player of world.players) {
    if (player.isUsingGlider) {
      const glider = player.getEquipment(EquipmentSlot.Chest);
      if (player.gamemode !== "creative") player.damageItem(EquipmentSlot.Chest);
      if (glider.durability <= 0) {
        player.isUsingGlider = false;
      }
    }
  }
}, 20);

afterEvents.playerOnAirJump.subscribe(({ player }) => {
  const itemStack = player.getEquipment(EquipmentSlot.Chest);
  if (itemStack && itemStack.typeId === `${ns}:glider` && !player.isUsingGlider && !player.isInWater) {
    player.isUsingGlider = true;
    player.dimension.spawnParticle(`${ns}:glider_use`, player.location);
  } else if (player.isUsingGlider) {
    player.isUsingGlider = false;
  }
});

afterEvents.playerOnEquip.subscribe(({ player, itemStack }) => {
  if (itemStack.typeId === `${ns}:glider`) {
    player.playAnimation("animation.ecbl_bc.glider.remove", {
      stopExpression: "false",
    });
  }
});

afterEvents.playerSpawn.subscribe(({ player, initialSpawn }) => {
  if (initialSpawn) {
    player.stopGliding();
  }
});

afterEvents.playerOnUnequip.subscribe(({ player, itemStack }) => {
  if (itemStack.typeId === `${ns}:glider`) {
    player.isUsingGlider = false;
  }
});

afterEvents.playerOnLand.subscribe(({ player }) => {
  player.isUsingGlider = false;
});

afterEvents.playerSpawn.subscribe(({ player }) => {
  player.isUsingGlider = false;
});

Object.defineProperty(Player.prototype, "isUsingGlider", {
  value: false,
  writable: true,
});

Object.defineProperty(Player.prototype, "isPlayingGliderAnimation", {
  value: false,
  writable: true,
});

Object.defineProperty(Player.prototype, "stopGliding", {
  value: function () {
    this.isUsingGlider = false;
    this.removeEffect("minecraft:slow_falling");
    this.movementComponent.resetToDefaultValue();
    //this.camera.clear()
    if (this.isPlayingGliderAnimation) {
      this.isPlayingGliderAnimation = false;

      runTimeout(() => {
        if (!this.isUsingGlider) {
          this.playAnimation("animation.ecbl_bc.glider.close", {
            stopExpression: "false",
          });
        }
      });
      runTimeout(() => {
        if (!this.isUsingGlider) {
          this.playAnimation("animation.ecbl_bc.glider.remove", {
            stopExpression: "false",
          });
        }
      }, 20);
    }
  },
});
