package net.minecraft.world.entity;

import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.scores.Team;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.server.level.ServerPlayer;
import javax.annotation.Nullable;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.players.OldUsersConverter;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.ai.goal.SitGoal;
import java.util.UUID;
import java.util.Optional;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.entity.animal.Animal;

public abstract class TamableAnimal extends Animal {
    protected static final EntityDataAccessor<Byte> DATA_FLAGS_ID;
    protected static final EntityDataAccessor<Optional<UUID>> DATA_OWNERUUID_ID;
    protected SitGoal sitGoal;
    
    protected TamableAnimal(final EntityType<? extends TamableAnimal> aku, final Level bjw) {
        super(aku, bjw);
        this.reassessTameGoals();
    }
    
    @Override
    protected void defineSynchedData() {
        super.defineSynchedData();
        this.entityData.<Byte>define(TamableAnimal.DATA_FLAGS_ID, (Byte)0);
        this.entityData.<Optional<UUID>>define(TamableAnimal.DATA_OWNERUUID_ID, Optional.<UUID>empty());
    }
    
    @Override
    public void addAdditionalSaveData(final CompoundTag jt) {
        super.addAdditionalSaveData(jt);
        if (this.getOwnerUUID() == null) {
            jt.putString("OwnerUUID", "");
        }
        else {
            jt.putString("OwnerUUID", this.getOwnerUUID().toString());
        }
        jt.putBoolean("Sitting", this.isSitting());
    }
    
    @Override
    public void readAdditionalSaveData(final CompoundTag jt) {
        super.readAdditionalSaveData(jt);
        String string3;
        if (jt.contains("OwnerUUID", 8)) {
            string3 = jt.getString("OwnerUUID");
        }
        else {
            final String string4 = jt.getString("Owner");
            string3 = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), string4);
        }
        if (!string3.isEmpty()) {
            try {
                this.setOwnerUUID(UUID.fromString(string3));
                this.setTame(true);
            }
            catch (Throwable throwable4) {
                this.setTame(false);
            }
        }
        if (this.sitGoal != null) {
            this.sitGoal.wantToSit(jt.getBoolean("Sitting"));
        }
        this.setSitting(jt.getBoolean("Sitting"));
    }
    
    @Override
    public boolean canBeLeashed(final Player ayj) {
        return !this.isLeashed();
    }
    
    protected void spawnTamingParticles(final boolean boolean1) {
        ParticleOptions gt3 = ParticleTypes.HEART;
        if (!boolean1) {
            gt3 = ParticleTypes.SMOKE;
        }
        for (int integer4 = 0; integer4 < 7; ++integer4) {
            final double double5 = this.random.nextGaussian() * 0.02;
            final double double6 = this.random.nextGaussian() * 0.02;
            final double double7 = this.random.nextGaussian() * 0.02;
            this.level.addParticle(gt3, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), double5, double6, double7);
        }
    }
    
    @Override
    public void handleEntityEvent(final byte byte1) {
        if (byte1 == 7) {
            this.spawnTamingParticles(true);
        }
        else if (byte1 == 6) {
            this.spawnTamingParticles(false);
        }
        else {
            super.handleEntityEvent(byte1);
        }
    }
    
    public boolean isTame() {
        return (this.entityData.<Byte>get(TamableAnimal.DATA_FLAGS_ID) & 0x4) != 0x0;
    }
    
    public void setTame(final boolean boolean1) {
        final byte byte3 = this.entityData.<Byte>get(TamableAnimal.DATA_FLAGS_ID);
        if (boolean1) {
            this.entityData.<Byte>set(TamableAnimal.DATA_FLAGS_ID, (byte)(byte3 | 0x4));
        }
        else {
            this.entityData.<Byte>set(TamableAnimal.DATA_FLAGS_ID, (byte)(byte3 & 0xFFFFFFFB));
        }
        this.reassessTameGoals();
    }
    
    protected void reassessTameGoals() {
    }
    
    public boolean isSitting() {
        return (this.entityData.<Byte>get(TamableAnimal.DATA_FLAGS_ID) & 0x1) != 0x0;
    }
    
    public void setSitting(final boolean boolean1) {
        final byte byte3 = this.entityData.<Byte>get(TamableAnimal.DATA_FLAGS_ID);
        if (boolean1) {
            this.entityData.<Byte>set(TamableAnimal.DATA_FLAGS_ID, (byte)(byte3 | 0x1));
        }
        else {
            this.entityData.<Byte>set(TamableAnimal.DATA_FLAGS_ID, (byte)(byte3 & 0xFFFFFFFE));
        }
    }
    
    @Nullable
    public UUID getOwnerUUID() {
        return this.entityData.<Optional<UUID>>get(TamableAnimal.DATA_OWNERUUID_ID).orElse(null);
    }
    
    public void setOwnerUUID(@Nullable final UUID uUID) {
        this.entityData.<Optional<UUID>>set(TamableAnimal.DATA_OWNERUUID_ID, Optional.<UUID>ofNullable(uUID));
    }
    
    public void tame(final Player ayj) {
        this.setTame(true);
        this.setOwnerUUID(ayj.getUUID());
        if (ayj instanceof ServerPlayer) {
            CriteriaTriggers.TAME_ANIMAL.trigger((ServerPlayer)ayj, this);
        }
    }
    
    @Nullable
    public LivingEntity getOwner() {
        try {
            final UUID uUID2 = this.getOwnerUUID();
            if (uUID2 == null) {
                return null;
            }
            return this.level.getPlayerByUUID(uUID2);
        }
        catch (IllegalArgumentException illegalArgumentException2) {
            return null;
        }
    }
    
    @Override
    public boolean canAttack(final LivingEntity akz) {
        return !this.isOwnedBy(akz) && super.canAttack(akz);
    }
    
    public boolean isOwnedBy(final LivingEntity akz) {
        return akz == this.getOwner();
    }
    
    public SitGoal getSitGoal() {
        return this.sitGoal;
    }
    
    public boolean wantsToAttack(final LivingEntity akz1, final LivingEntity akz2) {
        return true;
    }
    
    @Override
    public Team getTeam() {
        if (this.isTame()) {
            final LivingEntity akz2 = this.getOwner();
            if (akz2 != null) {
                return akz2.getTeam();
            }
        }
        return super.getTeam();
    }
    
    @Override
    public boolean isAlliedTo(final Entity akq) {
        if (this.isTame()) {
            final LivingEntity akz3 = this.getOwner();
            if (akq == akz3) {
                return true;
            }
            if (akz3 != null) {
                return akz3.isAlliedTo(akq);
            }
        }
        return super.isAlliedTo(akq);
    }
    
    @Override
    public void die(final DamageSource ajz) {
        if (!this.level.isClientSide && this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES) && this.getOwner() instanceof ServerPlayer) {
            this.getOwner().sendMessage(this.getCombatTracker().getDeathMessage());
        }
        super.die(ajz);
    }
    
    static {
        DATA_FLAGS_ID = SynchedEntityData.<Byte>defineId(TamableAnimal.class, EntityDataSerializers.BYTE);
        DATA_OWNERUUID_ID = SynchedEntityData.<Optional<UUID>>defineId(TamableAnimal.class, EntityDataSerializers.OPTIONAL_UUID);
    }
}
