import { ARMOR_EFFECT_STATS, DYNAMIC_PROPERTY, TAGS } from "./data.js"
import { system, world } from "@minecraft/server";

export const ARMOR_SET = {
  "4ks_wp:cryo": cryoArmorSet,
  "4ks_wp:flame": flameArmorSet,
  "4ks_wp:demonic": demonicArmorSet,
  "4ks_wp:divine": divineArmorSet,
  "4ks_wp:sculk": sculkArmorSet,
  "4ks_wp:dragon": dragonArmorSet,
  "4ks_wp:bedrock": bedrockArmorSet
}

export const ARMOR_SET_REMOVED = {
  "4ks_wp:cryo": cryoArmorRemoved,
  "4ks_wp:flame": flameArmorRemoved,
  "4ks_wp:demonic": demonicArmorRemoved,
  "4ks_wp:divine": divineArmorRemoved,
  "4ks_wp:sculk": sculkArmorRemoved,
  "4ks_wp:dragon": dragonArmorRemoved,
  "4ks_wp:bedrock": bedrockArmorRemoved
}

export const ON_HIT_TAGS = {}

ON_HIT_TAGS[TAGS.CRYO_ARMOR] = cryoArmorOnHit
ON_HIT_TAGS[TAGS.FLAME_ARMOR] = flameArmorOnHit
export const LOOP_TAGS_CHECK = {}

LOOP_TAGS_CHECK[TAGS.DIVINE_ARMOR] = divineArmorMainHand
LOOP_TAGS_CHECK[TAGS.DEMONIC_ARMOR] = demonicArmorMainHand
LOOP_TAGS_CHECK[TAGS.SCULK_ARMOR] = sculkXray

function sleep(tick) {
  return new Promise(resolve => {
    system.runTimeout(() => {
      resolve(tick)
    }, tick)
  })
}

async function demonicArmorMainHand(player) {
  const equippable = player.getComponent("minecraft:equippable");
  const mainhand = equippable?.getEquipment("Mainhand")?.typeId
  if (mainhand?.includes("_sword") || mainhand?.includes("_cutlass") || mainhand?.includes("_battleaxe") || mainhand?.includes("_club") || mainhand?.includes("_dagger")
    || mainhand?.includes("_gladius") || mainhand?.includes("_greatsword") || mainhand?.includes("_halberd") || mainhand?.includes("_khopesh") || mainhand?.includes("_mace")
    || mainhand?.includes("_mace") || mainhand?.includes("_spear")) {
    if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_SWORD)) return
    player.runCommand(`/effect @s strength ${ARMOR_EFFECT_STATS.demonic_armor_sword_strength_duration} ${ARMOR_EFFECT_STATS.demonic_armor_sword_strength_level} ${ARMOR_EFFECT_STATS.demonic_armor_sword_strength_hide_effect}`)
    player.runCommand(`/effect @s speed ${ARMOR_EFFECT_STATS.demonic_armor_sword_speed_duration} ${ARMOR_EFFECT_STATS.demonic_armor_sword_speed_level} ${ARMOR_EFFECT_STATS.demonic_armor_sword_speed_hide_effect}`)
    player.runCommand(`/effect @s haste 0 0`)
    player.addTag(TAGS.CUSTOM_MAIN_HAND_SWORD)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)
  } else if ((mainhand?.includes("_pickaxe") || mainhand?.includes("_hoe") || mainhand?.includes("_axe") || mainhand?.includes("_shovel"))) {
    if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)) return
    player.runCommand(`/effect @s strength 0 0`)
    player.runCommand(`/effect @s speed 0 0`)
    player.runCommand(`/effect @s haste ${ARMOR_EFFECT_STATS.demonic_armor_tools_haste_duration} ${ARMOR_EFFECT_STATS.demonic_armor_tools_haste_level} ${ARMOR_EFFECT_STATS.demonic_armor_tools_haste_hide_effect}`)
    player.addTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_SWORD)
  } else if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_SWORD)) {
    player.runCommand(`/effect @s strength 0 0`)
    player.runCommand(`/effect @s speed 0 0`)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_SWORD)
  } else if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)) {
    player.runCommand(`/effect @s haste 0 0`)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)
  }
}


