package edu.uprm.walsaip.vte.core;

import static java.lang.System.err;
import java.util.HashMap;
import java.util.Map;
/**
 * 
 * Generic module factory class. 
 * 
 * @author Ricardo Veguilla
 *
 * @param <ModuleType> Type of the object to be created by this factory.
 */
public class ModuleFactory<ModuleType extends Module> {

		protected Map<String, ModuleInfo<? extends ModuleType>> moduleMap;
		protected Map<Integer, ModuleInfo<? extends ModuleType>> moduleMapByOrder;
		protected int numModules = 0;
		
		public ModuleFactory() {
			moduleMap = new HashMap<String, ModuleInfo<? extends ModuleType>>();
			moduleMapByOrder = new HashMap<Integer, ModuleInfo<? extends ModuleType>>();
		}
/**
 * Register a new module with this factory. 
 * @param info ModuleInfo object describing the module. 
 */
		public void registerModule(ModuleInfo<? extends ModuleType> info) {
			
			moduleMap.put(info.getKey(), info);
			moduleMapByOrder.put(numModules++, info);
			
		}
/**
 * Request a module instance by its registered key (name).
 * @param key Name of the module to be created.
 * @return An instance of the requested module.
 */
		public  ModuleType getModule(String key)  {
			
			if (moduleMap.containsKey(key)) {

				try {
					return  moduleMap.get(key).getModuleClass().newInstance();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			} else
				err.println("No module found for key: " + key);
			return null;
		}
/**
 * Request a module instance by registry order.
 * @param num Number of the module to be created.
 * @return An instance of the requested module. 
 */
		public  ModuleType getModule(int num)  {
			
			if (moduleMapByOrder.containsKey(num)) {

				try {
					return  moduleMapByOrder.get(num).getModuleClass().newInstance();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			} else
				err.println("No module found for key: " + num);
			return null;
		}

	}
