import { world, ItemStack, Direction, system, Player } from '@minecraft/server';

export const itemList = {
    "ph_wild:nature_journal": {
      spawn_entity: "ph_wild:nature_journal",
      replace_item: "air",
    },
    "ph_wild:bucket_jellyfish": {
        spawn_entity: "ph_wild:jellyfish",
        set_block: "flowing_water",
        replace_item: "bucket",
        play_sound: "bucket.empty_fish",
    },
    "ph_wild:bucket_octopus": {
      spawn_entity: "ph_wild:octopus",
      set_block: "flowing_water",
      replace_item: "bucket",
      play_sound: "bucket.empty_fish",
    },
    "ph_wild:jar_butterfly": {
      spawn_entity: "ph_wild:butterfly",
      replace_item: "ph_wild:jar_empty",
      play_sound: "bucket.fill_powder_snow",
    },
    "ph_wild:jar_dragonfly": {
      spawn_entity: "ph_wild:dragonfly",
      replace_item: "ph_wild:jar_empty",
      play_sound: "bucket.fill_powder_snow",
    },
    "ph_wild:jar_hamster": {
      spawn_entity: "ph_wild:hamster",
      replace_item: "ph_wild:jar_empty",
      play_sound: "bucket.fill_powder_snow",
    },
    "ph_wild:jar_lizard": {
      spawn_entity: "ph_wild:lizard",
      replace_item: "ph_wild:jar_empty",
      play_sound: "bucket.fill_powder_snow",
    },
    "ph_wild:jar_snake": {
      spawn_entity: "ph_wild:snake",
      replace_item: "ph_wild:jar_empty",
      play_sound: "bucket.fill_powder_snow",
    },

    "ph_wild:animal_fat": {
      block_interactible: true,
      effects: [
        { type: "nausea", duration: 500, amplifier: 0, probability: 0.1, particles: false }
      ]
    },
    "ph_wild:strength_elixir": {
      block_interactible: true,
      replace_item: "glass_bottle",
      effects: [
        { type: "strength", duration: 3600, amplifier: 3, probability: 1, particles: true },
        { type: "regeneration", duration: 800, amplifier: 1, probability: 0.1, particles: true }
      ]
    },
    "ph_wild:potion_of_stingray_venom": {
      block_interactible: true,
      replace_item: "glass_bottle",
      effects: [
        { type: "fatal_poison", duration: 400, amplifier: 3, probability: 1, particles: true },
        { type: "nausea", duration: 200, amplifier: 0, probability: 1, particles: false }
      ]
    },
    "ph_wild:potion_of_stingray_venom.splash": {
      block_interactible: true,
      replace_item: "air",
      projectile: "ph_wild:custom_splash_potion",
      launch_sound: "random.bow",
      hit_sound: "random.glass",
      speed: 0.5,
      effects: [
        { type: "fatal_poison", duration: 400, amplifier: 3, probability: 1, particles: true },
        { type: "nausea", duration: 200, amplifier: 0, probability: 1, particles: false }
      ]
    },
    "ph_wild:potion_of_stingray_venom.lingering": {
      block_interactible: true,
      replace_item: "air",
      projectile: "ph_wild:custom_splash_potion",
      launch_sound: "random.bow",
      hit_sound: "random.glass",
      speed: 0.5,
      effects: [
        { type: "fatal_poison", duration: 200, amplifier: 3, probability: 1, particles: true },
        { type: "nausea", duration: 100, amplifier: 0, probability: 1, particles: false }
      ]
    },
    "ph_wild:banana_peel": {
      block_interactible: true,
      projectile: "ph_wild:banana_peel",
      launch_sound: "random.bow",
      hit_sound: "random.bow",
      speed: 0.75,
      effects: [
        { type: "nausea", duration: 300, amplifier: 0, probability: 1, particles: true }
      ]
    },

    "ph_wild:venomous_stinger": {
        block_interactible: true,
        effects: [
          { type: "poison", duration: 40, amplifier: 0, probability: 1, particles: true }
        ]
    },
    "ph_wild:venomous_dagger": {
        block_interactible: true,
        effects: [
          { type: "poison", duration: 100, amplifier: 1, probability: 1, particles: true }
        ]
    },

    "ph_wild:tortoise_chestplate": {
        block_interactible: true,
        effects: [
          { type: "slowness", duration: 300, amplifier: 1, probability: 1, particles: false },
          { type: "resistance", duration: 300, amplifier: 2, probability: 1, particles: false }
        ]
    },
    "ph_wild:claw_necklace": {
        block_interactible: true,
        effects: [
          { type: "speed", duration: 300, amplifier: 1, probability: 1, particles: false },
          { type: "strength", duration: 300, amplifier: 1, probability: 1, particles: false },
          { type: "hunger", duration: 300, amplifier: 0, probability: 1, particles: false },
          { type: "night_vision", duration: 300, amplifier: 0, probability: 1, particles: false }
        ]
    },

    "ph_wild:jar_empty": {
        block_interactible: true,
        play_sound: "bucket.fill_powder_snow",
        entity_to_item_ID: {
            "ph_wild:butterfly": "ph_wild:jar_butterfly",
            "ph_wild:dragonfly": "ph_wild:jar_dragonfly",
            "ph_wild:hamster": "ph_wild:jar_hamster",
            "ph_wild:lizard": "ph_wild:jar_lizard",
            "ph_wild:snake": "ph_wild:jar_snake",
        }
    },
    "minecraft:water_bucket": {
        block_interactible: true,
        play_sound: "bucket.fill_fish",
        entity_to_item_ID: {
            "ph_wild:jellyfish": "ph_wild:bucket_jellyfish",
            "ph_wild:octopus": "ph_wild:bucket_octopus",
        }
    },
};


