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

import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.BoneMealItem;
import net.minecraft.core.Position;
import net.minecraft.world.entity.ai.memory.WalkTarget;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.CropBlock;
import net.minecraft.core.Vec3i;
import net.minecraft.world.item.Items;
import net.minecraft.server.level.ServerLevel;
import java.util.Map;
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.core.BlockPos;
import java.util.Optional;
import net.minecraft.world.entity.npc.Villager;

public class UseBonemeal extends Behavior<Villager> {
    private long nextWorkCycleTime;
    private long lastBonemealingSession;
    private int timeWorkedSoFar;
    private Optional<BlockPos> cropPos;
    
    public UseBonemeal() {
        super(ImmutableMap.<MemoryModuleType<PositionTracker>, MemoryStatus>of(MemoryModuleType.LOOK_TARGET, MemoryStatus.VALUE_ABSENT, (MemoryModuleType<PositionTracker>)MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT));
        this.cropPos = Optional.<BlockPos>empty();
    }
    
    @Override
    protected boolean checkExtraStartConditions(final ServerLevel zd, final Villager bdp) {
        if (bdp.tickCount % 10 != 0 || (this.lastBonemealingSession != 0L && this.lastBonemealingSession + 160L > bdp.tickCount)) {
            return false;
        }
        if (bdp.getInventory().countItem(Items.BONE_MEAL) <= 0) {
            return false;
        }
        this.cropPos = this.pickNextTarget(zd, bdp);
        return this.cropPos.isPresent();
    }
    
    @Override
    protected boolean canStillUse(final ServerLevel zd, final Villager bdp, final long long3) {
        return this.timeWorkedSoFar < 80 && this.cropPos.isPresent();
    }
    
    private Optional<BlockPos> pickNextTarget(final ServerLevel zd, final Villager bdp) {
        final BlockPos.MutableBlockPos a4 = new BlockPos.MutableBlockPos();
        Optional<BlockPos> optional5 = Optional.<BlockPos>empty();
        int integer6 = 0;
        for (int integer7 = -1; integer7 <= 1; ++integer7) {
            for (int integer8 = -1; integer8 <= 1; ++integer8) {
                for (int integer9 = -1; integer9 <= 1; ++integer9) {
                    a4.setWithOffset(bdp.blockPosition(), integer7, integer8, integer9);
                    if (this.validPos(a4, zd) && zd.random.nextInt(++integer6) == 0) {
                        optional5 = Optional.<BlockPos>of(a4.immutable());
                    }
                }
            }
        }
        return optional5;
    }
    
    private boolean validPos(final BlockPos fu, final ServerLevel zd) {
        final BlockState cfj4 = zd.getBlockState(fu);
        final Block bvr5 = cfj4.getBlock();
        return bvr5 instanceof CropBlock && !((CropBlock)bvr5).isMaxAge(cfj4);
    }
    
    @Override
    protected void start(final ServerLevel zd, final Villager bdp, final long long3) {
        this.setCurrentCropAsTarget(bdp);
        bdp.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.BONE_MEAL));
        this.nextWorkCycleTime = long3;
        this.timeWorkedSoFar = 0;
    }
    
    private void setCurrentCropAsTarget(final Villager bdp) {
        final BlockPosTracker aqj3;
        this.cropPos.ifPresent(fu -> {
            aqj3 = new BlockPosTracker(fu);
            bdp.getBrain().<PositionTracker>setMemory(MemoryModuleType.LOOK_TARGET, aqj3);
            bdp.getBrain().<WalkTarget>setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(aqj3, 0.5f, 1));
        });
    }
    
    @Override
    protected void stop(final ServerLevel zd, final Villager bdp, final long long3) {
        bdp.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
        this.lastBonemealingSession = bdp.tickCount;
    }
    
    @Override
    protected void tick(final ServerLevel zd, final Villager bdp, final long long3) {
        final BlockPos fu6 = this.cropPos.get();
        if (long3 < this.nextWorkCycleTime || !fu6.closerThan(bdp.position(), 1.0)) {
            return;
        }
        ItemStack bki7 = ItemStack.EMPTY;
        final SimpleContainer anm8 = bdp.getInventory();
        for (int integer9 = anm8.getContainerSize(), integer10 = 0; integer10 < integer9; ++integer10) {
            final ItemStack bki8 = anm8.getItem(integer10);
            if (bki8.getItem() == Items.BONE_MEAL) {
                bki7 = bki8;
                break;
            }
        }
        if (!bki7.isEmpty() && BoneMealItem.growCrop(bki7, zd, fu6)) {
            zd.levelEvent(2005, fu6, 0);
            this.cropPos = this.pickNextTarget(zd, bdp);
            this.setCurrentCropAsTarget(bdp);
            this.nextWorkCycleTime = long3 + 40L;
        }
        ++this.timeWorkedSoFar;
    }
}
