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

import net.minecraft.core.GlobalPos;
import net.minecraft.world.level.pathfinder.Path;
import net.minecraft.world.entity.ai.village.poi.PoiType;
import net.minecraft.world.entity.ai.Brain;
import net.minecraft.world.entity.EntityType;
import java.util.Optional;
import net.minecraft.network.protocol.game.DebugPackets;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.server.level.ServerLevel;
import java.util.Map;
import net.minecraft.world.entity.AgableMob;
import com.google.common.collect.ImmutableMap;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.npc.Villager;

public class VillagerMakeLove extends Behavior<Villager> {
    private long birthTimestamp;
    
    public VillagerMakeLove() {
        super(ImmutableMap.<MemoryModuleType<AgableMob>, MemoryStatus>of(MemoryModuleType.BREED_TARGET, MemoryStatus.VALUE_PRESENT, (MemoryModuleType<AgableMob>)MemoryModuleType.VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT), 350, 350);
    }
    
    @Override
    protected boolean checkExtraStartConditions(final ServerLevel zd, final Villager bdp) {
        return this.isBreedingPossible(bdp);
    }
    
    @Override
    protected boolean canStillUse(final ServerLevel zd, final Villager bdp, final long long3) {
        return long3 <= this.birthTimestamp && this.isBreedingPossible(bdp);
    }
    
    @Override
    protected void start(final ServerLevel zd, final Villager bdp, final long long3) {
        final AgableMob aok6 = bdp.getBrain().<AgableMob>getMemory(MemoryModuleType.BREED_TARGET).get();
        BehaviorUtils.lockGazeAndWalkToEachOther(bdp, aok6, 0.5f);
        zd.broadcastEntityEvent(aok6, (byte)18);
        zd.broadcastEntityEvent(bdp, (byte)18);
        final int integer7 = 275 + bdp.getRandom().nextInt(50);
        this.birthTimestamp = long3 + integer7;
    }
    
    @Override
    protected void tick(final ServerLevel zd, final Villager bdp, final long long3) {
        final Villager bdp2 = bdp.getBrain().<Villager>getMemory((MemoryModuleType<Villager>)MemoryModuleType.BREED_TARGET).get();
        if (bdp.distanceToSqr(bdp2) > 5.0) {
            return;
        }
        BehaviorUtils.lockGazeAndWalkToEachOther(bdp, bdp2, 0.5f);
        if (long3 >= this.birthTimestamp) {
            bdp.eatAndDigestFood();
            bdp2.eatAndDigestFood();
            this.tryToGiveBirth(zd, bdp, bdp2);
        }
        else if (bdp.getRandom().nextInt(35) == 0) {
            zd.broadcastEntityEvent(bdp2, (byte)12);
            zd.broadcastEntityEvent(bdp, (byte)12);
        }
    }
    
    private void tryToGiveBirth(final ServerLevel zd, final Villager bdp2, final Villager bdp3) {
        final Optional<BlockPos> optional5 = this.takeVacantBed(zd, bdp2);
        if (!optional5.isPresent()) {
            zd.broadcastEntityEvent(bdp3, (byte)13);
            zd.broadcastEntityEvent(bdp2, (byte)13);
        }
        else {
            final Optional<Villager> optional6 = this.breed(bdp2, bdp3);
            if (optional6.isPresent()) {
                this.giveBedToChild(zd, optional6.get(), optional5.get());
            }
            else {
                zd.getPoiManager().release(optional5.get());
                DebugPackets.sendPoiTicketCountPacket(zd, optional5.get());
            }
        }
    }
    
    @Override
    protected void tick(final ServerLevel zd, final Villager bdp, final long long3) {
        bdp.getBrain().<AgableMob>eraseMemory(MemoryModuleType.BREED_TARGET);
    }
    
    private boolean isBreedingPossible(final Villager bdp) {
        final Brain<Villager> apr3 = bdp.getBrain();
        final Optional<AgableMob> optional4 = apr3.<AgableMob>getMemory(MemoryModuleType.BREED_TARGET).filter(aok -> aok.getType() == EntityType.VILLAGER);
        return optional4.isPresent() && BehaviorUtils.targetIsValid(apr3, MemoryModuleType.BREED_TARGET, EntityType.VILLAGER) && bdp.canBreed() && optional4.get().canBreed();
    }
    
    private Optional<BlockPos> takeVacantBed(final ServerLevel zd, final Villager bdp) {
        return zd.getPoiManager().take(PoiType.HOME.getPredicate(), fu -> this.canReach(bdp, fu), bdp.blockPosition(), 48);
    }
    
    private boolean canReach(final Villager bdp, final BlockPos fu) {
        final Path czf4 = bdp.getNavigation().createPath(fu, PoiType.HOME.getValidRange());
        return czf4 != null && czf4.canReach();
    }
    
    private Optional<Villager> breed(final Villager bdp1, final Villager bdp2) {
        final Villager bdp3 = bdp1.getBreedOffspring((AgableMob)bdp2);
        if (bdp3 == null) {
            return Optional.<Villager>empty();
        }
        bdp1.setAge(6000);
        bdp2.setAge(6000);
        bdp3.setAge(-24000);
        bdp3.moveTo(bdp1.getX(), bdp1.getY(), bdp1.getZ(), 0.0f, 0.0f);
        bdp1.level.addFreshEntity(bdp3);
        bdp1.level.broadcastEntityEvent(bdp3, (byte)12);
        return Optional.<Villager>of(bdp3);
    }
    
    private void giveBedToChild(final ServerLevel zd, final Villager bdp, final BlockPos fu) {
        final GlobalPos gc5 = GlobalPos.of(zd.dimension(), fu);
        bdp.getBrain().<GlobalPos>setMemory(MemoryModuleType.HOME, gc5);
    }
}
