package net.minecraft.world.entity.animal.horse;

import net.minecraft.world.entity.Entity;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.AgableMob;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.item.Items;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.SpawnEggItem;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.Container;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.item.HorseArmorItem;
import net.minecraft.world.entity.monster.SharedMonsterAttributes;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.EntityType;
import javax.annotation.Nullable;
import net.minecraft.network.syncher.EntityDataAccessor;
import java.util.UUID;

public class Horse extends AbstractHorse {
    private static final UUID ARMOR_MODIFIER_UUID;
    private static final EntityDataAccessor<Integer> DATA_ID_TYPE_VARIANT;
    private static final String[] VARIANT_TEXTURES;
    private static final String[] VARIANT_HASHES;
    private static final String[] MARKING_TEXTURES;
    private static final String[] MARKING_HASHES;
    @Nullable
    private String layerTextureHashName;
    private final String[] layerTextureLayers;
    
    public Horse(final EntityType<? extends Horse> aku, final Level bjw) {
        super(aku, bjw);
        this.layerTextureLayers = new String[2];
    }
    
    @Override
    protected void defineSynchedData() {
        super.defineSynchedData();
        this.entityData.<Integer>define(Horse.DATA_ID_TYPE_VARIANT, 0);
    }
    
    @Override
    public void addAdditionalSaveData(final CompoundTag jt) {
        super.addAdditionalSaveData(jt);
        jt.putInt("Variant", this.getVariant());
        if (!this.inventory.getItem(1).isEmpty()) {
            jt.put("ArmorItem", this.inventory.getItem(1).save(new CompoundTag()));
        }
    }
    
    public ItemStack getArmor() {
        return this.getItemBySlot(EquipmentSlot.CHEST);
    }
    
    private void setArmor(final ItemStack ben) {
        this.setItemSlot(EquipmentSlot.CHEST, ben);
        this.setDropChance(EquipmentSlot.CHEST, 0.0f);
    }
    
    @Override
    public void readAdditionalSaveData(final CompoundTag jt) {
        super.readAdditionalSaveData(jt);
        this.setVariant(jt.getInt("Variant"));
        if (jt.contains("ArmorItem", 10)) {
            final ItemStack ben3 = ItemStack.of(jt.getCompound("ArmorItem"));
            if (!ben3.isEmpty() && this.isArmor(ben3)) {
                this.inventory.setItem(1, ben3);
            }
        }
        this.updateEquipment();
    }
    
    public void setVariant(final int integer) {
        this.entityData.<Integer>set(Horse.DATA_ID_TYPE_VARIANT, integer);
        this.clearLayeredTextureInfo();
    }
    
    public int getVariant() {
        return this.entityData.<Integer>get(Horse.DATA_ID_TYPE_VARIANT);
    }
    
    private void clearLayeredTextureInfo() {
        this.layerTextureHashName = null;
    }
    
    private void rebuildLayeredTextureInfo() {
        final int integer2 = this.getVariant();
        final int integer3 = (integer2 & 0xFF) % 7;
        final int integer4 = ((integer2 & 0xFF00) >> 8) % 5;
        this.layerTextureLayers[0] = Horse.VARIANT_TEXTURES[integer3];
        this.layerTextureLayers[1] = Horse.MARKING_TEXTURES[integer4];
        this.layerTextureHashName = "horse/" + Horse.VARIANT_HASHES[integer3] + Horse.MARKING_HASHES[integer4];
    }
    
    public String getLayeredTextureHashName() {
        if (this.layerTextureHashName == null) {
            this.rebuildLayeredTextureInfo();
        }
        return this.layerTextureHashName;
    }
    
    public String[] getLayeredTextureLayers() {
        if (this.layerTextureHashName == null) {
            this.rebuildLayeredTextureInfo();
        }
        return this.layerTextureLayers;
    }
    
    @Override
    protected void updateEquipment() {
        super.updateEquipment();
        this.setArmorEquipment(this.inventory.getItem(1));
        this.setDropChance(EquipmentSlot.CHEST, 0.0f);
    }
    
    private void setArmorEquipment(final ItemStack ben) {
        this.setArmor(ben);
        if (!this.level.isClientSide) {
            this.getAttribute(SharedMonsterAttributes.ARMOR).removeModifier(Horse.ARMOR_MODIFIER_UUID);
            if (this.isArmor(ben)) {
                final int integer3 = ((HorseArmorItem)ben.getItem()).getProtection();
                if (integer3 != 0) {
                    this.getAttribute(SharedMonsterAttributes.ARMOR).addModifier(new AttributeModifier(Horse.ARMOR_MODIFIER_UUID, "Horse armor bonus", integer3, AttributeModifier.Operation.ADDITION).setSerialize(false));
                }
            }
        }
    }
    
    @Override
    public void containerChanged(final Container aje) {
        final ItemStack ben3 = this.getArmor();
        super.containerChanged(aje);
        final ItemStack ben4 = this.getArmor();
        if (this.tickCount > 20 && this.isArmor(ben4) && ben3 != ben4) {
            this.playSound(SoundEvents.HORSE_ARMOR, 0.5f, 1.0f);
        }
    }
    
    @Override
    protected void playGallopSound(final SoundType bum) {
        super.playGallopSound(bum);
        if (this.random.nextInt(10) == 0) {
            this.playSound(SoundEvents.HORSE_BREATHE, bum.getVolume() * 0.6f, bum.getPitch());
        }
    }
    
    @Override
    protected void registerAttributes() {
        super.registerAttributes();
        this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(this.generateRandomMaxHealth());
        this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(this.generateRandomSpeed());
        this.getAttribute(Horse.JUMP_STRENGTH).setBaseValue(this.generateRandomJumpStrength());
    }
    
