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

import java.util.HashMap;

import cz.cuni.amis.pogamut.base.exceptions.PogamutRuntimeException;
import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;

/**
 * Main class responsible for the item decoration.
 * <p><p>
 * Items in UT2004 has a lots of characteristics which don't change over the time (at least during one game).
 * As it is pointless to send all those information every time an item is perceived by a bot, those information 
 * are sent through the ITCMsgs (ItemCategory). This message is used in ItemTranslator as a configuration message for an ItemDescriptor.
 * <p><p>
 * ItemDescriptor contains all characteristics available for the corresponding UTClass of items and is returned by the 
 * ItemTranslator. This description is then attached to the item (in fact to all item events like AIN, INV, IPK).
 * <p><p>
 * Now how does it work insight? ItemTranslator uses a set of DescriptorFactories (one for each type of an item).
 * ITCMsg messages are usually sent at the beginning of the game (classes for all items in the map). 
 * But they can arrive in the middle of the game for a new category of an item.
 * 
 * TODO: maybe it is rather ItemDecorator.
 * 
 * @author Ondrej
 */
public class ItemTranslator {
    
    private HashMap<ItemType, ItemDescriptor> descriptors = new HashMap<ItemType, ItemDescriptor>();

	private static ItemTranslator instance = new ItemTranslator();
	
    private ItemTranslator() {};
   
    public static ItemTranslator getInstance() {
    	return instance ;
    }
    
	public ItemType[] getItemTypes() {
		return descriptors.values().toArray(new ItemType[0]);
	}

    public ItemDescriptor getDescriptor(ItemTyped msg) {
		return getDescriptor(msg.getType());
    }
    
    public ItemDescriptor getDescriptor(ItemType type) {
    	return descriptors.get(type);
    }
    
    /**
     * If you create a new item type inside the UT2004 and gamebots will export it, it will
     * be marked as Other category item + Other group and this method will be called to provide a descriptor
     * for that item thus you may subclass this class and override this method to provide your
     * own descriptor for such item.
     * <p><p>
     * Default implementation is using GeneralDescriptor.
     * 
     * @param message
     * @return
     */
    protected ItemDescriptor getOtherDescriptor(ItemTyped message) {
    	return GeneralDescriptorFactory.getInstance().getNewDescriptor(message);
    }
    
    public void createDescriptor(ItemTyped message) {
    	switch(message.getType().getCategory()) {
    	case AMMO:
    		// TODO: [Ondra] provide a descriptor for ammo
    		return;
    	case ARMOR:
    		// TODO: [Ondra] provide a descriptor for the armor
    		return;
    	case OTHER:
    		if (message.getType().getGroup() == ItemType.Group.OTHER) {
    			descriptors.put(message.getType(), getOtherDescriptor(message));
    		} else {
    			// TODO: [Ondra] provide a factory for other item (may be UDamage, Key, etc.)
    			descriptors.put(message.getType(), getOtherDescriptor(message));
    		}
    		return;
    	case HEALTH:
    		// TODO: [Ondra] provide a descriptor for the health
    		return;
    	case ADRENALINE:
    		// TODO: [Ondra] provide a descriptor for the adrenaline
    		return;
    	case WEAPON:
    		descriptors.put(message.getType(), WeaponDescriptorFactory.getInstance().getNewDescriptor(message));
    		return;
    	default:
    		throw new PogamutRuntimeException("should not reach here - new ItemType.Category has been added and not handled inside the ItemTranslator, item type = " + message.getType(), this);    	
    	}
    }
   
}