import {
  world,
  BlockTypes,
  system,
  EntityComponentTypes,
  EquipmentSlot,
} from "@minecraft/server";
import {
  checkBuddyProperties,
  getBuddyFoodIndex,
} from "arcedge/bap/buddy/getBuddyPart";

const frozenBlocks = new Map();
const buddyState = new WeakMap();

world.afterEvents.entitySpawn.subscribe((data) => {
  const water_projectile = data.entity
})

system.runInterval(() => {
  const overworld = world.getDimension("overworld");

  for (const water_projectile of overworld.getEntities({ type: "arcedge_bap:elephant_water_projectile" })) {
    water_projectile.dimension.spawnParticle("arcedge_bap:water_spout", water_projectile.location)
  }

  for (const player of world.getPlayers()) {
    const buddies = player.dimension.getEntities({
      type: "arcedge_bap:buddy",
      maxDistance: 8,
      location: player.location,
    });

    if (!buddies || buddies.length === 0) continue;

    const equippedItem = player.getComponent(EntityComponentTypes.Equippable);
    const slotMainHand = equippedItem.getEquipment(EquipmentSlot.Mainhand);

    const holdingFoodItem =
      (getBuddyFoodIndex(slotMainHand?.typeId)?.index ?? -1) + 1;

    for (const buddy of buddies) {
      const isAllowedToSit =
        !(holdingFoodItem && checkBuddyProperties(holdingFoodItem, buddy)) &&
        !buddy.isInWater &&
        slotMainHand?.typeId != "minecraft:name_tag" &&
        slotMainHand?.typeId != "arcedge_bap:buddy_stuffing" &&
        slotMainHand?.typeId != "minecraft:lead" &&
        !buddy.getComponent("minecraft:leashable").isLeashed &&
        buddy.getComponent("minecraft:tameable").tamedToPlayer === player;

      const lastState = buddyState.get(buddy);

      const isSneakingAction =
        player.isSneaking && checkBuddyProperties(15, buddy);

      if (isSneakingAction) {
        buddy.triggerEvent("arcedge_bap:buddy_deny_sitting");
        buddy.setProperty("arcedge_bap:sleeping", false);
        buddy.triggerEvent("arcedge_bap:head_and_body_rotation_enabled");
        buddyState.set(buddy, false);
        continue;
      }

      if (isAllowedToSit !== lastState) {
        if (!isAllowedToSit) {
          buddy.triggerEvent("arcedge_bap:buddy_deny_sitting");
          buddy.setProperty("arcedge_bap:sleeping", false);
          buddy.triggerEvent("arcedge_bap:head_and_body_rotation_enabled");
        } else if (isAllowedToSit) {
          buddy.triggerEvent("arcedge_bap:buddy_allow_sitting");
        }
        buddyState.set(buddy, isAllowedToSit);
      }
    }
  }
});

function randomSpawnDelay() {
  return Math.floor(Math.random() * (36000 - 18000) + 18000);
}

function randomOffset(radius = 20) {
  const x = Math.floor(Math.random() * radius * 2) - radius;
  const z = Math.floor(Math.random() * radius * 2) - radius;
  return { x, z };
}

let buddyTraderSpawnTimer = randomSpawnDelay();


system.runInterval(() => {
  const overworld = world.getDimension("overworld");

  for (const buddy of overworld.getEntities({ type: "arcedge_bap:buddy" })) {
    if (checkBuddyProperties(2, buddy)) dolphinAbility(buddy, overworld);
    if (checkBuddyProperties(4, buddy)) flamingoAbility(buddy, overworld);
    if (checkBuddyProperties(6, buddy)) hermitCrabAbility(buddy);
    if (checkBuddyProperties(10, buddy)) pantherAbility(buddy);
    if (checkBuddyProperties(12, buddy)) polarBearAbility(buddy, overworld);
    if (checkBuddyProperties(13, buddy)) teddyBearAbility(buddy, overworld);
    if (checkBuddyProperties(16, buddy)) wolfAbility(buddy, overworld);

    if (checkBuddyProperties(1, buddy) || checkBuddyProperties(2, buddy)) {
      if (buddy.isInWater) {
        buddy.triggerEvent("arcedge_bap:buddy_is_amphibious_on_water");
      } else if (!buddy.isInWater) {
        buddy.triggerEvent("arcedge_bap:buddy_is_amphibious_on_land");
      }
    }
  }

  const now = system.currentTick;
  for (const [key, data] of frozenBlocks.entries()) {
    if (now - data.lastSeen > 200) {
      const block = overworld.getBlock({ x: data.x, y: data.y, z: data.z });
      if (block?.typeId === "minecraft:ice")
        block.setType(BlockTypes.get("minecraft:water"));
      frozenBlocks.delete(key);
    }
  }
}, 10);


