package net.minecraft.world.entity.npc;

import java.util.Iterator;
import net.minecraft.world.level.BlockGetter;
import javax.annotation.Nullable;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.NaturalSpawner;
import net.minecraft.world.entity.SpawnPlacements;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.entity.animal.horse.TraderLlama;
import net.minecraft.world.entity.Entity;
import java.util.Optional;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.chat.Component;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.ai.village.poi.PoiManager;
import net.minecraft.world.entity.ai.village.poi.PoiType;
import net.minecraft.util.Mth;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.server.level.ServerLevel;
import java.util.Random;

public class WanderingTraderSpawner {
    private final Random random;
    private final ServerLevel level;
    private int tickDelay;
    private int spawnDelay;
    private int spawnChance;
    
    public WanderingTraderSpawner(final ServerLevel xd) {
        this.random = new Random();
        this.level = xd;
        this.tickDelay = 1200;
        final LevelData crm3 = xd.getLevelData();
        this.spawnDelay = crm3.getWanderingTraderSpawnDelay();
        this.spawnChance = crm3.getWanderingTraderSpawnChance();
        if (this.spawnDelay == 0 && this.spawnChance == 0) {
            crm3.setWanderingTraderSpawnDelay(this.spawnDelay = 24000);
            crm3.setWanderingTraderSpawnChance(this.spawnChance = 25);
        }
    }
    
    public void tick() {
        if (!this.level.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) {
            return;
        }
        if (--this.tickDelay > 0) {
            return;
        }
        this.tickDelay = 1200;
        final LevelData crm2 = this.level.getLevelData();
        crm2.setWanderingTraderSpawnDelay(this.spawnDelay -= 1200);
        if (this.spawnDelay > 0) {
            return;
        }
        this.spawnDelay = 24000;
        if (!this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
            return;
        }
        final int integer3 = this.spawnChance;
        crm2.setWanderingTraderSpawnChance(this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75));
        if (this.random.nextInt(100) > integer3) {
            return;
        }
        if (this.spawn()) {
            this.spawnChance = 25;
        }
    }
    
    private boolean spawn() {
        final Player ayj2 = this.level.getRandomPlayer();
        if (ayj2 == null) {
            return true;
        }
        if (this.random.nextInt(10) != 0) {
            return false;
        }
        final BlockPos fk3 = ayj2.getCommandSenderBlockPosition();
        final int integer4 = 48;
        final PoiManager asr5 = this.level.getPoiManager();
        final Optional<BlockPos> optional6 = asr5.find(PoiType.MEETING.getPredicate(), fk -> true, fk3, 48, PoiManager.Occupancy.ANY);
        final BlockPos fk4 = optional6.orElse(fk3);
        final BlockPos fk5 = this.findSpawnPositionNear(fk4, 48);
        if (fk5 != null && this.hasEnoughSpace(fk5)) {
            if (this.level.getBiome(fk5) == Biomes.THE_VOID) {
                return false;
            }
            final WanderingTrader ayc9 = EntityType.WANDERING_TRADER.spawn(this.level, null, null, null, fk5, MobSpawnType.EVENT, false, false);
            if (ayc9 != null) {
                for (int integer5 = 0; integer5 < 2; ++integer5) {
                    this.tryToSpawnLlamaFor(ayc9, 4);
                }
                this.level.getLevelData().setWanderingTraderId(ayc9.getUUID());
                ayc9.setDespawnDelay(48000);
                ayc9.setWanderTarget(fk4);
                ayc9.restrictTo(fk4, 16);
                return true;
            }
        }
        return false;
    }
    
    private void tryToSpawnLlamaFor(final WanderingTrader ayc, final int integer) {
        final BlockPos fk4 = this.findSpawnPositionNear(new BlockPos(ayc), integer);
        if (fk4 == null) {
            return;
        }
        final TraderLlama aul5 = EntityType.TRADER_LLAMA.spawn(this.level, null, null, null, fk4, MobSpawnType.EVENT, false, false);
        if (aul5 == null) {
            return;
        }
        aul5.setLeashedTo(ayc, true);
    }
    
    @Nullable
    private BlockPos findSpawnPositionNear(final BlockPos fk, final int integer) {
        BlockPos fk2 = null;
        for (int integer2 = 0; integer2 < 10; ++integer2) {
            final int integer3 = fk.getX() + this.random.nextInt(integer * 2) - integer;
            final int integer4 = fk.getZ() + this.random.nextInt(integer * 2) - integer;
            final int integer5 = this.level.getHeight(Heightmap.Types.WORLD_SURFACE, integer3, integer4);
            final BlockPos fk3 = new BlockPos(integer3, integer5, integer4);
            if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, this.level, fk3, EntityType.WANDERING_TRADER)) {
                fk2 = fk3;
                break;
            }
        }
        return fk2;
    }
    
    private boolean hasEnoughSpace(final BlockPos fk) {
        for (final BlockPos fk2 : BlockPos.betweenClosed(fk, fk.offset(1, 2, 1))) {
            if (!this.level.getBlockState(fk2).getCollisionShape(this.level, fk2).isEmpty()) {
                return false;
            }
        }
        return true;
    }
}
