package org.squiddev.plethora.integration.vanilla.meta;

import com.google.common.collect.Maps;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.output.NullOutputStream;
import org.squiddev.plethora.api.meta.BasicMetaProvider;
import org.squiddev.plethora.api.meta.IMetaProvider;
import org.squiddev.plethora.utils.DebugLogger;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

/**
 * Adds basic properties for item stacks.
 */
@IMetaProvider.Inject(ItemStack.class)
public class MetaItemBasic extends BasicMetaProvider<ItemStack> {
	@Nonnull
	@Override
	public Map<Object, Object> getMeta(@Nonnull ItemStack stack) {
		HashMap<Object, Object> data = getBasicProperties(stack);

		String display = stack.getDisplayName();
		data.put("displayName", display == null || display.length() == 0 ? stack.getUnlocalizedName() : display);
		data.put("rawName", stack.getUnlocalizedName());

		data.put("maxCount", stack.getMaxStackSize());
		data.put("maxDamage", stack.getMaxDamage());

		if (stack.getItem().showDurabilityBar(stack)) {
			data.put("durability", stack.getItem().getDurabilityForDisplay(stack));
		}

		return data;
	}

	@Nonnull
	public static HashMap<Object, Object> getBasicProperties(@Nonnull ItemStack stack) {
		HashMap<Object, Object> data = Maps.newHashMap();

		data.put("name", stack.getItem().getRegistryName());
		data.put("damage", stack.getItemDamage());
		data.put("count", stack.stackSize);
		data.put("nbtHash", getNBTHash(stack));

		return data;
	}

	@Nullable
	private static String getNBTHash(@Nonnull ItemStack stack) {
		if (!stack.hasTagCompound() || stack.getTagCompound().hasNoTags()) return null;

		NBTTagCompound tag = stack.getTagCompound();
		try {
			MessageDigest digest = MessageDigest.getInstance("MD5");
			OutputStream dump = new NullOutputStream();
			DigestOutputStream hasher = new DigestOutputStream(dump, digest);
			DataOutput output = new DataOutputStream(hasher);
			CompressedStreamTools.write(tag, output);
			byte[] hash = digest.digest();
			return new String(Hex.encodeHex(hash));
		} catch (NoSuchAlgorithmException e) {
			DebugLogger.error("Cannot hash NBT", e);
			return null;
		} catch (IOException e) {
			DebugLogger.error("Cannot hash NBT", e);
			return null;
		}
	}
}

@@ -89,16 +89,95 @@
 t.Maps;%0A
+import net.minecraft.creativetab.CreativeTabs;%0Aimport net.minecraft.item.Item;%0A
 import n
@@ -294,16 +294,82 @@
 mpound;%0A
+import net.minecraftforge.fml.common.ObfuscationReflectionHelper;%0A
 import o
@@ -1705,16 +1705,304 @@
 );%0A%09%09%7D%0A%0A
+%09%09// tabToDisplayOn%0A%09%09CreativeTabs tab = ObfuscationReflectionHelper.getPrivateValue(Item.class, stack.getItem(), %22field_77701_a%22);%0A%09%09if (tab != null) %7B%0A%09%09%09// tabLabel%0A%09%09%09data.put(%22creativeTab%22, ObfuscationReflectionHelper.getPrivateValue(CreativeTabs.class, tab, %22field_78034_o%22));%0A%09%09%7D%0A%0A
 %09%09return

Add creative tab to item metadata