system.runInterval(() => {
  buddyTraderSpawnTimer -= 20;
  if (buddyTraderSpawnTimer > 0) return;

  const players = world.getPlayers();
  if (players.length === 0) return;

  const player = players[Math.floor(Math.random() * players.length)];

  const offset = randomOffset(20);
  const spawnLocation = {
    x: player.location.x + offset.x,
    y: player.location.y,
    z: player.location.z + offset.z,
  };

  const buddyTrader = player.dimension.spawnEntity(
    "arcedge_bap:buddy_trader",
    spawnLocation
  );

  buddyTrader.dimension.spawnParticle("arcedge_bap:appear", {
    x: buddyTrader.location.x,
    y: buddyTrader.location.y + 1,
    z: buddyTrader.location.z,
  });
  
  world.sendMessage([
    {
      translate: "arcedge_bap.buddy_trader.summon",
    },
  ]);

  if (
    player.getDynamicProperty("first_buddy_trader_interact_default") == false
  ) {
    player.setDynamicProperty("first_buddy_trader_interact_default", true);
    system.runTimeout(() => {
          player.sendMessage([
      {
        translate: "arcedge_bap.buddy_trader.summon_tip",
        with: [":_input_key.sneak:", ":_input_key.use:"],
      },
    ]);
    }, 80)
  }

  buddyTraderSpawnTimer = randomSpawnDelay();
  
}, 20);

let snoreToggle = true;

function playSnore() {
  const dimensions = [
    world.getDimension("overworld"),
    world.getDimension("nether"),
    world.getDimension("the_end"),
  ];

  for (const dimension of dimensions) {
    const buddies = dimension.getEntities({ type: "arcedge_bap:buddy" });

    for (const buddy of buddies) {
      if(!buddy.getProperty("arcedge_bap:sleeping")) continue
      const sound = snoreToggle
        ? "arcedge_bap.buddy.sleep_in"
        : "arcedge_bap.buddy.sleep_out";

      dimension.playSound(sound, buddy.location);
    }
  }

  snoreToggle = !snoreToggle;

  system.runTimeout(playSnore, 20);
}

system.runTimeout(playSnore, 20);

function polarBearAbility(buddy, overworld) {
  const baseY = Math.floor(buddy.location.y - 1);

  for (let dx = -3; dx <= 3; dx++) {
    for (let dz = -3; dz <= 3; dz++) {
      const x = Math.floor(buddy.location.x + dx);
      const z = Math.floor(buddy.location.z + dz);

      const block = overworld.getBlock({ x, y: baseY, z });
      const blockAbove = overworld.getBlock({ x, y: baseY + 1, z });

      if (block?.typeId === "minecraft:water" && blockAbove?.isAir) {
        block.setType(BlockTypes.get("minecraft:ice"));
      }

      if (block?.typeId === "minecraft:ice") {
        frozenBlocks.set(`${x},${baseY},${z}`, {
          x,
          y: baseY,
          z,
          lastSeen: system.currentTick,
        });
      }
    }
  }
}

function wolfAbility(buddy, overworld) {
  const nearbyWolves = overworld.getEntities({
    type: "minecraft:wolf",
    location: buddy.location,
    maxDistance: 15,
  });

  for (const target of nearbyWolves) {
    if (target.id === "minecraft:wolf") continue;

    target.addEffect("speed", 100, { amplifier: 3, showParticles: true });
    target.addEffect("strength", 100, { amplifier: 2, showParticles: true });
  }
}

function pantherAbility(buddy) {
  if (buddy.isFalling || !buddy.isOnGround) {
    buddy.addEffect("strength", 40, { amplifier: 3, showParticles: false });
  }
}

function hermitCrabAbility(buddy) {
  if (buddy.getProperty("arcedge_bap:hermit_crab_shell_size") > 0) {
    buddy.addEffect("resistance", 20, {
      amplifier: 3 * buddy.getProperty("arcedge_bap:hermit_crab_shell_size"),
      showParticles: false,
    });
  }
}

function teddyBearAbility(buddy, overworld) {
  const nearbyPlayers = overworld.getEntities({
    type: "minecraft:player",
    location: buddy.location,
    maxDistance: 5,
  });

  for (const target of nearbyPlayers) {
    if (target.id === "minecraft:player") continue;

    target.addEffect("resistance", 210, { amplifier: 3, showParticles: false });
  }
}

function dolphinAbility(buddy, overworld) {
  const nearbyPlayers = overworld.getEntities({
    type: "minecraft:player",
    location: buddy.location,
    maxDistance: 25,
  });

  for (const target of nearbyPlayers) {
    if (target.id === "minecraft:player") continue;

    if (target.isInWater == true) {
      target.addEffect("water_breathing", 210, {
        amplifier: 1,
        showParticles: false,
      });
    }
  }
}

function flamingoAbility(buddy, overworld) {
  const nearbyPlayers = overworld.getEntities({
    type: "minecraft:player",
    location: buddy.location,
    maxDistance: 10,
  });

  for (const target of nearbyPlayers) {
    if (target.id === "minecraft:player") continue;

    if (target.isInWater == true) {
      target.addEffect("regeneration", 20, {
        amplifier: 1,
        showParticles: false,
      });
    }
  }
}
