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

import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.util.RandomPos;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.core.Vec3i;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
import java.util.Optional;
import net.minecraft.world.entity.ai.Brain;
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 net.minecraft.core.BlockPos;
import javax.annotation.Nullable;
import net.minecraft.world.level.pathfinder.Path;
import net.minecraft.world.entity.Mob;

public class MoveToTargetSink extends Behavior<Mob> {
    @Nullable
    private Path path;
    @Nullable
    private BlockPos lastTargetPos;
    private float speedModifier;
    private int remainingDelay;
    
    public MoveToTargetSink(final int integer) {
        super(ImmutableMap.<MemoryModuleType<Long>, MemoryStatus>of(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryStatus.REGISTERED, (MemoryModuleType<Long>)MemoryModuleType.PATH, MemoryStatus.VALUE_ABSENT, (MemoryModuleType<Long>)MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_PRESENT), integer);
    }
    
    @Override
    protected boolean checkExtraStartConditions(final ServerLevel zd, final Mob aoz) {
        final Brain<?> apr4 = aoz.getBrain();
        final WalkTarget awr5 = apr4.<WalkTarget>getMemory(MemoryModuleType.WALK_TARGET).get();
        final boolean boolean6 = this.reachedTarget(aoz, awr5);
        if (!boolean6 && this.tryComputePath(aoz, awr5, zd.getGameTime())) {
            this.lastTargetPos = awr5.getTarget().currentBlockPosition();
            return true;
        }
        apr4.<WalkTarget>eraseMemory(MemoryModuleType.WALK_TARGET);
        if (boolean6) {
            apr4.<Long>eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
        }
        return false;
    }
    
    @Override
    protected boolean canStillUse(final ServerLevel zd, final Mob aoz, final long long3) {
        if (this.path == null || this.lastTargetPos == null) {
            return false;
        }
        final Optional<WalkTarget> optional6 = aoz.getBrain().<WalkTarget>getMemory(MemoryModuleType.WALK_TARGET);
        final PathNavigation awv7 = aoz.getNavigation();
        return !awv7.isDone() && optional6.isPresent() && !this.reachedTarget(aoz, optional6.get());
    }
    
    @Override
    protected void stop(final ServerLevel zd, final Mob aoz, final long long3) {
        aoz.getNavigation().stop();
        aoz.getBrain().<WalkTarget>eraseMemory(MemoryModuleType.WALK_TARGET);
        aoz.getBrain().<Path>eraseMemory(MemoryModuleType.PATH);
        this.path = null;
    }
    
    @Override
    protected void stop(final ServerLevel zd, final Mob aoz, final long long3) {
        aoz.getBrain().<Path>setMemory(MemoryModuleType.PATH, this.path);
        aoz.getNavigation().moveTo(this.path, this.speedModifier);
        this.remainingDelay = zd.getRandom().nextInt(10);
    }
    
    @Override
    protected void tick(final ServerLevel zd, final Mob aoz, final long long3) {
        --this.remainingDelay;
        if (this.remainingDelay > 0) {
            return;
        }
        final Path czf6 = aoz.getNavigation().getPath();
        final Brain<?> apr7 = aoz.getBrain();
        if (this.path != czf6) {
            this.path = czf6;
            apr7.<Path>setMemory(MemoryModuleType.PATH, czf6);
        }
        if (czf6 == null || this.lastTargetPos == null) {
            return;
        }
        final WalkTarget awr8 = apr7.<WalkTarget>getMemory(MemoryModuleType.WALK_TARGET).get();
        if (awr8.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0 && this.tryComputePath(aoz, awr8, zd.getGameTime())) {
            this.lastTargetPos = awr8.getTarget().currentBlockPosition();
            this.stop(zd, aoz, long3);
        }
    }
    
    private boolean tryComputePath(final Mob aoz, final WalkTarget awr, final long long3) {
        final BlockPos fu6 = awr.getTarget().currentBlockPosition();
        this.path = aoz.getNavigation().createPath(fu6, 0);
        this.speedModifier = awr.getSpeedModifier();
        final Brain<?> apr7 = aoz.getBrain();
        if (this.reachedTarget(aoz, awr)) {
            apr7.<Long>eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
        }
        else {
            final boolean boolean8 = this.path != null && this.path.canReach();
            if (boolean8) {
                apr7.<Long>eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
            }
            else if (!apr7.hasMemoryValue(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) {
                apr7.<Long>setMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, long3);
            }
            if (this.path != null) {
                return true;
            }
            final Vec3 dem9 = RandomPos.getPosTowards((PathfinderMob)aoz, 10, 7, Vec3.atBottomCenterOf(fu6));
            if (dem9 != null) {
                this.path = aoz.getNavigation().createPath(dem9.x, dem9.y, dem9.z, 0);
                return this.path != null;
            }
        }
        return false;
    }
    
    private boolean reachedTarget(final Mob aoz, final WalkTarget awr) {
        return awr.getTarget().currentBlockPosition().distManhattan(aoz.blockPosition()) <= awr.getCloseEnoughDist();
    }
}