world.beforeEvents.itemUseOn.subscribe((BlockInteract) => {
    const { block, blockFace, itemStack, source } = BlockInteract;

    const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

    if (!itemData) return;

    if (!itemData.block_interactible) {
      const directions = {
          [Direction.Down]: block.below(),
          [Direction.East]: block.east(),
          [Direction.North]: block.north(),
          [Direction.South]: block.south(),
          [Direction.Up]: block.above(),
          [Direction.West]: block.west()
      };
  
      const blockPlacementLocation = block.isLiquid ? block.below(0) : directions[blockFace];
  
      const isOccupied = !blockPlacementLocation.isAir && !blockPlacementLocation.isLiquid;
  
      if (isOccupied) {
          system.run(() => {
            source.onScreenDisplay.setActionBar('§4Invalid placement location');
            source.onScreenDisplay.setActionBar('');
          });
          BlockInteract.cancel = true;
          return;
      };
    };

    if (itemData.spawn_entity) {
      const StrData = itemStack.getDynamicProperty('ph_wild:item_data');

      if (StrData) {
          const itemSavedData = JSON.parse(StrData);
          if (itemSavedData.entityOwnerId && itemSavedData.entityOwnerId !== source.id) {
            system.run(() => {
              source.onScreenDisplay.setActionBar('§4Only the owner can place this entity');
              source.onScreenDisplay.setActionBar('');
            });
            BlockInteract.cancel = true;
          };
      };
    }
});

