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

import net.minecraft.world.entity.LivingEntity;
import java.util.Optional;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.memory.WalkTarget;
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 javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Mob;

public class JumpOnBed extends Behavior<Mob> {
    private final float speed;
    @Nullable
    private BlockPos targetBed;
    private int remainingTimeToReachBed;
    private int remainingJumps;
    private int remainingCooldownUntilNextJump;
    
    public JumpOnBed(final float float1) {
        super(ImmutableMap.<MemoryModuleType<BlockPos>, MemoryStatus>of(MemoryModuleType.NEAREST_BED, MemoryStatus.VALUE_PRESENT, (MemoryModuleType<BlockPos>)MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT));
        this.speed = float1;
    }
    
    @Override
    protected boolean checkExtraStartConditions(final ServerLevel xd, final Mob ala) {
        return ala.isBaby() && this.nearBed(xd, ala);
    }
    
    @Override
    protected void start(final ServerLevel xd, final Mob ala, final long long3) {
        super.start(xd, ala, long3);
        this.getNearestBed(ala).ifPresent(fk -> {
            this.targetBed = fk;
            this.remainingTimeToReachBed = 100;
            this.remainingJumps = 3 + xd.random.nextInt(4);
            this.remainingCooldownUntilNextJump = 0;
            this.startWalkingTowardsBed(ala, fk);
        });
    }
    
    @Override
    protected void stop(final ServerLevel xd, final Mob ala, final long long3) {
        super.stop(xd, ala, long3);
        this.targetBed = null;
        this.remainingTimeToReachBed = 0;
        this.remainingJumps = 0;
        this.remainingCooldownUntilNextJump = 0;
    }
    
    @Override
    protected boolean canStillUse(final ServerLevel xd, final Mob ala, final long long3) {
        return ala.isBaby() && this.targetBed != null && this.isBed(xd, this.targetBed) && !this.tiredOfWalking(xd, ala) && !this.tiredOfJumping(xd, ala);
    }
    
    @Override
    protected boolean timedOut(final long long1) {
        return false;
    }
    
    @Override
    protected void tick(final ServerLevel xd, final Mob ala, final long long3) {
        if (!this.onOrOverBed(xd, ala)) {
            --this.remainingTimeToReachBed;
            return;
        }
        if (this.remainingCooldownUntilNextJump > 0) {
            --this.remainingCooldownUntilNextJump;
            return;
        }
        if (this.onBedSurface(xd, ala)) {
            ala.getJumpControl().jump();
            --this.remainingJumps;
            this.remainingCooldownUntilNextJump = 5;
        }
    }
    
    private void startWalkingTowardsBed(final Mob ala, final BlockPos fk) {
        ala.getBrain().<WalkTarget>setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(fk, this.speed, 0));
    }
    
    private boolean nearBed(final ServerLevel xd, final Mob ala) {
        return this.onOrOverBed(xd, ala) || this.getNearestBed(ala).isPresent();
    }
    
    private boolean onOrOverBed(final ServerLevel xd, final Mob ala) {
        final BlockPos fk4 = new BlockPos(ala);
        final BlockPos fk5 = fk4.below();
        return this.isBed(xd, fk4) || this.isBed(xd, fk5);
    }
    
    private boolean onBedSurface(final ServerLevel xd, final Mob ala) {
        return this.isBed(xd, new BlockPos(ala));
    }
    
    private boolean isBed(final ServerLevel xd, final BlockPos fk) {
        return xd.getBlockState(fk).is(BlockTags.BEDS);
    }
    
    private Optional<BlockPos> getNearestBed(final Mob ala) {
        return ala.getBrain().<BlockPos>getMemory(MemoryModuleType.NEAREST_BED);
    }
    
    private boolean tiredOfWalking(final ServerLevel xd, final Mob ala) {
        return !this.onOrOverBed(xd, ala) && this.remainingTimeToReachBed <= 0;
    }
    
    private boolean tiredOfJumping(final ServerLevel xd, final Mob ala) {
        return this.onOrOverBed(xd, ala) && this.remainingJumps <= 0;
    }
}
