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

import javax.annotation.Nullable;
import net.minecraft.core.Vec3i;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.monster.Zombie;
import net.minecraft.world.entity.player.Player;
import java.util.Iterator;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.CustomSpawner;

public class VillageSiege implements CustomSpawner {
    private boolean hasSetupSiege;
    private State siegeState;
    private int zombiesToSpawn;
    private int nextSpawnTime;
    private int spawnX;
    private int spawnY;
    private int spawnZ;
    
    public VillageSiege() {
        this.siegeState = State.SIEGE_DONE;
    }
    
    @Override
    public int tick(final ServerLevel zd, final boolean boolean2, final boolean boolean3) {
        if (zd.isDay() || !boolean2) {
            this.siegeState = State.SIEGE_DONE;
            this.hasSetupSiege = false;
            return 0;
        }
        final float float5 = zd.getTimeOfDay(0.0f);
        if (float5 == 0.5) {
            this.siegeState = ((zd.random.nextInt(10) == 0) ? State.SIEGE_TONIGHT : State.SIEGE_DONE);
        }
        if (this.siegeState == State.SIEGE_DONE) {
            return 0;
        }
        if (!this.hasSetupSiege) {
            if (!this.tryToSetupSiege(zd)) {
                return 0;
            }
            this.hasSetupSiege = true;
        }
        if (this.nextSpawnTime > 0) {
            --this.nextSpawnTime;
            return 0;
        }
        this.nextSpawnTime = 2;
        if (this.zombiesToSpawn > 0) {
            this.trySpawn(zd);
            --this.zombiesToSpawn;
        }
        else {
            this.siegeState = State.SIEGE_DONE;
        }
        return 1;
    }
    
    private boolean tryToSetupSiege(final ServerLevel zd) {
        for (final Player bec4 : zd.players()) {
            if (!bec4.isSpectator()) {
                final BlockPos fu5 = bec4.blockPosition();
                if (!zd.isVillage(fu5)) {
                    continue;
                }
                if (zd.getBiome(fu5).getBiomeCategory() == Biome.BiomeCategory.MUSHROOM) {
                    continue;
                }
                for (int integer6 = 0; integer6 < 10; ++integer6) {
                    final float float7 = zd.random.nextFloat() * 6.2831855f;
                    this.spawnX = fu5.getX() + Mth.floor(Mth.cos(float7) * 32.0f);
                    this.spawnY = fu5.getY();
                    this.spawnZ = fu5.getZ() + Mth.floor(Mth.sin(float7) * 32.0f);
                    if (this.findRandomSpawnPos(zd, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)) != null) {
                        this.nextSpawnTime = 0;
                        this.zombiesToSpawn = 20;
                        break;
                    }
                }
                return true;
            }
        }
        return false;
    }
    
    private void trySpawn(final ServerLevel zd) {
        final Vec3 dem3 = this.findRandomSpawnPos(zd, new BlockPos(this.spawnX, this.spawnY, this.spawnZ));
        if (dem3 == null) {
            return;
        }
        Zombie bcu4;
        try {
            bcu4 = new Zombie(zd);
            bcu4.finalizeSpawn(zd, zd.getCurrentDifficultyAt(bcu4.blockPosition()), MobSpawnType.EVENT, null, null);
        }
        catch (Exception exception5) {
            exception5.printStackTrace();
            return;
        }
        bcu4.moveTo(dem3.x, dem3.y, dem3.z, zd.random.nextFloat() * 360.0f, 0.0f);
        zd.addFreshEntity(bcu4);
    }
    
    @Nullable
    private Vec3 findRandomSpawnPos(final ServerLevel zd, final BlockPos fu) {
        for (int integer4 = 0; integer4 < 10; ++integer4) {
            final int integer5 = fu.getX() + zd.random.nextInt(16) - 8;
            final int integer6 = fu.getZ() + zd.random.nextInt(16) - 8;
            final int integer7 = zd.getHeight(Heightmap.Types.WORLD_SURFACE, integer5, integer6);
            final BlockPos fu2 = new BlockPos(integer5, integer7, integer6);
            if (zd.isVillage(fu2)) {
                if (Monster.checkMonsterSpawnRules(EntityType.ZOMBIE, zd, MobSpawnType.EVENT, fu2, zd.random)) {
                    return Vec3.atBottomCenterOf(fu2);
                }
            }
        }
        return null;
    }
    
    enum State {
        SIEGE_CAN_ACTIVATE, 
        SIEGE_TONIGHT, 
        SIEGE_DONE;
    }
}
