package net.minecraft.world.entity.animal;

import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.level.GameRules;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.stats.Stats;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import javax.annotation.Nullable;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.player.Player;
import java.util.Random;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.LevelReader;
import net.minecraft.core.BlockPos;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.EntityType;
import java.util.UUID;
import net.minecraft.world.entity.AgableMob;

public abstract class Animal extends AgableMob {
    private int inLove;
    private UUID loveCause;
    
    protected Animal(final EntityType<? extends Animal> aoq, final Level bqb) {
        super(aoq, bqb);
        this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0f);
        this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0f);
    }
    
    @Override
    protected void customServerAiStep() {
        if (this.getAge() != 0) {
            this.inLove = 0;
        }
        super.customServerAiStep();
    }
    
    @Override
    public void aiStep() {
        super.aiStep();
        if (this.getAge() != 0) {
            this.inLove = 0;
        }
        if (this.inLove > 0) {
            --this.inLove;
            if (this.inLove % 10 == 0) {
                final double double2 = this.random.nextGaussian() * 0.02;
                final double double3 = this.random.nextGaussian() * 0.02;
                final double double4 = this.random.nextGaussian() * 0.02;
                this.level.addParticle(ParticleTypes.HEART, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), double2, double3, double4);
            }
        }
    }
    
    @Override
    public boolean hurt(final DamageSource anw, final float float2) {
        if (this.isInvulnerableTo(anw)) {
            return false;
        }
        this.inLove = 0;
        return super.hurt(anw, float2);
    }
    
    @Override
    public float getWalkTargetValue(final BlockPos fu, final LevelReader bqd) {
        if (bqd.getBlockState(fu.below()).is(Blocks.GRASS_BLOCK)) {
            return 10.0f;
        }
        return bqd.getBrightness(fu) - 0.5f;
    }
    
    @Override
    public void addAdditionalSaveData(final CompoundTag le) {
        super.addAdditionalSaveData(le);
        le.putInt("InLove", this.inLove);
        if (this.loveCause != null) {
            le.putUUID("LoveCause", this.loveCause);
        }
    }
    
    @Override
    public double getMyRidingOffset() {
        return 0.14;
    }
    
    @Override
    public void readAdditionalSaveData(final CompoundTag le) {
        super.readAdditionalSaveData(le);
        this.inLove = le.getInt("InLove");
        this.loveCause = (le.hasUUID("LoveCause") ? le.getUUID("LoveCause") : null);
    }
    
    public static boolean checkAnimalSpawnRules(final EntityType<? extends Animal> aoq, final LevelAccessor bqc, final MobSpawnType apb, final BlockPos fu, final Random random) {
        return bqc.getBlockState(fu.below()).is(Blocks.GRASS_BLOCK) && bqc.getRawBrightness(fu, 0) > 8;
    }
    
    @Override
    public int getAmbientSoundInterval() {
        return 120;
    }
    
    @Override
    public boolean removeWhenFarAway(final double double1) {
        return false;
    }
    
    @Override
    protected int getExperienceReward(final Player bec) {
        return 1 + this.level.random.nextInt(3);
    }
    
    public boolean isFood(final ItemStack bki) {
        return bki.getItem() == Items.WHEAT;
    }
    
    public InteractionResult mobInteract(final Player bec, final InteractionHand anf) {
        final ItemStack bki4 = bec.getItemInHand(anf);
        if (this.isFood(bki4)) {
            final int integer5 = this.getAge();
            if (!this.level.isClientSide && integer5 == 0 && this.canFallInLove()) {
                this.usePlayerItem(bec, bki4);
                this.setInLove(bec);
                return InteractionResult.SUCCESS;
            }
            if (this.isBaby()) {
                this.usePlayerItem(bec, bki4);
                this.ageUp((int)(-integer5 / 20 * 0.1f), true);
                return InteractionResult.sidedSuccess(this.level.isClientSide);
            }
            if (this.level.isClientSide) {
                return InteractionResult.CONSUME;
            }
        }
        return super.mobInteract(bec, anf);
    }
    
    protected void usePlayerItem(final Player bec, final ItemStack bki) {
        if (!bec.abilities.instabuild) {
            bki.shrink(1);
        }
    }
    
    public boolean canFallInLove() {
        return this.inLove <= 0;
    }
    
    public void setInLove(@Nullable final Player bec) {
        this.inLove = 600;
        if (bec != null) {
            this.loveCause = bec.getUUID();
        }
        this.level.broadcastEntityEvent(this, (byte)18);
    }
    
    public void setInLoveTime(final int integer) {
        this.inLove = integer;
    }
    
    public int getInLoveTime() {
        return this.inLove;
    }
    
    @Nullable
    public ServerPlayer getLoveCause() {
        if (this.loveCause == null) {
            return null;
        }
        final Player bec2 = this.level.getPlayerByUUID(this.loveCause);
        if (bec2 instanceof ServerPlayer) {
            return (ServerPlayer)bec2;
        }
        return null;
    }
    
    public boolean isInLove() {
        return this.inLove > 0;
    }
    
    public void resetLove() {
        this.inLove = 0;
    }
    
    public boolean canMate(final Animal ayk) {
        return ayk != this && ayk.getClass() == this.getClass() && this.isInLove() && ayk.isInLove();
    }
    
    public void spawnChildFromBreeding(final Level bqb, final Animal ayk) {
        final AgableMob aok4 = this.getBreedOffspring(ayk);
        if (aok4 == null) {
            return;
        }
        ServerPlayer ze5 = this.getLoveCause();
        if (ze5 == null && ayk.getLoveCause() != null) {
            ze5 = ayk.getLoveCause();
        }
        if (ze5 != null) {
            ze5.awardStat(Stats.ANIMALS_BRED);
            CriteriaTriggers.BRED_ANIMALS.trigger(ze5, this, ayk, aok4);
        }
        this.setAge(6000);
        ayk.setAge(6000);
        this.resetLove();
        ayk.resetLove();
        aok4.setBaby(true);
        aok4.moveTo(this.getX(), this.getY(), this.getZ(), 0.0f, 0.0f);
        bqb.addFreshEntity(aok4);
        bqb.broadcastEntityEvent(this, (byte)18);
        if (bqb.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
            bqb.addFreshEntity(new ExperienceOrb(bqb, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1));
        }
    }
    
    @Override
    public void handleEntityEvent(final byte byte1) {
        if (byte1 == 18) {
            for (int integer3 = 0; integer3 < 7; ++integer3) {
                final double double4 = this.random.nextGaussian() * 0.02;
                final double double5 = this.random.nextGaussian() * 0.02;
                final double double6 = this.random.nextGaussian() * 0.02;
                this.level.addParticle(ParticleTypes.HEART, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), double4, double5, double6);
            }
        }
        else {
            super.handleEntityEvent(byte1);
        }
    }
}
