package cz.cuni.amis.pogamut.ut2004.communication.translator.itemdescriptor;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ItemCategory;

/**
 * A parent of all item descriptors.
 * 
 * Contains attributes common for all descriptors plus some common functions.
 * 
 * @author Ondrej, knight
 */
public abstract class ItemDescriptor {
    
	private int amount;
        
    private String inventoryType;
        
    private String pickupType;
        
    private ItemType.Category itemCategory; 
               
	public int getAmount() {
		return amount;
	}

    public String getInventoryType()
    {
        return inventoryType;
    }
    
    public String getPickupType()
    {
        return pickupType;
    }
    
    public ItemType.Category getItemCategory()
    {
        return itemCategory;
    }        

	/**
	 * Converts a fully qualified field name (e.g. private boolean cz.cuni.amis.MyClass.myBoolean)
	 * to a field name (e.g. myBoolean).
	 * 
	 * @param string - complete identifier of a field in a class
	 * @return name of a field
	 */
	protected String fieldToName(String string) {
		String result = string.substring(string.lastIndexOf(".") + 1);
		return firstCharToUpperCase(result);
	}
	
	protected String firstCharToUpperCase(String input) {
		return input.substring(0,1).toUpperCase() + input.substring(1);
	}

	/**
	 * This method does the mapping from a map of attributes contained it ITCMsg and the attributes of the descriptor.
	 * 
	 * NOTE: names of the attributes must be equal to the keys of the HashMap contained in ITCMsg.
	 * 
	 * @param configMsg
	 */
	protected void doReflexion(Object configMsg, Class<? extends ItemDescriptor> clazz) {
		Field[] configMsgFields = configMsg.getClass().getDeclaredFields();
		Map<String, Field> configMsgFieldsMap = new HashMap<String, Field>();
		for (Field field : configMsgFields) {
			configMsgFieldsMap.put(field.getName(), field);
		}
		Field[] descFields = clazz.getDeclaredFields();
		Field descField;
		for (int i = 0; i < descFields.length; ++i) {
			if (!descFields[i].isAnnotationPresent(ItemDescriptorField.class)) continue;
			descField = descFields[i];
			descField.setAccessible(true);
			String key = fieldToName(descField.toString());
			Field configField = configMsgFieldsMap.get(key);
			try {
				if (configField == null) {
					descField.set(this, null);
				} else {
					configField.setAccessible(true);
					descField.set(this, configField.get(configMsg));
					configField.setAccessible(false);
				}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} finally {
				descField.setAccessible(false);
			}
		}
	}
	
	public abstract String toString();

}
