package net.minecraft.world.item;

import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.Tag;
import com.google.common.collect.HashMultimap;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import com.google.common.collect.Multimap;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.core.NonNullList;
import net.minecraft.world.phys.Vec3;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.level.ClipContext;
import java.util.List;
import net.minecraft.world.entity.Entity;
import net.minecraft.Util;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import com.google.common.collect.Maps;
import net.minecraft.core.Registry;
import net.minecraft.world.food.FoodProperties;
import javax.annotation.Nullable;
import net.minecraft.resources.ResourceLocation;
import java.util.Random;
import java.util.UUID;
import net.minecraft.world.level.block.Block;
import java.util.Map;
import net.minecraft.world.level.ItemLike;

public class Item implements ItemLike {
    public static final Map<Block, Item> BY_BLOCK;
    private static final ItemPropertyFunction PROPERTY_DAMAGED;
    private static final ItemPropertyFunction PROPERTY_DAMAGE;
    private static final ItemPropertyFunction PROPERTY_LEFTHANDED;
    private static final ItemPropertyFunction PROPERTY_COOLDOWN;
    private static final ItemPropertyFunction PROPERTY_CUSTOM_MODEL_DATA;
    protected static final UUID BASE_ATTACK_DAMAGE_UUID;
    protected static final UUID BASE_ATTACK_SPEED_UUID;
    protected static final Random random;
    private final Map<ResourceLocation, ItemPropertyFunction> properties;
    protected final CreativeModeTab category;
    private final Rarity rarity;
    private final int maxStackSize;
    private final int maxDamage;
    private final Item craftingRemainingItem;
    @Nullable
    private String descriptionId;
    @Nullable
    private final FoodProperties foodProperties;
    
    public static int getId(final Item bei) {
        return (bei == null) ? 0 : Registry.ITEM.getId(bei);
    }
    
    public static Item byId(final int integer) {
        return Registry.ITEM.byId(integer);
    }
    
    @Deprecated
    public static Item byBlock(final Block bph) {
        return Item.BY_BLOCK.getOrDefault(bph, Items.AIR);
    }
    
    public Item(final Properties a) {
        this.properties = Maps.newHashMap();
        this.addProperty(new ResourceLocation("lefthanded"), Item.PROPERTY_LEFTHANDED);
        this.addProperty(new ResourceLocation("cooldown"), Item.PROPERTY_COOLDOWN);
        this.addProperty(new ResourceLocation("custom_model_data"), Item.PROPERTY_CUSTOM_MODEL_DATA);
        this.category = a.category;
        this.rarity = a.rarity;
        this.craftingRemainingItem = a.craftingRemainingItem;
        this.maxDamage = a.maxDamage;
        this.maxStackSize = a.maxStackSize;
        this.foodProperties = a.foodProperties;
        if (this.maxDamage > 0) {
            this.addProperty(new ResourceLocation("damaged"), Item.PROPERTY_DAMAGED);
            this.addProperty(new ResourceLocation("damage"), Item.PROPERTY_DAMAGE);
        }
    }
    
    public void onUseTick(final Level bjw, final LivingEntity akz, final ItemStack ben, final int integer) {
    }
    
    @Nullable
    public ItemPropertyFunction getProperty(final ResourceLocation sm) {
        return this.properties.get(sm);
    }
    
    public boolean hasProperties() {
        return !this.properties.isEmpty();
    }
    
    public boolean verifyTagAfterLoad(final CompoundTag jt) {
        return false;
    }
    
    public boolean canAttackBlock(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj) {
        return true;
    }
    
    @Override
    public Item asItem() {
        return this;
    }
    
    public final void addProperty(final ResourceLocation sm, final ItemPropertyFunction bem) {
        this.properties.put(sm, bem);
    }
    
    public InteractionResult useOn(final UseOnContext bfz) {
        return InteractionResult.PASS;
    }
    
    public float getDestroySpeed(final ItemStack ben, final BlockState byj) {
        return 1.0f;
    }
    
    public InteractionResultHolder<ItemStack> use(final Level bjw, final Player ayj, final InteractionHand ajk) {
        if (!this.isEdible()) {
            return InteractionResultHolder.<ItemStack>pass(ayj.getItemInHand(ajk));
        }
        final ItemStack ben5 = ayj.getItemInHand(ajk);
        if (ayj.canEat(this.getFoodProperties().canAlwaysEat())) {
            ayj.startUsingItem(ajk);
            return InteractionResultHolder.<ItemStack>consume(ben5);
        }
        return InteractionResultHolder.<ItemStack>fail(ben5);
    }
    