async function sculkXray(player) {
  if (player.isSneaking && !player.getDynamicProperty(DYNAMIC_PROPERTY.sculk_delay)) {
    player.setDynamicProperty(DYNAMIC_PROPERTY.sculk_delay, true);
    const position = player.location;
    player.runCommand(`/tellraw @s { "rawtext": [ { "translate": "4ks_wp:text.xray.scanning" } ] }`);
    player.runCommand(`/playsound beacon.activate @s ~~~ 1.0 5.0`)
    const maxRadius = 25;
    let count = 0;

    for (let radius = 1; radius <= maxRadius; radius++) {
      for (let x = -radius; x <= radius; x++) {
        for (let y = -radius; y <= radius; y++) {
          for (let z = -radius; z <= radius; z++) {
            // Skip blocks inside the previous radius
            if (Math.abs(x) < radius && Math.abs(y) < radius && Math.abs(z) < radius) continue;

            const blockPosition = {
              x: position.x + x,
              y: position.y + y,
              z: position.z + z
            };
            const block = player.dimension.getBlock(blockPosition);
            count++;
            if (!block) continue;

            // Delay processing every 1000 blocks to prevent lag
            if (count % 1000 === 0) {
              await sleep(1);
            }

            const foundPosition = {
              x: block.location.x,
              y: block.location.y,
              z: block.location.z
            };

            if (
              block.permutation.matches("minecraft:diamond_ore") ||
              block.permutation.matches("minecraft:deepslate_diamond_ore") ||
              block.permutation.matches("minecraft:ancient_debris") ||
              block.permutation.matches("mob_spawner")
            ) {
              player.runCommand(
                `/summon 4ks_wp:xray_entity ${foundPosition.x} ${foundPosition.y} ${foundPosition.z}`
              );
            } else if (
              block.permutation.matches("minecraft:chest") ||
              block.permutation.matches("minecraft:trapped_chest")
            ) {
              const direction = block.permutation.getState("minecraft:cardinal_direction");
              const rotation = direction === "north"
                ? -180
                : direction === "south"
                  ? 0
                  : direction === "west"
                    ? 90
                    : -90;
              player.runCommand(
                `/summon 4ks_wp:xray_entity ${foundPosition.x} ${foundPosition.y} ${foundPosition.z} ${rotation}`
              );
            }
          }
        }
      }
    }

    player.runCommand(`/tellraw @s { "rawtext": [ { "translate": "4ks_wp:xray.scanning.done" } ] }`);
    player.runCommand("/playsound random.levelup @s");
    await sleep(100);
    player.setDynamicProperty(DYNAMIC_PROPERTY.sculk_delay, false);
  }
}

async function dragonArmorSet(player) {
  player.addTag(TAGS.DRAGON_ARMOR)
  player.runCommand("/effect @s resistance infinite 0 true")
  player.runCommand("/effect @s strength infinite 0 true")
}

async function dragonArmorRemoved(player) {
  player.removeTag(TAGS.DRAGON_ARMOR)
  player.runCommand("/effect @s resistance 0 0 true")
  player.runCommand("/effect @s strength 0 0 true")
}

async function bedrockArmorSet(player) {
  player.addTag(TAGS.BEDROCK_ARMOR)
  player.runCommand("/effect @s resistance infinite 0 true")
}

async function bedrockArmorRemoved(player) {
  player.removeTag(TAGS.BEDROCK_ARMOR)
  player.runCommand("/effect @s resistance 0 0 true")
}


async function sculkArmorSet(player) {
  player.addTag(TAGS.SCULK_ARMOR)
  player.runCommand("/effect @s strength infinite 1 true")
  player.runCommand("/effect @s resistance infinite 1 true")
}

async function sculkArmorRemoved(player) {
  player.removeTag(TAGS.SCULK_ARMOR)
  player.runCommand("/effect @s strength 0 0 true")
  player.runCommand("/effect @s resistance 0 0 true")
}

async function demonicArmorSet(player) {
  player.addTag(TAGS.DEMONIC_ARMOR)
  player.runCommand("/effect @s resistance infinite 2 true")
}


async function demonicArmorRemoved(player) {
  player.removeTag(TAGS.DEMONIC_ARMOR)
  player.runCommand("/effect @s resistance 0 0 true")  
  player.runCommand(`/effect @s strength 0 0`)
  if (!player.hasTag("4ksspwp") && !player.hasTag("4ksscutlass"))
    player.runCommand(`/effect @s speed 0 0`)
  player.runCommand(`/effect @s haste 0 0`)
  player.runCommand("/effect @s resistance 0 0 true")
}

async function divineArmorSet(player) {
  player.addTag(TAGS.DIVINE_ARMOR)
  player.runCommand("/effect @s resistance infinite 1 true")
}

