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

import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Entity;
import java.util.EnumSet;
import net.minecraft.world.level.pathfinder.Path;
import net.minecraft.world.entity.PathfinderMob;

public class MeleeAttackGoal extends Goal {
    protected final PathfinderMob mob;
    protected int attackTime;
    private final double speedModifier;
    private final boolean trackTarget;
    private Path path;
    private int timeToRecalcPath;
    private double pathedTargetX;
    private double pathedTargetY;
    private double pathedTargetZ;
    protected final int attackInterval = 20;
    private long lastUpdate;
    
    public MeleeAttackGoal(final PathfinderMob alg, final double double2, final boolean boolean3) {
        this.mob = alg;
        this.speedModifier = double2;
        this.trackTarget = boolean3;
        this.setFlags(EnumSet.<Flag>of(Flag.MOVE, Flag.LOOK));
    }
    
    @Override
    public boolean canUse() {
        final long long2 = this.mob.level.getGameTime();
        if (long2 - this.lastUpdate < 20L) {
            return false;
        }
        this.lastUpdate = long2;
        final LivingEntity akz4 = this.mob.getTarget();
        if (akz4 == null) {
            return false;
        }
        if (!akz4.isAlive()) {
            return false;
        }
        this.path = this.mob.getNavigation().createPath(akz4, 0);
        return this.path != null || this.getAttackReachSqr(akz4) >= this.mob.distanceToSqr(akz4.getX(), akz4.getY(), akz4.getZ());
    }
    
    @Override
    public boolean canContinueToUse() {
        final LivingEntity akz2 = this.mob.getTarget();
        if (akz2 == null) {
            return false;
        }
        if (!akz2.isAlive()) {
            return false;
        }
        if (!this.trackTarget) {
            return !this.mob.getNavigation().isDone();
        }
        return this.mob.isWithinRestriction(new BlockPos(akz2)) && (!(akz2 instanceof Player) || (!akz2.isSpectator() && !((Player)akz2).isCreative()));
    }
    
    @Override
    public void start() {
        this.mob.getNavigation().moveTo(this.path, this.speedModifier);
        this.mob.setAggressive(true);
        this.timeToRecalcPath = 0;
    }
    
    @Override
    public void stop() {
        final LivingEntity akz2 = this.mob.getTarget();
        if (!EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(akz2)) {
            this.mob.setTarget(null);
        }
        this.mob.setAggressive(false);
        this.mob.getNavigation().stop();
    }
    
    @Override
    public void tick() {
        final LivingEntity akz2 = this.mob.getTarget();
        this.mob.getLookControl().setLookAt(akz2, 30.0f, 30.0f);
        final double double3 = this.mob.distanceToSqr(akz2.getX(), akz2.getY(), akz2.getZ());
        --this.timeToRecalcPath;
        if ((this.trackTarget || this.mob.getSensing().canSee(akz2)) && this.timeToRecalcPath <= 0 && ((this.pathedTargetX == 0.0 && this.pathedTargetY == 0.0 && this.pathedTargetZ == 0.0) || akz2.distanceToSqr(this.pathedTargetX, this.pathedTargetY, this.pathedTargetZ) >= 1.0 || this.mob.getRandom().nextFloat() < 0.05f)) {
            this.pathedTargetX = akz2.getX();
            this.pathedTargetY = akz2.getY();
            this.pathedTargetZ = akz2.getZ();
            this.timeToRecalcPath = 4 + this.mob.getRandom().nextInt(7);
            if (double3 > 1024.0) {
                this.timeToRecalcPath += 10;
            }
            else if (double3 > 256.0) {
                this.timeToRecalcPath += 5;
            }
            if (!this.mob.getNavigation().moveTo(akz2, this.speedModifier)) {
                this.timeToRecalcPath += 15;
            }
        }
        this.attackTime = Math.max(this.attackTime - 1, 0);
        this.checkAndPerformAttack(akz2, double3);
    }
    
    protected void checkAndPerformAttack(final LivingEntity akz, final double double2) {
        final double double3 = this.getAttackReachSqr(akz);
        if (double2 <= double3 && this.attackTime <= 0) {
            this.attackTime = 20;
            this.mob.swing(InteractionHand.MAIN_HAND);
            this.mob.doHurtTarget(akz);
        }
    }
    
    protected double getAttackReachSqr(final LivingEntity akz) {
        return this.mob.getBbWidth() * 2.0f * (this.mob.getBbWidth() * 2.0f) + akz.getBbWidth();
    }
}