    public ItemStack finishUsingItem(final ItemStack ben, final Level bjw, final LivingEntity akz) {
        if (this.isEdible()) {
            return akz.eat(bjw, ben);
        }
        return ben;
    }
    
    public final int getMaxStackSize() {
        return this.maxStackSize;
    }
    
    public final int getMaxDamage() {
        return this.maxDamage;
    }
    
    public boolean canBeDepleted() {
        return this.maxDamage > 0;
    }
    
    public boolean hurtEnemy(final ItemStack ben, final LivingEntity akz2, final LivingEntity akz3) {
        return false;
    }
    
    public boolean mineBlock(final ItemStack ben, final Level bjw, final BlockState byj, final BlockPos fk, final LivingEntity akz) {
        return false;
    }
    
    public boolean canDestroySpecial(final BlockState byj) {
        return false;
    }
    
    public boolean interactEnemy(final ItemStack ben, final Player ayj, final LivingEntity akz, final InteractionHand ajk) {
        return false;
    }
    
    public Component getDescription() {
        return new TranslatableComponent(this.getDescriptionId(), new Object[0]);
    }
    
    @Override
    public String toString() {
        return Registry.ITEM.getKey(this).getPath();
    }
    
    protected String getOrCreateDescriptionId() {
        if (this.descriptionId == null) {
            this.descriptionId = Util.makeDescriptionId("item", Registry.ITEM.getKey(this));
        }
        return this.descriptionId;
    }
    
    public String getDescriptionId() {
        return this.getOrCreateDescriptionId();
    }
    
    public String getDescriptionId(final ItemStack ben) {
        return this.getDescriptionId();
    }
    
    public boolean shouldOverrideMultiplayerNbt() {
        return true;
    }
    
    @Nullable
    public final Item getCraftingRemainingItem() {
        return this.craftingRemainingItem;
    }
    
    public boolean hasCraftingRemainingItem() {
        return this.craftingRemainingItem != null;
    }
    
    public void inventoryTick(final ItemStack ben, final Level bjw, final Entity akq, final int integer, final boolean boolean5) {
    }
    
    public void onCraftedBy(final ItemStack ben, final Level bjw, final Player ayj) {
    }
    
    public boolean isComplex() {
        return false;
    }
    
    public UseAnim getUseAnimation(final ItemStack ben) {
        return ben.getItem().isEdible() ? UseAnim.EAT : UseAnim.NONE;
    }
    
    public int getUseDuration(final ItemStack ben) {
        if (ben.getItem().isEdible()) {
            return this.getFoodProperties().isFastFood() ? 16 : 32;
        }
        return 0;
    }
    
    public void releaseUsing(final ItemStack ben, final Level bjw, final LivingEntity akz, final int integer) {
    }
    
    public void appendHoverText(final ItemStack ben, @Nullable final Level bjw, final List<Component> list, final TooltipFlag bfw) {
    }
    
    public Component getName(final ItemStack ben) {
        return new TranslatableComponent(this.getDescriptionId(ben), new Object[0]);
    }
    
    public boolean isFoil(final ItemStack ben) {
        return ben.isEnchanted();
    }
    
    public Rarity getRarity(final ItemStack ben) {
        if (!ben.isEnchanted()) {
            return this.rarity;
        }
        switch (this.rarity) {
            case COMMON:
            case UNCOMMON: {
                return Rarity.RARE;
            }
            case RARE: {
                return Rarity.EPIC;
            }
            default: {
                return this.rarity;
            }
        }
    }
    
    public boolean isEnchantable(final ItemStack ben) {
        return this.getMaxStackSize() == 1 && this.canBeDepleted();
    }
    
    protected static HitResult getPlayerPOVHitResult(final Level bjw, final Player ayj, final ClipContext.Fluid b) {
        final float float4 = ayj.xRot;
        final float float5 = ayj.yRot;
        final Vec3 cvl6 = ayj.getEyePosition(1.0f);
        final float float6 = Mth.cos(-float5 * 0.017453292f - 3.1415927f);
        final float float7 = Mth.sin(-float5 * 0.017453292f - 3.1415927f);
        final float float8 = -Mth.cos(-float4 * 0.017453292f);
        final float float9 = Mth.sin(-float4 * 0.017453292f);
        final float float10 = float7 * float8;
        final float float11 = float9;
        final float float12 = float6 * float8;
        final double double14 = 5.0;
        final Vec3 cvl7 = cvl6.add(float10 * 5.0, float11 * 5.0, float12 * 5.0);
        return bjw.clip(new ClipContext(cvl6, cvl7, ClipContext.Block.OUTLINE, b, ayj));
    }
    