    @Override
    public void tick() {
        super.tick();
        if (this.level.isClientSide && this.entityData.isDirty()) {
            this.entityData.clearDirty();
            this.clearLayeredTextureInfo();
        }
    }
    
    @Override
    protected SoundEvent getAmbientSound() {
        super.getAmbientSound();
        return SoundEvents.HORSE_AMBIENT;
    }
    
    @Override
    protected SoundEvent getDeathSound() {
        super.getDeathSound();
        return SoundEvents.HORSE_DEATH;
    }
    
    @Override
    protected SoundEvent getHurtSound(final DamageSource ajz) {
        super.getHurtSound(ajz);
        return SoundEvents.HORSE_HURT;
    }
    
    @Override
    protected SoundEvent getAngrySound() {
        super.getAngrySound();
        return SoundEvents.HORSE_ANGRY;
    }
    
    @Override
    public boolean mobInteract(final Player ayj, final InteractionHand ajk) {
        final ItemStack ben4 = ayj.getItemInHand(ajk);
        final boolean boolean5 = !ben4.isEmpty();
        if (boolean5 && ben4.getItem() instanceof SpawnEggItem) {
            return super.mobInteract(ayj, ajk);
        }
        if (!this.isBaby()) {
            if (this.isTamed() && ayj.isSecondaryUseActive()) {
                this.openInventory(ayj);
                return true;
            }
            if (this.isVehicle()) {
                return super.mobInteract(ayj, ajk);
            }
        }
        if (boolean5) {
            if (this.handleEating(ayj, ben4)) {
                if (!ayj.abilities.instabuild) {
                    ben4.shrink(1);
                }
                return true;
            }
            if (ben4.interactEnemy(ayj, this, ajk)) {
                return true;
            }
            if (!this.isTamed()) {
                this.makeMad();
                return true;
            }
            final boolean boolean6 = !this.isBaby() && !this.isSaddled() && ben4.getItem() == Items.SADDLE;
            if (this.isArmor(ben4) || boolean6) {
                this.openInventory(ayj);
                return true;
            }
        }
        if (this.isBaby()) {
            return super.mobInteract(ayj, ajk);
        }
        this.doPlayerRide(ayj);
        return true;
    }
    
    @Override
    public boolean canMate(final Animal atc) {
        return atc != this && (atc instanceof Donkey || atc instanceof Horse) && this.canParent() && ((AbstractHorse)atc).canParent();
    }
    
    @Override
    public AgableMob getBreedOffspring(final AgableMob ako) {
        AbstractHorse aue3;
        if (ako instanceof Donkey) {
            aue3 = EntityType.MULE.create(this.level);
        }
        else {
            final Horse aug4 = (Horse)ako;
            aue3 = EntityType.HORSE.create(this.level);
            final int integer6 = this.random.nextInt(9);
            int integer7;
            if (integer6 < 4) {
                integer7 = (this.getVariant() & 0xFF);
            }
            else if (integer6 < 8) {
                integer7 = (aug4.getVariant() & 0xFF);
            }
            else {
                integer7 = this.random.nextInt(7);
            }
            final int integer8 = this.random.nextInt(5);
            if (integer8 < 2) {
                integer7 |= (this.getVariant() & 0xFF00);
            }
            else if (integer8 < 4) {
                integer7 |= (aug4.getVariant() & 0xFF00);
            }
            else {
                integer7 |= (this.random.nextInt(5) << 8 & 0xFF00);
            }
            ((Horse)aue3).setVariant(integer7);
        }
        this.setOffspringAttributes(ako, aue3);
        return aue3;
    }
    
    @Override
    public boolean wearsArmor() {
        return true;
    }
    
    @Override
    public boolean isArmor(final ItemStack ben) {
        return ben.getItem() instanceof HorseArmorItem;
    }
    
    @Nullable
    @Override
    public SpawnGroupData finalizeSpawn(final LevelAccessor bjx, final DifficultyInstance ajj, final MobSpawnType alc, @Nullable SpawnGroupData alm, @Nullable final CompoundTag jt) {
        int integer7;
        if (alm instanceof HorseGroupData) {
            integer7 = ((HorseGroupData)alm).variant;
        }
        else {
            integer7 = this.random.nextInt(7);
            alm = new HorseGroupData(integer7);
        }
        this.setVariant(integer7 | this.random.nextInt(5) << 8);
        return super.finalizeSpawn(bjx, ajj, alc, alm, jt);
    }
    
    static {
        ARMOR_MODIFIER_UUID = UUID.fromString("556E1665-8B10-40C8-8F9D-CF9B1667F295");
        DATA_ID_TYPE_VARIANT = SynchedEntityData.<Integer>defineId(Horse.class, EntityDataSerializers.INT);
        VARIANT_TEXTURES = new String[] { "textures/entity/horse/horse_white.png", "textures/entity/horse/horse_creamy.png", "textures/entity/horse/horse_chestnut.png", "textures/entity/horse/horse_brown.png", "textures/entity/horse/horse_black.png", "textures/entity/horse/horse_gray.png", "textures/entity/horse/horse_darkbrown.png" };
        VARIANT_HASHES = new String[] { "hwh", "hcr", "hch", "hbr", "hbl", "hgr", "hdb" };
        MARKING_TEXTURES = new String[] { null, "textures/entity/horse/horse_markings_white.png", "textures/entity/horse/horse_markings_whitefield.png", "textures/entity/horse/horse_markings_whitedots.png", "textures/entity/horse/horse_markings_blackdots.png" };
        MARKING_HASHES = new String[] { "", "wo_", "wmo", "wdo", "bdo" };
    }
    
    public static class HorseGroupData extends AgableMobGroupData {
        public final int variant;
        
        public HorseGroupData(final int integer) {
            this.variant = integer;
        }
    }
}
