package de.dass_it.vanhelsing.gui;

import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import edu.emory.mathcs.backport.java.util.Collections;

import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.Locale;
import java.util.HashMap;

//import org.apache.log4j.Logger;

/**
 * Helper class to encapsulate common bean methods.
 * Managed beans will extend this class either directly or 
 * via a data structure helper class like TreeNavigation
 * @author tgoecke
 */
public class BeanUtil {
	// Logging

	// protected final Logger logger = Logger.getLogger(this.getClass());

	// Messagebundles
	/**
	 * getter method for a property value
	 * @param key	key of the queried property, e.g. director.client.name.type
	 * @return s	value of the property
	 */
	public static String getProperty(String key) {
		String s = PropertyBundle.getProperty(key);
		return s;
	}
	/**
	 * convenience method to return all properties of a given attribute
	 * @param key	key contains the key value of the set of properties for a given attribute<br/>
	 * 				except for the suffix which defines the content type of the property.
	 * @return	bundle	contains all four properties of an attribute
	 */
	public static String[] getProperties(String key) {
		String[] suffix = { "ref", "type", "required", "def" };
		String[] bundle = new String[4];
		for (int i = 0; i < 4; i++) {
			bundle[i] = BeanUtil.getProperty(key + "." + suffix[i]);
		}
		return bundle;
	}
	/**
	 * returns true if the given attribute is required
	 * @param type	resource type of the attribute, like Client
	 * @param key	attribute name of the resource, like Port
	 * @return		true if the field is required
	 */
	public static boolean getRequired(String type, String key) {
		String s = getFieldProperty(type, key, 2);
		if (s == null) return false;
		if (s.equals("true"))
			return true;
		return false;
	}
	/**
	 * returns the data type of a given attribute.
	 * @param type	resource type of the attribute, like Client
	 * @param key	attribute name of the resource, like Port
	 * @return		data type of the attribute
	 */
	public static String getDataType(String type, String key) {
		return getFieldProperty(type, key, 1);
	}

	// getRenderer returns rendererType based on properties
	/**
	 * returns the renderer for a given attribute
	 * @param type	resource type of the attribute, like Client
	 * @param key	attribute name of the resource, like Port
	 * @return		"inputText", "radioGroup" or "selectOneMenu"
	 * 				
	 */
	public static String getRenderer(String type, String key) {
		return getFieldProperty(type, key, 0);
	}
	/**
	 * returns properties for a given attribute depending on the value of i.
	 * One should use the getter method for the property.
	 * @param type	resource type of the attribute, like Client
	 * @param key	attribute name of the resource, like Port
	 * @param i		i maybe between 0 and 3. The return value of the method is selected by the value of i
	 * @return		one of the four properties as a String of a given attribute. 
	 */
	public static String getFieldProperty(String type, String key, int i) {
		String daemon = "director";
		String res = "inputText";
		if (type.startsWith("SD")) {
			daemon = "storagedaemon";
		}
		if (type.startsWith("FD")) {
			daemon = "filedaemon";
		}
		type = type.toLowerCase();
		key = key.toLowerCase();
		key = key.replaceAll(" ", "");
		String result[] = getProperties((daemon + "." + type + "." + key));
		if (result[0] == null) return null;
		if (i == 0) {
			if (result[1].equals("boolean")) {
				return "radioGroup";
			}
			if (!(result[0].equals("0"))) {
				return "selectOneMenu";
			}
			return res;
		}
		if (i == 2)
			return result[2];
		if (i == 1)
			return result[1];
		if (i == 3)
			return result[3];
		return res;
	}

	// Statusmeldungen an den Client
	/**
	 * sends an information type message to the message field at the bottom of the screen
	 * @param client	could contain an identifier of a client. value can be set to null
	 * @param message	the message to be displayed at the clients view
	 */
	public static void setInfoMessage(String client, String message) {
		FacesContext.getCurrentInstance().addMessage(client,
				new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
	}
	/**
	 * sends an error type message to the message field at the bottom of the screen 
	 * @param client	could contain an identifier of a client. value can be set to null
	 * @param message	the message to be displayed at the clients view
	 */
	public static void setErrorMessage(String client, String message) {
		FacesContext.getCurrentInstance()
				.addMessage(
						client,
						new FacesMessage(FacesMessage.SEVERITY_ERROR, message,
								message));
	}

	// Linkout to Bacula documentation
	// ListItemsConfigView
	// ListItemsTopologyView
	// ListItemsJobSchedule

	// GetParameterFromContext
	/**
	 * returns values of a given parameter of the FacesContext
	 * @param name	name of the parameter e.g. the id of a parameter in the view.	
	 * @return 	value of a given parameter
	 */
	public static String getRequestParameter(String name) {
		return (String) FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get(name);
	}
	/**
	 * translation method for resource or object names.
	 * @param type	untranslated name 
	 * @return 		translated name if there is a translation. Otherwise type will be returned.
	 */
	public static String getAccessType(String type) {
		String result = new String();
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("jobdefs", "job");
		map.put("SDStorage", "Storage");
		map.put("Storage", "SDStorage");
		map.put("SDDevice", "Device");
		map.put("Device", "SDDevice");
		map.put("SDDevice", "Device");
		result = map.get(type);
		if (result != null)
			return result;
		return type;
	}
	/**
	 * 
	 * @param key	resource name
	 * @return newRes	ArrayList of ViewItem
	 */
	public static ArrayList<ViewItem> getTypeProperties(String key){
		ArrayList<ViewItem> newRes = new ArrayList<ViewItem>();
		ArrayList<ViewItem> newOptRes = new ArrayList<ViewItem>();
		ArrayList<String> properties = PropertyBundle.getTypeAttributes("director."+key);
		
		System.err.println(properties.size());
		ViewItem vi;
		for (String s : properties){
			vi = new ViewItem();
			vi.setRequired(BeanUtil.getRequired(key, s));
			vi.setDataType(BeanUtil.getDataType(key, s));
			vi.setKey(s);
			vi.setRenderer(BeanUtil.getRenderer(key, s));
			vi.setKeyValue(BeanUtil.getFieldProperty(key, s, 3));
			if (vi.getRequired()){
				newRes.add(vi);
			} else {
				newOptRes.add(vi);
			}
		}
		newRes.addAll(newOptRes);
		return newRes;
	}
}
