package net.minecraft.world.entity.animal;

import net.minecraft.world.entity.ai.goal.PanicGoal;
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
import java.util.Iterator;
import java.util.List;
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
import net.minecraft.util.TimeUtil;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.Pose;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundEvent;
import javax.annotation.Nullable;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.biome.Biomes;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal;
import java.util.function.Predicate;
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.ai.goal.RandomStrollGoal;
import net.minecraft.world.entity.ai.goal.FollowParentGoal;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.goal.FloatGoal;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.AgableMob;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.EntityType;
import java.util.UUID;
import net.minecraft.util.IntRange;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.entity.NeutralMob;

public class PolarBear extends Animal implements NeutralMob {
    private static final EntityDataAccessor<Boolean> DATA_STANDING_ID;
    private float clientSideStandAnimationO;
    private float clientSideStandAnimation;
    private int warningSoundTicks;
    private static final IntRange PERSISTENT_ANGER_TIME;
    private int remainingPersistentAngerTime;
    private UUID persistentAngerTarget;
    
    public PolarBear(final EntityType<? extends PolarBear> aoq, final Level bqb) {
        super(aoq, bqb);
    }
    
    @Override
    public AgableMob getBreedOffspring(final AgableMob aok) {
        return EntityType.POLAR_BEAR.create(this.level);
    }
    
    @Override
    public boolean isFood(final ItemStack bki) {
        return false;
    }
    
