import BaseBoss from '../BaseBoss';
import { world, system, EntityDamageCause, BlockPermutation } from "@minecraft/server";
import * as utils from "../misc";
import { startCoroutineForBoss } from "../CoroutineClass";

const ABILITY_COOLDOWN_CONFIG = new Map([
  ["range_attack", 2000] // Cooldown in milliseconds
]);

const TRY_ABILITY_COOLDOWN = 120; // 1000 ms between each check

class MAgmaKing extends BaseBoss {
  abilityCd;
  lastAbilityCheckTime;
  isSubscribed = false;

  constructor(entityId) {
    super('MAgmaKing', entityId);
    this.abilityCd = new Map();
  }

  async specialBehavior() {
    if (!this.isSubscribed) {
      world.afterEvents.dataDrivenEntityTrigger.subscribe((args) => {
        const { entity, eventId } = args;
        if (!this.entity.isValid()) return;
        if (entity.id === this.entityId && eventId === 'lv_mo:try_active_ability') {
          this.tryActiveAbility();
        }
      });
      this.isSubscribed = true
    }
    const magmaBlock = system.runInterval(() => {
      if (!this.entity.isValid()) {
        system.clearRun(magmaBlock);
        return;
      }
      try {
        const entityLocation = {
          x: Math.floor(this.entity.location.x),
          y: Math.floor(this.entity.location.y),
          z: Math.floor(this.entity.location.z),
        };
        const blockBelowLocation = { x: entityLocation.x, y: entityLocation.y - 1, z: entityLocation.z };
        const currentBlock = this.entity.dimension.getBlock(blockBelowLocation);
        if (currentBlock?.type.id === "minecraft:lava" || currentBlock?.type.id === "minecraft:flowing_lava") return;
        const lavaBlock = BlockPermutation.resolve("minecraft:flowing_lava");
        for (let dx = -1; dx <= 1; dx++) {
          for (let dz = -1; dz <= 1; dz++) {
            const targetBlockLocation = {
              x: entityLocation.x + dx,
              y: entityLocation.y - 1,
              z: entityLocation.z + dz,
            };
            const targetBlock = this.entity.dimension.getBlock(targetBlockLocation);
            //console.warn(targetBlock.type.id)
            targetBlock?.setPermutation(lavaBlock);
          }
        }
      } catch (error) {
      }
    },20);
    
  }


  async tryActiveAbility() {
    const now = Date.now();

    // Check if enough time has passed since the last ability check
    if (now - this.lastAbilityCheckTime < TRY_ABILITY_COOLDOWN) return;

    this.lastAbilityCheckTime = now; // Update last ability check time

    // Choose available abilities based on cooldown (basic_attack is always available)
    const availableAbilities = ["basic_attack"];
    if (this.isAbilityReady("range_attack")) {
      availableAbilities.push("range_attack");
    }

    // Select a random ability and execute it
    const abilityId = this.randomAbility(availableAbilities);
    if (abilityId === "basic_attack") {
      await this.basic_attack();
    } else if (abilityId === "range_attack") {
      await this.range_attack();
    }
  }

  // Helper function to check if an ability's cooldown has expired
  isAbilityReady(abilityId) {
    const now = Date.now();
    const lastUsed = this.abilityCd.get(abilityId) || 0;
    const cooldownTime = ABILITY_COOLDOWN_CONFIG.get(abilityId) || 0;
    return (now - lastUsed) >= cooldownTime;
  }

  BASIC_ATTACK_DURATION = parseFloat(1.5 * 20)
  BASIC_ATTACK_TIME = parseFloat(0.75 * 20)
  BASIC_ATTACK_RADIUS = 3;
  BASIC_ATTACK_DAMAGE = 5;
  async basic_attack() {
    if (!this.entity.isValid()) return;
    this.entity.setProperty('lv_mo:animations', 'basic_attack');
    utils.facePlayer(this.entity, 1)
    if (!this.entity.isValid()) return;
    let victims = utils.getRadiusEntity(this.entity, utils.getPosForward(this.entity, 2), this.BASIC_ATTACK_RADIUS, ['player']);
    utils.delayExecute(this.BASIC_ATTACK_TIME, () => {
      if (!this.entity.isValid()) return;
      for (let victim of victims) {
        if (!this.entity.isValid()) return;
        victim.applyDamage(this.BASIC_ATTACK_DAMAGE, {
          cause: EntityDamageCause.entityAttack,
          damagingEntity: this.entity,
        });
      }
    });
    await this.wait((this.BASIC_ATTACK_DURATION - this.BASIC_ATTACK_TIME));

    // No cooldown set here, as basic_attack is always available
    await this.resetAndReadyAbility();
  }

  RANGE_ATTACK_PROJECTILE = 'lv_mo:magma_spike';
  RANGE_ATTACK_DURATION = parseFloat(1.25 * 20);
  RANGE_ATTACK_TIME = parseFloat(0.42 * 20);
  RANGE_ATTACK_TIP_DURATION = parseFloat(3 * 20);
  async range_attack() {
    this.tipPlayer(15, 'avoid the special attack');
    let i = 0;
    const test = system.runInterval(() => {
      if (!this.entity.isValid() || i >= this.RANGE_ATTACK_TIP_DURATION) {
        system.clearRun(test)
      }
      if (i % 5 == 0) {
        this.entity.runCommand("/execute as @s facing entity @p eyes run tp @s ~ ~ ~ ~ ~");
      }
      utils.applyImpulse(this.entity, 0.05, 0, -1)
      i++
    }, 1)

    let active = function* () {
      if (!this.entity.isValid()) return;

      // Initial tip duration
      yield this.RANGE_ATTACK_TIP_DURATION;

      if (!this.entity.isValid()) return;
      utils.facePlayer(this.entity, 1);
      this.entity.setProperty('lv_mo:animations', 'range_attack');

      yield this.RANGE_ATTACK_TIME;

      // Target victims
      const victimLoc = this.getRadiusEntity(this.entity.location, 15);
      for (let victim of victimLoc) {
        const { x, y, z } = victim.location;
        yield 5;  // Adjust this delay if needed
        if (!this.entity.isValid()) return;
        this.entity.runCommand(`summon ${this.RANGE_ATTACK_PROJECTILE} ${x} ${y} ${z} facing ^^^180`);
        this.entity.runCommand(`playsound block.lantern.break @a ${x} ${y} ${z} 1 1.5 0.001`);
        this.entity.runCommand(`playsound block.lantern.break @a ${x} ${y} ${z} 0.75 0.5 0.001`);
        this.entity.runCommand(`playsound fall.netherrack @a ${x} ${y} ${z} 1 0.75 0.001`);
        this.entity.runCommand(`playsound fall.netherrack @a ${x} ${y} ${z} 0.75 0.25 0.001`);
        this.entity.runCommand(`playsound fall.nether_gold_ore @a ${x} ${y} ${z} 0.75 0.25 0.001`);
      }

      // Final cooldown yield
      const cooldownTime = ABILITY_COOLDOWN_CONFIG.get('range_attack');
      yield (this.RANGE_ATTACK_DURATION - this.RANGE_ATTACK_TIME);

      if (!this.entity.isValid()) return;
      this.abilityCd.set("range_attack", Date.now() + cooldownTime);
    }.bind(this);

    startCoroutineForBoss(active, () => {
      this.resetAndReadyAbility();
    }, this.entity.id);

  }
}

export default MAgmaKing;