async function divineArmorRemoved(player) {
  player.removeTag(TAGS.DIVINE_ARMOR)
  player.runCommand("/effect @s resistance 0 0 true")  
  player.runCommand(`/effect @s strength 0 0`)
  if (!player.hasTag("4ksspwp") && !player.hasTag("4ksscutlass"))
    player.runCommand(`/effect @s speed 0 0`)
  player.runCommand(`/effect @s haste 0 0`)
  player.runCommand("/effect @s resistance 0 0 true")
}

async function divineArmorMainHand(player) {
  const equippable = player.getComponent("minecraft:equippable");
  const mainhand = equippable?.getEquipment("Mainhand")?.typeId

  if (mainhand?.includes("_sword") || mainhand?.includes("_cutlass") || mainhand?.includes("_battleaxe") || mainhand?.includes("_club") || mainhand?.includes("_dagger")
    || mainhand?.includes("_gladius") || mainhand?.includes("_greatsword") || mainhand?.includes("_halberd") || mainhand?.includes("_khopesh") || mainhand?.includes("_mace")
    || mainhand?.includes("_mace") || mainhand?.includes("_spear")) {
    if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_SWORD)) return
    player.runCommand(`/effect @s strength ${ARMOR_EFFECT_STATS.divine_armor_sword_strength_duration} ${ARMOR_EFFECT_STATS.divine_armor_sword_strength_level} ${ARMOR_EFFECT_STATS.divine_armor_sword_strength_hide_effect}`)
    player.runCommand(`/effect @s speed ${ARMOR_EFFECT_STATS.divine_armor_sword_speed_duration} ${ARMOR_EFFECT_STATS.divine_armor_sword_speed_level} ${ARMOR_EFFECT_STATS.divine_armor_sword_speed_hide_effect}`)
    player.runCommand(`/effect @s haste 0 0`)
    player.addTag(TAGS.CUSTOM_MAIN_HAND_SWORD)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)
  } else if ((mainhand?.includes("_pickaxe") || mainhand?.includes("_hoe") || mainhand?.includes("_axe") || mainhand?.includes("_shovel"))) {
    if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)) return
    player.runCommand(`/effect @s strength 0 0`)
    player.runCommand(`/effect @s speed 0 0`)
    player.runCommand(`/effect @s haste ${ARMOR_EFFECT_STATS.divine_armor_tools_haste_duration} ${ARMOR_EFFECT_STATS.divine_armor_tools_haste_level} ${ARMOR_EFFECT_STATS.divine_armor_tools_haste_hide_effect}`)
    player.addTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_SWORD)
  } else if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_SWORD)) {
    player.runCommand(`/effect @s strength 0 0`)
    player.runCommand(`/effect @s speed 0 0`)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_SWORD)
  } else if (player.hasTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)) {
    player.runCommand(`/effect @s haste 0 0`)
    player.removeTag(TAGS.CUSTOM_MAIN_HAND_TOOLS)
  }
}

async function cryoArmorSet(player) {
  player.runCommand(`/effect @s water_breathing ${ARMOR_EFFECT_STATS.cryo_armor_water_breathing_duration} ${ARMOR_EFFECT_STATS.cryo_armor_water_breathing_level} ${ARMOR_EFFECT_STATS.cryo_armor_water_breathing_hide_particle_effect}`)
  player.addTag(TAGS.CRYO_ARMOR)
}

async function cryoArmorRemoved(player) {
  player.runCommand(`/effect @s water_breathing 0 0 true`)
  player.removeTag(TAGS.CRYO_ARMOR)
}

async function cryoArmorOnHit(player, victim) {
  player.runCommand(`/effect @s slowness ${ARMOR_EFFECT_STATS.cryo_armor_slowness_duration} ${ARMOR_EFFECT_STATS.cryo_armor_slowness_level} ${ARMOR_EFFECT_STATS.cryo_armor_slowness_hide_particle_effect}`)
}

async function flameArmorSet(player) {
  player.runCommand(`/effect @s fire_resistance ${ARMOR_EFFECT_STATS.flame_armor_fire_resistance_duration} ${ARMOR_EFFECT_STATS.flame_armor_fire_resistance_level} ${ARMOR_EFFECT_STATS.flame_armor_fire_resistance_hide_particle_effect}`)
  player.addTag(TAGS.FLAME_ARMOR)
}

async function flameArmorRemoved(player) {
  player.runCommand(`/effect @s fire_resistance 0 0 true`)
  player.removeTag(TAGS.FLAME_ARMOR)
}

async function flameArmorOnHit(player, victim) {
  player.setOnFire(5, true)
}