    public int getEnchantmentValue() {
        return 0;
    }
    
    public void fillItemCategory(final CreativeModeTab bdd, final NonNullList<ItemStack> fy) {
        if (this.allowdedIn(bdd)) {
            fy.add(new ItemStack(this));
        }
    }
    
    protected boolean allowdedIn(final CreativeModeTab bdd) {
        final CreativeModeTab bdd2 = this.getItemCategory();
        return bdd2 != null && (bdd == CreativeModeTab.TAB_SEARCH || bdd == bdd2);
    }
    
    @Nullable
    public final CreativeModeTab getItemCategory() {
        return this.category;
    }
    
    public boolean isValidRepairItem(final ItemStack ben1, final ItemStack ben2) {
        return false;
    }
    
    public Multimap<String, AttributeModifier> getDefaultAttributeModifiers(final EquipmentSlot akv) {
        return HashMultimap.create();
    }
    
    public boolean useOnRelease(final ItemStack ben) {
        return ben.getItem() == Items.CROSSBOW;
    }
    
    public ItemStack getDefaultInstance() {
        return new ItemStack(this);
    }
    
    public boolean is(final Tag<Item> aaz) {
        return aaz.contains(this);
    }
    
    public boolean isEdible() {
        return this.foodProperties != null;
    }
    
    @Nullable
    public FoodProperties getFoodProperties() {
        return this.foodProperties;
    }
    
    public SoundEvent getDrinkingSound() {
        return SoundEvents.GENERIC_DRINK;
    }
    
    public SoundEvent getEatingSound() {
        return SoundEvents.GENERIC_EAT;
    }
    
    static {
        BY_BLOCK = Maps.newHashMap();
        PROPERTY_DAMAGED = ((ben, bjw, akz) -> ben.isDamaged() ? 1.0f : 0.0f);
        PROPERTY_DAMAGE = ((ben, bjw, akz) -> Mth.clamp(ben.getDamageValue() / (float)ben.getMaxDamage(), 0.0f, 1.0f));
        PROPERTY_LEFTHANDED = ((ben, bjw, akz) -> (akz == null || akz.getMainArm() == HumanoidArm.RIGHT) ? 0.0f : 1.0f);
        PROPERTY_COOLDOWN = ((ben, bjw, akz) -> (akz instanceof Player) ? akz.getCooldowns().getCooldownPercent(ben.getItem(), 0.0f) : 0.0f);
        PROPERTY_CUSTOM_MODEL_DATA = ((ben, bjw, akz) -> ben.hasTag() ? ((float)ben.getTag().getInt("CustomModelData")) : 0.0f);
        BASE_ATTACK_DAMAGE_UUID = UUID.fromString("CB3F55D3-645C-4F38-A497-9C13A33DB5CF");
        BASE_ATTACK_SPEED_UUID = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3");
        random = new Random();
    }
    
    public static class Properties {
        private int maxStackSize;
        private int maxDamage;
        private Item craftingRemainingItem;
        private CreativeModeTab category;
        private Rarity rarity;
        private FoodProperties foodProperties;
        
        public Properties() {
            this.maxStackSize = 64;
            this.rarity = Rarity.COMMON;
        }
        
        public Properties food(final FoodProperties bak) {
            this.foodProperties = bak;
            return this;
        }
        
        public Properties stacksTo(final int integer) {
            if (this.maxDamage > 0) {
                throw new RuntimeException("Unable to have damage AND stack.");
            }
            this.maxStackSize = integer;
            return this;
        }
        
        public Properties defaultDurability(final int integer) {
            return (this.maxDamage == 0) ? this.durability(integer) : this;
        }
        
        public Properties durability(final int integer) {
            this.maxDamage = integer;
            this.maxStackSize = 1;
            return this;
        }
        
        public Properties craftRemainder(final Item bei) {
            this.craftingRemainingItem = bei;
            return this;
        }
        
        public Properties tab(final CreativeModeTab bdd) {
            this.category = bdd;
            return this;
        }
        
        public Properties rarity(final Rarity bfa) {
            this.rarity = bfa;
            return this;
        }
    }
}
