package org.bukkit.craftbukkit.inventory;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.server.NBTTagCompound;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.koloboke.collect.map.hash.HashIntObjMaps;
import com.koloboke.collect.map.hash.HashObjIntMaps;
@DelegateDeserialization(SerializableMeta.class)
class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorageMeta {
static final ItemMetaKey STORED_ENCHANTMENTS = new ItemMetaKey("StoredEnchantments", "stored-enchants");
private Map<Enchantment, Integer> enchantments;
CraftMetaEnchantedBook(CraftMetaItem meta) {
super(meta);
if (!(meta instanceof CraftMetaEnchantedBook)) {
return;
}
CraftMetaEnchantedBook that = (CraftMetaEnchantedBook) meta;
if (that.hasEnchants()) {
this.enchantments = HashObjIntMaps.newMutableMap(that.enchantments);
}
}
CraftMetaEnchantedBook(NBTTagCompound tag) {
super(tag);
if (!tag.hasKey(STORED_ENCHANTMENTS.NBT)) {
return;
}
enchantments = buildEnchantments(tag, STORED_ENCHANTMENTS);
}
CraftMetaEnchantedBook(Map<String, Object> map) {
super(map);
enchantments = buildEnchantments(map, STORED_ENCHANTMENTS);
}
@Override
void applyToItem(NBTTagCompound itemTag) {
super.applyToItem(itemTag);
applyEnchantments(enchantments, itemTag, STORED_ENCHANTMENTS);
}
@Override
boolean applicableTo(Material type) {
switch (type) {
case ENCHANTED_BOOK:
return true;
default:
return false;
}
}
@Override
boolean isEmpty() {
return super.isEmpty() && isEnchantedEmpty();
}
@Override
boolean equalsCommon(CraftMetaItem meta) {
if (!super.equalsCommon(meta)) {
return false;
}
if (meta instanceof CraftMetaEnchantedBook) {
CraftMetaEnchantedBook that = (CraftMetaEnchantedBook) meta;
return (hasStoredEnchants() ? that.hasStoredEnchants() && this.enchantments.equals(that.enchantments) : !that.hasStoredEnchants());
}
return true;
}
@Override
boolean notUncommon(CraftMetaItem meta) {
return super.notUncommon(meta) && (meta instanceof CraftMetaEnchantedBook || isEnchantedEmpty());
}
@Override
int applyHash() {
final int original;
int hash = original = super.applyHash();
if (hasStoredEnchants()) {
hash = 61 * hash + enchantments.hashCode();
}
return original != hash ? CraftMetaEnchantedBook.class.hashCode() ^ hash : hash;
}
@Override
public CraftMetaEnchantedBook clone() {
CraftMetaEnchantedBook meta = (CraftMetaEnchantedBook) super.clone();
if (this.enchantments != null) {
meta.enchantments = HashObjIntMaps.newMutableMap(this.enchantments);
}
return meta;
}
@Override
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
serializeEnchantments(enchantments, builder, STORED_ENCHANTMENTS);
return builder;
}
boolean isEnchantedEmpty() {
return !hasStoredEnchants();
}
@Override
public boolean hasStoredEnchant(Enchantment ench) {
return hasStoredEnchants() && enchantments.containsKey(ench);
}
@Override
public int getStoredEnchantLevel(Enchantment ench) {
Integer level = hasStoredEnchants() ? enchantments.get(ench) : null;
if (level == null) {
return 0;
}
return level;
}
@Override
public Map<Enchantment, Integer> getStoredEnchants() {
return hasStoredEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.<Enchantment, Integer>of();
}
@Override
public boolean addStoredEnchant(Enchantment ench, int level, boolean ignoreRestrictions) {
if (enchantments == null) {
enchantments = HashObjIntMaps.newMutableMap(4);
}
if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) {
Integer old = enchantments.put(ench, level);
return old == null || old != level;
}
return false;
}
@Override
public boolean removeStoredEnchant(Enchantment ench) {
return hasStoredEnchants() && enchantments.remove(ench) != null;
}
@Override
public boolean hasStoredEnchants() {
return !(enchantments == null || enchantments.isEmpty());
}
@Override
public boolean hasConflictingStoredEnchant(Enchantment ench) {
return checkConflictingEnchants(enchantments, ench);
}
}