package org.ultramine.mods.hawkeye;

import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;

import java.util.HashMap;
import java.util.Map;

import org.ultramine.mods.hawkeye.entry.BlockChangeEntry;
import org.ultramine.mods.hawkeye.entry.BlockBreakEntry;
import org.ultramine.mods.hawkeye.entry.ContainerEntry;
import org.ultramine.mods.hawkeye.entry.DataEntry;

/**
 * Enumeration class representing all the different actions that HawkEye can
 * handle
 * 
 * @author oliverw92
 */
public enum DataType
{
	BLOCK_BREAK(0, BlockBreakEntry.class, "block-break", true, true),
	MACHINE_BREAK(1, BlockBreakEntry.class, "machine-break", true, true),
	ENTITY_BREAK(2, BlockBreakEntry.class, "entity-break", true, true),
	UNKNOWN_BREAK(3, BlockBreakEntry.class, "unknown-break", true, true),
	EXPLOSION(4, BlockBreakEntry.class, "explosion", true, true),
	BLOCK_BURN(5, BlockBreakEntry.class, "block-burn", true, true),
	LEAF_DECAY(6, BlockBreakEntry.class, "leaf-decay", true, true),

	BLOCK_PLACE(10, BlockChangeEntry.class, "block-place", true, true),
	MACHINE_PLACE(11, BlockChangeEntry.class, "machine-place", true, true),
	ENTITY_PLACE(12, BlockChangeEntry.class, "entity-place", true, true),
	UNKNOWN_PLACE(13, BlockChangeEntry.class, "unknown-place", true, true),
	BLOCK_FORM(14, BlockChangeEntry.class, "block-form", true, true),
	BLOCK_FADE(15, BlockChangeEntry.class, "block-fade", true, true),
	LIQUID_FLOW(16, BlockChangeEntry.class, "liquid-flow", true, true),
	GROW(17, BlockChangeEntry.class, "grow", true, true),
	PLAYER_GROW(18, BlockChangeEntry.class, "player-grow", true, true),

	CHAT(20, DataEntry.class, "chat", false, false),
	COMMAND(21, DataEntry.class, "command", false, false),
	JOIN(22, DataEntry.class, "join", false, false),
	QUIT(23, DataEntry.class, "quit", false, false),
	BLOCK_INTERACT(24, DataEntry.class, "block-interact", true, false),
	PVP_DEATH(25, DataEntry.class, "pvp-death", false, false),
	MOB_DEATH(26, DataEntry.class, "mob-death", false, false),
	OTHER_DEATH(27, DataEntry.class, "other-death", false, false),
	ITEM_DROP(28, DataEntry.class, "item-drop", true, false),
	ITEM_PICKUP(29, DataEntry.class, "item-pickup", true, false),
	CONTAINER_TRANSACTION(30, ContainerEntry.class, "container-transaction", true, true),
	HANGING_BREAK(31, DataEntry.class, "hanging-break", true, false),
	HANGING_PLACE(32, DataEntry.class, "hanging-place", true, false),
	ENTITY_KILL(33, DataEntry.class, "entity-kill", false, false),

	OTHER(34, DataEntry.class, "other", false, false),
	REGION_ACTION(35, DataEntry.class, "region-action", true, false);

	private final int id;
	private final boolean canHere;
	private final String configName;
	private final boolean canRollback;
	private final Class<?> entryClass;

	private static final Map<String, DataType> nameMapping = new HashMap<String, DataType>();
	private static final TIntObjectMap<DataType> idMapping = new TIntObjectHashMap<DataType>();

	static
	{
		for(DataType type : values())
		{
			nameMapping.put(type.configName, type);
		}
		for(DataType type : values())
		{
			idMapping.put(type.id, type);
		}
	}

	private DataType(int id, Class<?> entryClass, String configName, boolean canHere, boolean canRollback)
	{
		this.id = id;
		this.entryClass = entryClass;
		this.canHere = canHere;
		this.configName = configName;
		this.canRollback = canRollback;
	}

	/**
	 * Get the id of the DataType
	 * 
	 * @return int id of the DataType
	 */
	public int getId()
	{
		return id;
	}

	/**
	 * Get the config name of the DataType
	 * 
	 * @return String config name
	 */
	public String getConfigName()
	{
		return configName;
	}

	/**
	 * Get the class to be used for DataEntry
	 * 
	 * @return String name of entry class
	 */
	public Class<?> getEntryClass()
	{
		return entryClass;
	}

	/**
	 * Get a matching DataType from the supplied config name
	 * 
	 * @param name
	 *            DataType config name to search for
	 * @return {@link DataType}
	 */
	public static DataType fromName(String name)
	{
		return nameMapping.get(name);
	}

	/**
	 * Get a matching DataType from the supplied id
	 * 
	 * @param id
	 *            DataType id to search for
	 * @return {@link DataType}
	 */
	public static DataType fromId(int id)
	{
		return idMapping.get(id);
	}

	/**
	 * Check if the DataType can be rolled back
	 * 
	 * @return true if it can be, false if not
	 */
	public boolean canRollback()
	{
		return canRollback;
	}

	/**
	 * Check if the DataType can be used in 'here' searches
	 * 
	 * @return true if it can be, false if not
	 */
	public boolean canHere()
	{
		return canHere;
	}

}