world.beforeEvents.worldInitialize.subscribe((initEvent) => {
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:custom_projectile", {
      onUse(event) {
          const { itemStack, source } = event;

          const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];
          const { x: sourceX, y: sourceY, z: sourceZ } = source.location;
          const direction = source.getViewDirection();

          const right = {
              x: -direction.z,
              y: 0,
              z: direction.x,
          };

          const offset = { x: 0, y: 1.6, z: 0 };
          const angle = { pitch: 20, yaw: 0 };

          const pitchRad = (Math.PI / 180) * angle.pitch;
          const yawRad = (Math.PI / 180) * angle.yaw;

          const spawnLocation = {
            x: sourceX + direction.x * offset.x + right.x * offset.z,
            y: sourceY + offset.y,
            z: sourceZ + direction.z * offset.x + right.z * offset.z,
          };

          const adjustedDirection = {
            x: direction.x * Math.cos(yawRad) - direction.z * Math.sin(yawRad),
            y: direction.y + Math.sin(pitchRad),
            z: direction.x * Math.sin(yawRad) + direction.z * Math.cos(yawRad)
          };

          const magnitude = Math.sqrt(
              adjustedDirection.x ** 2 +
              adjustedDirection.y ** 2 +
              adjustedDirection.z ** 2
          );

          const velocity = {
            x: (adjustedDirection.x / magnitude) * itemData.speed,
            y: (adjustedDirection.y / magnitude) * itemData.speed,
            z: (adjustedDirection.z / magnitude) * itemData.speed
          };

          const projectile = source.dimension.spawnEntity(itemData.projectile, spawnLocation);

          const projectileData = {
            effects: itemData.effects,
            hit_sound: itemData.hit_sound
          };
          const storeStrData = JSON.stringify(projectileData);
          projectile.setDynamicProperty('ph_wild:projectile_data', storeStrData);

          source.dimension.playSound(itemData.launch_sound, source.location, { volume: 0.5, pitch: 0.5 });

          const projectileComp = projectile.getComponent('minecraft:projectile');
          const projectileVar = projectile.getComponent('minecraft:mark_variant');
          projectileVar.value = 18;
          if (projectileComp) {
              projectileComp.owner = source;
              projectileComp.gravity = -0.05;
              projectileComp.airInertia = 1;
          };
          projectile.applyImpulse(velocity);
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:consume_effect", {
      onConsume(event) {
          const { itemStack, source } = event;

          const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

          itemData.effects.forEach(effect => {
            if (Math.random() <= effect.probability) {
              source.addEffect(effect.type, effect.duration, {
                  amplifier: effect.amplifier,
                  showParticles: effect.particles,
              });
            }
          });
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:hit_effect", {
      onHitEntity(event) {
          const { itemStack, attackingEntity, hadEffect, hitEntity } = event;

          const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

          itemData.effects.forEach(effect => {
            hitEntity.addEffect(effect.type, effect.duration, {
                  amplifier: effect.amplifier,
                  showParticles: effect.particles,
              });
          });
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:spawn_entity", {
      onUseOn(event) {
        const { block, blockFace, itemStack, source } = event;

        const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

        const isLiquid = block.typeId === "minecraft:water" || block.typeId === "minecraft:lava";

        const blockCenter = { x: block.location.x + 0.5, y: block.location.y + 0.5, z: block.location.z + 0.5 };

        const offsets = {
            [Direction.Up]:    { x: 0, y: 0.5, z: 0 },
            [Direction.Down]:  { x: 0, y: -1.5, z: 0 },
            [Direction.North]: { x: 0, y: 0, z: -1 },
            [Direction.South]: { x: 0, y: 0, z: 1 },
            [Direction.East]:  { x: 1, y: 0, z: 0 },
            [Direction.West]:  { x: -1, y: 0, z: 0 }
        };

        let spawnLocation = {
            x: blockCenter.x + (offsets[blockFace]?.x),
            y: blockCenter.y + (offsets[blockFace]?.y),
            z: blockCenter.z + (offsets[blockFace]?.z)
        };

        if (isLiquid) spawnLocation.y -= 1;

        const entityRotation = {
            x: 0,
            y: Math.atan2(source.location.z - spawnLocation.z, source.location.x - spawnLocation.x) * (180 / Math.PI) - 90
        };

        const entity = source.dimension.spawnEntity(itemData.spawn_entity, spawnLocation);

        const StrData = itemStack.getDynamicProperty('ph_wild:item_data');

        if (StrData) {
            const itemSavedData = JSON.parse(StrData);

            if (itemSavedData.entityName) {
                entity.nameTag = `${itemSavedData.entityName}`;
            };
            if (itemSavedData.entityHealth) {
                entity.getComponent("health").setCurrentValue(itemSavedData.entityHealth);
            };
            if (itemSavedData.entityBaby) {
                entity.triggerEvent("baby");
            } else {
                entity.triggerEvent("adult");
            };
            if (itemSavedData.entityTamed) {
                entity.getComponent("tameable").tame(source);
            };
            if (itemSavedData.currentPage) {
                entity.setProperty('ph_wild:current_page', itemSavedData.currentPage);
            };
        };

        const itemNumberString = itemStack.typeId.split('_').pop();
        const itemNumber = parseInt(itemNumberString, 10);

        if (itemNumber) {
            entity.setProperty('ph_wild:skin', itemNumber);
        }

        entity.setRotation(entityRotation);
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:set_block", {
      onUseOn(event) {
        const { block, blockFace, itemStack } = event;

        const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

        const directions = {
            [Direction.Down]: block.below(),
            [Direction.East]: block.east(),
            [Direction.North]: block.north(),
            [Direction.South]: block.south(),
            [Direction.Up]: block.above(),
            [Direction.West]: block.west()
        };

        const blockPlacementLocation = block.isLiquid ? block.below(0) : directions[blockFace];

        blockPlacementLocation.setType(itemData.set_block);
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:play_sound", {
      onUseOn(event) {
        const { block, itemStack, source } = event;

        const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

        source.dimension.playSound(itemData.play_sound, block.location);
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:decrease_item_stack.onUse", {
      onUse(event) {
        const { itemStack, source } = event;

        const inv = source.getComponent("inventory").container;
        const selectedSlot = source.selectedSlotIndex;
        const currentItem = inv.getItem(selectedSlot);
    
        if (currentItem && currentItem.amount > 0 && !source.matches({ gameMode: 'creative' })) {
            if (currentItem.amount > 1) {
                currentItem.amount -= 1;
                inv.setItem(selectedSlot, currentItem);
            } else {
                inv.setItem(selectedSlot, undefined);
            }
        };
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:replace_item.onUse", {
      onUse(event) {
        const { itemStack, source } = event;
        const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

        if (!source.matches({ gameMode: 'creative' })) {
          const replaceItem = new ItemStack(itemData.replace_item);
          const inv = source.getComponent("inventory").container;
          inv.setItem(source.selectedSlotIndex, replaceItem);
        }
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:replace_item.onUseOn", {
      onUseOn(event) {
        const { itemStack, source } = event;
        const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

        if (!source.matches({ gameMode: 'creative' })) {
          const replaceItem = new ItemStack(itemData.replace_item);
          const inv = source.getComponent("inventory").container;
          inv.setItem(source.selectedSlotIndex, replaceItem);
        }
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:replace_item.onConsume", {
      onConsume(event) {
        const { itemStack, source } = event;
        const itemData = itemList[itemStack?.typeId.replace(/_\d+$/, '')];

        if (!source.matches({ gameMode: 'creative' })) {
          const replaceItem = new ItemStack(itemData.replace_item);
          const inv = source.getComponent("inventory").container;
          inv.setItem(source.selectedSlotIndex, replaceItem);
        }
      }
  });
  initEvent.itemComponentRegistry.registerCustomComponent("ph_wild:maintain_durability", {
      onBeforeDurabilityDamage(event) {
        const { itemStack, source } = event;
        event.durabilityDamage -= 2;
      }
  });
});

export const Dimensions = {
  Overworld: world.getDimension("overworld"),
  Nether: world.getDimension("nether"),
  End: world.getDimension("the_end")
};

class equipmentEffect {
  static loadedEntities = [];
  
  static playerLoaded(entity) {
    this.loadedEntities.push(entity);
  }
  
  static equipmentEffectUpdater() {
    const loadedEntities = this.loadedEntities;
    for (let i = loadedEntities.length - 1; i >= 0; i--) {
      const entity = loadedEntities[i];

      const equipment = entity.getComponent("equippable");
      if (!equipment) { continue; }

      const equipmentSlots = {
        Offhand: entity.getComponent("equippable").getEquipment("Offhand"),
        Head: entity.getComponent("equippable").getEquipment("Head"),
        Chest: entity.getComponent("equippable").getEquipment("Chest"),
        Legs: entity.getComponent("equippable").getEquipment("Legs"),
        Feet: entity.getComponent("equippable").getEquipment("Feet")
      };

      for (const [itemData, data] of Object.entries(itemList)) {
        Object.entries(equipmentSlots).forEach(([slotName, slot]) => {
          try {
            if (!slot) return;
            if (slot?.typeId === itemData) {
              data.effects.forEach(effect => {
                entity.addEffect(effect.type, effect.duration, {
                  amplifier: effect.amplifier,
                  showParticles: effect.particles
                });
              });
            }
          } catch (error) {
            console.error(`Error applying effect for ${slotName}:`, error);
          }
        });
      }
    }
  }
}

world.afterEvents.playerSpawn.subscribe(({ initialSpawn, player }) => { if (initialSpawn) equipmentEffect.playerLoaded(player); });

system.run(() => {
  const dimensions = Object.values(Dimensions);
  dimensions.forEach(dimension => {
    const entities = dimension.getEntities();
    entities.forEach(entity => equipmentEffect.playerLoaded(entity));
  });
});

system.runInterval(() => {
  equipmentEffect.equipmentEffectUpdater();
}, 40);


world.afterEvents.playerInteractWithEntity.subscribe((itemInteract) => {
    const { itemStack, player, target } = itemInteract;

    const itemData = itemList[itemStack?.typeId];
    if (itemData) {
      const entityToItemID = itemData?.entity_to_item_ID?.[target?.typeId];
      if (!entityToItemID) return;

      const healthComponent = target.getComponent("health");
      const tameableComponent = target.getComponent("tameable");
      const name = target?.nameTag;
      const currentHealth = healthComponent?.currentValue;
      const maxHealth = healthComponent?.defaultValue;
      const isBaby = target.hasComponent("minecraft:is_baby");
      const isTamed = target.hasComponent("minecraft:is_tamed");
      const ownerName = tameableComponent?.tamedToPlayer?.nameTag;
      const ownerId = tameableComponent?.tamedToPlayerId;
      const skinId = target.getProperty('ph_wild:skin');
  
      const storedData = {
          entityName: name,
          entityHealth: currentHealth,
          entityBaby: isBaby,
          entityTamed: isTamed,
          entityOwnerId: ownerId,
      }
  
      const storeStrData = JSON.stringify(storedData);
  
      const replaceItem = new ItemStack(`${entityToItemID}_${skinId}`);
      replaceItem.setDynamicProperty('ph_wild:item_data', storeStrData);
  
      const lore = [
        `§r§7Name: ${name || 'Unknown'}`,
        `§r§7Health: ${currentHealth}/${maxHealth}`,
        `§r§7Age: ${isBaby ? 'Baby' : 'Adult'}`,
      ];
  
      if (ownerName) {
        lore.push(`§r§7Owner: ${ownerName}`);
      }
  
      replaceItem.setLore(lore);
  
      const inv = player.getComponent("inventory").container;
      const selectedSlot = player.selectedSlotIndex;
      const currentItem = inv.getItem(selectedSlot);
  
      if (currentItem && currentItem.amount > 0 && !player.matches({ gameMode: 'creative' })) {
          if (currentItem.amount > 1) {
              currentItem.amount -= 1;
              inv.setItem(selectedSlot, currentItem);
  
              inv.addItem(replaceItem);
          } else {
              inv.setItem(selectedSlot, replaceItem);
          }
      };
  
      if (player.matches({ gameMode: 'creative' })) {
          inv.addItem(replaceItem);
      };
  
      target.dimension.playSound(itemData.play_sound, target.location);
  
      target.remove();
    };
});