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

import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.monster.RangedAttackMob;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.entity.monster.CrossbowAttackMob;
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.world.entity.LivingEntity;

public class CrossbowAttack<E extends Mob, T extends LivingEntity> extends Behavior<E> {
    private int attackDelay;
    private CrossbowState crossbowState;
    
    public CrossbowAttack() {
        super(ImmutableMap.<MemoryModuleType<PositionTracker>, MemoryStatus>of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, (MemoryModuleType<PositionTracker>)MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_PRESENT), 1200);
        this.crossbowState = CrossbowState.UNCHARGED;
    }
    
    @Override
    protected boolean checkExtraStartConditions(final ServerLevel zd, final E aoz) {
        final LivingEntity aoy4 = getAttackTarget((LivingEntity)aoz);
        return ((LivingEntity)aoz).isHolding(Items.CROSSBOW) && BehaviorUtils.canSee((LivingEntity)aoz, aoy4) && BehaviorUtils.isWithinAttackRange((Mob)aoz, aoy4, 0);
    }
    
    @Override
    protected boolean canStillUse(final ServerLevel zd, final E aoz, final long long3) {
        return ((LivingEntity)aoz).getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET) && this.checkExtraStartConditions(zd, aoz);
    }
    
    @Override
    protected void tick(final ServerLevel zd, final E aoz, final long long3) {
        final LivingEntity aoy6 = getAttackTarget((LivingEntity)aoz);
        this.lookAtTarget((Mob)aoz, aoy6);
        this.crossbowAttack(aoz, aoy6);
    }
    
    @Override
    protected void stop(final ServerLevel zd, final E aoz, final long long3) {
        if (((LivingEntity)aoz).isUsingItem()) {
            ((LivingEntity)aoz).stopUsingItem();
        }
        if (((LivingEntity)aoz).isHolding(Items.CROSSBOW)) {
            ((CrossbowAttackMob)aoz).setChargingCrossbow(false);
            CrossbowItem.setCharged(((LivingEntity)aoz).getUseItem(), false);
        }
    }
    
    private void crossbowAttack(final E aoz, final LivingEntity aoy) {
        if (this.crossbowState == CrossbowState.UNCHARGED) {
            ((LivingEntity)aoz).startUsingItem(ProjectileUtil.getWeaponHoldingHand((LivingEntity)aoz, Items.CROSSBOW));
            this.crossbowState = CrossbowState.CHARGING;
            ((CrossbowAttackMob)aoz).setChargingCrossbow(true);
        }
        else if (this.crossbowState == CrossbowState.CHARGING) {
            if (!((LivingEntity)aoz).isUsingItem()) {
                this.crossbowState = CrossbowState.UNCHARGED;
            }
            final int integer4 = ((LivingEntity)aoz).getTicksUsingItem();
            final ItemStack bki5 = ((LivingEntity)aoz).getUseItem();
            if (integer4 >= CrossbowItem.getChargeDuration(bki5)) {
                ((LivingEntity)aoz).releaseUsingItem();
                this.crossbowState = CrossbowState.CHARGED;
                this.attackDelay = 20 + ((LivingEntity)aoz).getRandom().nextInt(20);
                ((CrossbowAttackMob)aoz).setChargingCrossbow(false);
            }
        }
        else if (this.crossbowState == CrossbowState.CHARGED) {
            --this.attackDelay;
            if (this.attackDelay == 0) {
                this.crossbowState = CrossbowState.READY_TO_ATTACK;
            }
        }
        else if (this.crossbowState == CrossbowState.READY_TO_ATTACK) {
            ((RangedAttackMob)aoz).performRangedAttack(aoy, 1.0f);
            final ItemStack bki6 = ((LivingEntity)aoz).getItemInHand(ProjectileUtil.getWeaponHoldingHand((LivingEntity)aoz, Items.CROSSBOW));
            CrossbowItem.setCharged(bki6, false);
            this.crossbowState = CrossbowState.UNCHARGED;
        }
    }
    
    private void lookAtTarget(final Mob aoz, final LivingEntity aoy) {
        aoz.getBrain().<EntityTracker>setMemory((MemoryModuleType<EntityTracker>)MemoryModuleType.LOOK_TARGET, new EntityTracker(aoy, true));
    }
    
    private static LivingEntity getAttackTarget(final LivingEntity aoy) {
        return aoy.getBrain().<LivingEntity>getMemory(MemoryModuleType.ATTACK_TARGET).get();
    }
    
    enum CrossbowState {
        UNCHARGED, 
        CHARGING, 
        CHARGED, 
        READY_TO_ATTACK;
    }
}
