/FileExtraction/Java_unseen/Wind-Development_WindSpigot/WindSpigot-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
package org.bukkit.craftbukkit.inventory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap.Builder;

import net.minecraft.server.NBTTagCompound;
import net.minecraft.server.NBTTagList;

@DelegateDeserialization(SerializableMeta.class)
class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
	static final ItemMetaKey AMPLIFIER = new ItemMetaKey("Amplifier", "amplifier");
	static final ItemMetaKey AMBIENT = new ItemMetaKey("Ambient", "ambient");
	static final ItemMetaKey DURATION = new ItemMetaKey("Duration", "duration");
	static final ItemMetaKey SHOW_PARTICLES = new ItemMetaKey("ShowParticles", "has-particles");
	static final ItemMetaKey POTION_EFFECTS = new ItemMetaKey("CustomPotionEffects", "custom-effects");
	static final ItemMetaKey ID = new ItemMetaKey("Id", "potion-id");

	private List<PotionEffect> customEffects;

	CraftMetaPotion(CraftMetaItem meta) {
		super(meta);
		if (!(meta instanceof CraftMetaPotion)) {
			return;
		}
		CraftMetaPotion potionMeta = (CraftMetaPotion) meta;
		if (potionMeta.hasCustomEffects()) {
			this.customEffects = new ArrayList<PotionEffect>(potionMeta.customEffects);
		}
	}

	CraftMetaPotion(NBTTagCompound tag) {
		super(tag);

		if (tag.hasKey(POTION_EFFECTS.NBT)) {
			NBTTagList list = tag.getList(POTION_EFFECTS.NBT, 10);
			int length = list.size();
			customEffects = new ArrayList<PotionEffect>(length);

			for (int i = 0; i < length; i++) {
				NBTTagCompound effect = list.get(i);
				PotionEffectType type = PotionEffectType.getById(effect.getByte(ID.NBT));
				int amp = effect.getByte(AMPLIFIER.NBT);
				int duration = effect.getInt(DURATION.NBT);
				boolean ambient = effect.getBoolean(AMBIENT.NBT);
				boolean particles = effect.getBoolean(SHOW_PARTICLES.NBT);
				customEffects.add(new PotionEffect(type, duration, amp, ambient, particles));
			}
		}
	}

	CraftMetaPotion(Map<String, Object> map) {
		super(map);

		Iterable<?> rawEffectList = SerializableMeta.getObject(Iterable.class, map, POTION_EFFECTS.BUKKIT, true);
		if (rawEffectList == null) {
			return;
		}

		for (Object obj : rawEffectList) {
			if (!(obj instanceof PotionEffect)) {
				throw new IllegalArgumentException("Object in effect list is not valid. " + obj.getClass());
			}
			addCustomEffect((PotionEffect) obj, true);
		}
	}

	@Override
	void applyToItem(NBTTagCompound tag) {
		super.applyToItem(tag);
		if (customEffects != null) {
			NBTTagList effectList = new NBTTagList();
			tag.set(POTION_EFFECTS.NBT, effectList);

			for (PotionEffect effect : customEffects) {
				NBTTagCompound effectData = new NBTTagCompound();
				effectData.setByte(ID.NBT, (byte) effect.getType().getId());
				effectData.setByte(AMPLIFIER.NBT, (byte) effect.getAmplifier());
				effectData.setInt(DURATION.NBT, effect.getDuration());
				effectData.setBoolean(AMBIENT.NBT, effect.isAmbient());
				effectData.setBoolean(SHOW_PARTICLES.NBT, effect.hasParticles());
				effectList.add(effectData);
			}
		}
	}

	@Override
	boolean isEmpty() {
		return super.isEmpty() && isPotionEmpty();
	}

	boolean isPotionEmpty() {
		return !(hasCustomEffects());
	}

	@Override
	boolean applicableTo(Material type) {
		switch (type) {
		case POTION:
			return true;
		default:
			return false;
		}
	}

	@Override
	public CraftMetaPotion clone() {
		CraftMetaPotion clone = (CraftMetaPotion) super.clone();
		if (this.customEffects != null) {
			clone.customEffects = new ArrayList<PotionEffect>(this.customEffects);
		}
		return clone;
	}

	@Override
	public boolean hasCustomEffects() {
		return customEffects != null;
	}

	@Override
	public List<PotionEffect> getCustomEffects() {
		if (hasCustomEffects()) {
			return ImmutableList.copyOf(customEffects);
		}
		return ImmutableList.of();
	}

	@Override
	public boolean addCustomEffect(PotionEffect effect, boolean overwrite) {
		Validate.notNull(effect, "Potion effect must not be null");

		int index = indexOfEffect(effect.getType());
		if (index != -1) {
			if (overwrite) {
				PotionEffect old = customEffects.get(index);
				if (old.getAmplifier() == effect.getAmplifier() && old.getDuration() == effect.getDuration()
						&& old.isAmbient() == effect.isAmbient()) {
					return false;
				}
				customEffects.set(index, effect);
				return true;
			} else {
				return false;
			}
		} else {
			if (customEffects == null) {
				customEffects = new ArrayList<PotionEffect>();
			}
			customEffects.add(effect);
			return true;
		}
	}

	@Override
	public boolean removeCustomEffect(PotionEffectType type) {
		Validate.notNull(type, "Potion effect type must not be null");

		if (!hasCustomEffects()) {
			return false;
		}

		boolean changed = false;
		Iterator<PotionEffect> iterator = customEffects.iterator();
		while (iterator.hasNext()) {
			PotionEffect effect = iterator.next();
			if (effect.getType() == type) {
				iterator.remove();
				changed = true;
			}
		}
		if (customEffects.isEmpty()) {
			customEffects = null;
		}
		return changed;
	}

	@Override
	public boolean hasCustomEffect(PotionEffectType type) {
		Validate.notNull(type, "Potion effect type must not be null");
		return indexOfEffect(type) != -1;
	}

	@Override
	public boolean setMainEffect(PotionEffectType type) {
		Validate.notNull(type, "Potion effect type must not be null");
		int index = indexOfEffect(type);
		if (index == -1 || index == 0) {
			return false;
		}

		PotionEffect old = customEffects.get(0);
		customEffects.set(0, customEffects.get(index));
		customEffects.set(index, old);
		return true;
	}

	private int indexOfEffect(PotionEffectType type) {
		if (!hasCustomEffects()) {
			return -1;
		}

		for (int i = 0; i < customEffects.size(); i++) {
			if (customEffects.get(i).getType().equals(type)) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public boolean clearCustomEffects() {
		boolean changed = hasCustomEffects();
		customEffects = null;
		return changed;
	}

	@Override
	int applyHash() {
		final int original;
		int hash = original = super.applyHash();
		if (hasCustomEffects()) {
			hash = 73 * hash + customEffects.hashCode();
		}
		return original != hash ? CraftMetaPotion.class.hashCode() ^ hash : hash;
	}

	@Override
	public boolean equalsCommon(CraftMetaItem meta) {
		if (!super.equalsCommon(meta)) {
			return false;
		}
		if (meta instanceof CraftMetaPotion) {
			CraftMetaPotion that = (CraftMetaPotion) meta;

			return (this.hasCustomEffects() ? that.hasCustomEffects() && this.customEffects.equals(that.customEffects)
					: !that.hasCustomEffects());
		}
		return true;
	}

	@Override
	boolean notUncommon(CraftMetaItem meta) {
		return super.notUncommon(meta) && (meta instanceof CraftMetaPotion || isPotionEmpty());
	}

	@Override
	Builder<String, Object> serialize(Builder<String, Object> builder) {
		super.serialize(builder);

		if (hasCustomEffects()) {
			builder.put(POTION_EFFECTS.BUKKIT, ImmutableList.copyOf(this.customEffects));
		}

		return builder;
	}
}