    @Override
    protected void registerGoals() {
        super.registerGoals();
        this.goalSelector.addGoal(0, new FloatGoal(this));
        this.goalSelector.addGoal(1, new PolarBearMeleeAttackGoal());
        this.goalSelector.addGoal(1, new PolarBearPanicGoal());
        this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
        this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0));
        this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0f));
        this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
        this.targetSelector.addGoal(1, new PolarBearHurtByTargetGoal());
        this.targetSelector.addGoal(2, new PolarBearAttackPlayersGoal());
        this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
        this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, Fox.class, 10, true, true, null));
        this.targetSelector.addGoal(5, new ResetUniversalAngerTargetGoal<>(this, false));
    }
    
    public static AttributeSupplier.Builder createAttributes() {
        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0).add(Attributes.FOLLOW_RANGE, 20.0).add(Attributes.MOVEMENT_SPEED, 0.25).add(Attributes.ATTACK_DAMAGE, 6.0);
    }
    
    public static boolean checkPolarBearSpawnRules(final EntityType<PolarBear> aoq, final LevelAccessor bqc, final MobSpawnType apb, final BlockPos fu, final Random random) {
        final Biome bre6 = bqc.getBiome(fu);
        if (bre6 == Biomes.FROZEN_OCEAN || bre6 == Biomes.DEEP_FROZEN_OCEAN) {
            return bqc.getRawBrightness(fu, 0) > 8 && bqc.getBlockState(fu.below()).is(Blocks.ICE);
        }
        return Animal.checkAnimalSpawnRules(aoq, bqc, apb, fu, random);
    }
    
    @Override
    public void readAdditionalSaveData(final CompoundTag le) {
        super.readAdditionalSaveData(le);
        this.readPersistentAngerSaveData((ServerLevel)this.level, le);
    }
    
    @Override
    public void addAdditionalSaveData(final CompoundTag le) {
        super.addAdditionalSaveData(le);
        this.addPersistentAngerSaveData(le);
    }
    
    @Override
    public void startPersistentAngerTimer() {
        this.setRemainingPersistentAngerTime(PolarBear.PERSISTENT_ANGER_TIME.randomValue(this.random));
    }
    
    @Override
    public void setRemainingPersistentAngerTime(final int integer) {
        this.remainingPersistentAngerTime = integer;
    }
    
    @Override
    public int getRemainingPersistentAngerTime() {
        return this.remainingPersistentAngerTime;
    }
    
    @Override
    public void setPersistentAngerTarget(@Nullable final UUID uUID) {
        this.persistentAngerTarget = uUID;
    }
    
    @Override
    public UUID getPersistentAngerTarget() {
        return this.persistentAngerTarget;
    }
    
    @Override
    protected SoundEvent getAmbientSound() {
        if (this.isBaby()) {
            return SoundEvents.POLAR_BEAR_AMBIENT_BABY;
        }
        return SoundEvents.POLAR_BEAR_AMBIENT;
    }
    
    @Override
    protected SoundEvent getHurtSound(final DamageSource anw) {
        return SoundEvents.POLAR_BEAR_HURT;
    }
    
    @Override
    protected SoundEvent getDeathSound() {
        return SoundEvents.POLAR_BEAR_DEATH;
    }
    
    @Override
    protected void playStepSound(final BlockPos fu, final BlockState cfj) {
        this.playSound(SoundEvents.POLAR_BEAR_STEP, 0.15f, 1.0f);
    }
    
    protected void playWarningSound() {
        if (this.warningSoundTicks <= 0) {
            this.playSound(SoundEvents.POLAR_BEAR_WARNING, 1.0f, this.getVoicePitch());
            this.warningSoundTicks = 40;
        }
    }
    
    @Override
    protected void defineSynchedData() {
        super.defineSynchedData();
        this.entityData.<Boolean>define(PolarBear.DATA_STANDING_ID, false);
    }
    
    @Override
    public void tick() {
        super.tick();
        if (this.level.isClientSide) {
            if (this.clientSideStandAnimation != this.clientSideStandAnimationO) {
                this.refreshDimensions();
            }
            this.clientSideStandAnimationO = this.clientSideStandAnimation;
            if (this.isStanding()) {
                this.clientSideStandAnimation = Mth.clamp(this.clientSideStandAnimation + 1.0f, 0.0f, 6.0f);
            }
            else {
                this.clientSideStandAnimation = Mth.clamp(this.clientSideStandAnimation - 1.0f, 0.0f, 6.0f);
            }
        }
        if (this.warningSoundTicks > 0) {
            --this.warningSoundTicks;
        }
        if (!this.level.isClientSide) {
            this.updatePersistentAnger((ServerLevel)this.level, true);
        }
    }
    
    @Override
    public EntityDimensions getDimensions(final Pose apj) {
        if (this.clientSideStandAnimation > 0.0f) {
            final float float3 = this.clientSideStandAnimation / 6.0f;
            final float float4 = 1.0f + float3;
            return super.getDimensions(apj).scale(1.0f, float4);
        }
        return super.getDimensions(apj);
    }
    
    @Override
    public boolean doHurtTarget(final Entity aom) {
        final boolean boolean3 = aom.hurt(DamageSource.mobAttack(this), (float)(int)this.getAttributeValue(Attributes.ATTACK_DAMAGE));
        if (boolean3) {
            this.doEnchantDamageEffects(this, aom);
        }
        return boolean3;
    }
    
    public boolean isStanding() {
        return this.entityData.<Boolean>get(PolarBear.DATA_STANDING_ID);
    }
    
    public void setStanding(final boolean boolean1) {
        this.entityData.<Boolean>set(PolarBear.DATA_STANDING_ID, boolean1);
    }
    
    public float getStandingAnimationScale(final float float1) {
        return Mth.lerp(float1, this.clientSideStandAnimationO, this.clientSideStandAnimation) / 6.0f;
    }
    
    @Override
    protected float getWaterSlowDown() {
        return 0.98f;
    }
    
    @Override
    public SpawnGroupData finalizeSpawn(final LevelAccessor bqc, final DifficultyInstance ane, final MobSpawnType apb, @Nullable SpawnGroupData apo, @Nullable final CompoundTag le) {
        if (apo == null) {
            apo = new AgableMobGroupData();
            ((AgableMobGroupData)apo).setBabySpawnChance(1.0f);
        }
        return super.finalizeSpawn(bqc, ane, apb, apo, le);
    }
    
    static {
        DATA_STANDING_ID = SynchedEntityData.<Boolean>defineId(PolarBear.class, EntityDataSerializers.BOOLEAN);
        PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39);
    }
    
    class PolarBearHurtByTargetGoal extends HurtByTargetGoal {
        public PolarBearHurtByTargetGoal() {
            super(PolarBear.this, new Class[0]);
        }
        
        @Override
        public void start() {
            super.start();
            if (PolarBear.this.isBaby()) {
                this.alertOthers();
                this.stop();
            }
        }
        
        @Override
        protected void alertOther(final Mob aoz, final LivingEntity aoy) {
            if (aoz instanceof PolarBear && !aoz.isBaby()) {
                super.alertOther(aoz, aoy);
            }
        }
    }
    
    class PolarBearAttackPlayersGoal extends NearestAttackableTargetGoal<Player> {
        public PolarBearAttackPlayersGoal() {
            super(PolarBear.this, Player.class, 20, true, true, null);
        }
        
        @Override
        public boolean canUse() {
            if (PolarBear.this.isBaby()) {
                return false;
            }
            if (super.canUse()) {
                final List<PolarBear> list2 = PolarBear.this.level.<PolarBear>getEntitiesOfClass(PolarBear.class, PolarBear.this.getBoundingBox().inflate(8.0, 4.0, 8.0));
                for (final PolarBear ayz4 : list2) {
                    if (ayz4.isBaby()) {
                        return true;
                    }
                }
            }
            return false;
        }
        
        @Override
        protected double getFollowDistance() {
            return super.getFollowDistance() * 0.5;
        }
    }
    
    class PolarBearMeleeAttackGoal extends MeleeAttackGoal {
        public PolarBearMeleeAttackGoal() {
            super(PolarBear.this, 1.25, true);
        }
        
        @Override
        protected void checkAndPerformAttack(final LivingEntity aoy, final double double2) {
            final double double3 = this.getAttackReachSqr(aoy);
            if (double2 <= double3 && this.isTimeToAttack()) {
                this.resetAttackCooldown();
                this.mob.doHurtTarget(aoy);
                PolarBear.this.setStanding(false);
            }
            else if (double2 <= double3 * 2.0) {
                if (this.isTimeToAttack()) {
                    PolarBear.this.setStanding(false);
                    this.resetAttackCooldown();
                }
                if (this.getTicksUntilNextAttack() <= 10) {
                    PolarBear.this.setStanding(true);
                    PolarBear.this.playWarningSound();
                }
            }
            else {
                this.resetAttackCooldown();
                PolarBear.this.setStanding(false);
            }
        }
        
        @Override
        public void stop() {
            PolarBear.this.setStanding(false);
            super.stop();
        }
        
        @Override
        protected double getAttackReachSqr(final LivingEntity aoy) {
            return 4.0f + aoy.getBbWidth();
        }
    }
    
    class PolarBearPanicGoal extends PanicGoal {
        public PolarBearPanicGoal() {
            super(PolarBear.this, 2.0);
        }
        
        @Override
        public boolean canUse() {
            return (PolarBear.this.isBaby() || PolarBear.this.isOnFire()) && super.canUse();
        }
    }
}
