package net.minecraft.world.entity.ai.sensing;

import net.minecraft.world.entity.monster.Drowned;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import java.util.List;
import java.util.function.Predicate;
import java.util.Optional;
import net.minecraft.server.level.ServerLevel;
import com.google.common.collect.ImmutableSet;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import java.util.Set;
import net.minecraft.world.entity.EntityType;
import com.google.common.collect.ImmutableMap;
import net.minecraft.world.entity.LivingEntity;

public class VillagerHostilesSensor extends Sensor<LivingEntity> {
    private static final ImmutableMap<EntityType<?>, Float> ACCEPTABLE_DISTANCE_FROM_HOSTILES;
    
    @Override
    public Set<MemoryModuleType<?>> requires() {
        return ImmutableSet.of(MemoryModuleType.NEAREST_HOSTILE);
    }
    
    @Override
    protected void doTick(final ServerLevel zd, final LivingEntity aoy) {
        aoy.getBrain().<LivingEntity>setMemory(MemoryModuleType.NEAREST_HOSTILE, this.getNearestHostile(aoy));
    }
    
    private Optional<LivingEntity> getNearestHostile(final LivingEntity aoy) {
        return this.getVisibleEntities(aoy).<LivingEntity>flatMap(list -> list.stream().filter(this::isHostile).filter(aoy2 -> this.isClose(aoy, aoy2)).min((aoy2, aoy3) -> this.compareMobDistance(aoy, aoy2, aoy3)));
    }
    
    private Optional<List<LivingEntity>> getVisibleEntities(final LivingEntity aoy) {
        return aoy.getBrain().<List<LivingEntity>>getMemory(MemoryModuleType.VISIBLE_LIVING_ENTITIES);
    }
    
    private int compareMobDistance(final LivingEntity aoy1, final LivingEntity aoy2, final LivingEntity aoy3) {
        return Mth.floor(aoy2.distanceToSqr(aoy1) - aoy3.distanceToSqr(aoy1));
    }
    
    private boolean isClose(final LivingEntity aoy1, final LivingEntity aoy2) {
        final float float4 = VillagerHostilesSensor.ACCEPTABLE_DISTANCE_FROM_HOSTILES.get(aoy2.getType());
        return aoy2.distanceToSqr(aoy1) <= float4 * float4;
    }
    
    private boolean isHostile(final LivingEntity aoy) {
        return VillagerHostilesSensor.ACCEPTABLE_DISTANCE_FROM_HOSTILES.containsKey(aoy.getType());
    }
    
    static {
        ACCEPTABLE_DISTANCE_FROM_HOSTILES = ImmutableMap.<EntityType<Drowned>, Float>builder().put(EntityType.DROWNED, 8.0f).put((EntityType<Drowned>)EntityType.EVOKER, 12.0f).put((EntityType<Drowned>)EntityType.HUSK, 8.0f).put((EntityType<Drowned>)EntityType.ILLUSIONER, 12.0f).put((EntityType<Drowned>)EntityType.PILLAGER, 15.0f).put((EntityType<Drowned>)EntityType.RAVAGER, 12.0f).put((EntityType<Drowned>)EntityType.VEX, 8.0f).put((EntityType<Drowned>)EntityType.VINDICATOR, 10.0f).put((EntityType<Drowned>)EntityType.ZOGLIN, 10.0f).put((EntityType<Drowned>)EntityType.ZOMBIE, 8.0f).put((EntityType<Drowned>)EntityType.ZOMBIE_VILLAGER, 8.0f).build();
    }
}
