package lu.tudor.santec.gecamed.letter.gui.placeholders;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.Vector;

import lu.tudor.santec.gecamed.addressbook.ejb.entity.beans.Contact;
import lu.tudor.santec.gecamed.core.gui.controller.document.DocumentController;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.letter.ejb.entity.beans.LetterPlaceholder;
import lu.tudor.santec.gecamed.letter.ejb.session.beans.LetterPlaceholderBean;
import lu.tudor.santec.gecamed.letter.ejb.session.interfaces.LetterPlaceholderInterface;

import org.apache.log4j.Logger;

public class PlaceholdersConfig
{
	/* ======================================== */
	// 		CONSTANTS
	/* ======================================== */
	
	public static final String	CATEGORY_CONTACT	= OldPlaceholdersConfig.CATEGORY_CONTACT;
	
	
	
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(PlaceholdersConfig.class.getName());
	
	public static Map<String, String> old2NewMap;
	
	
	
	/* ======================================== */
	// 		LINKING METHODS
	/* ======================================== */
	
	/**
	 * <b>NOTICE:</b> <i>This method is only supported for placeholder version 0, 
	 * as the newer once need to get the exact placeholder names and will not 
	 * fetch the values of all existing placeholders (of a category).</i> 
	 * 
	 * @param category The category to search for. Use <code>null</code> to generate for all categories 
	 * @param contact The contact information to get information from
	 * @param version The placeholder version
	 * @return A map with all placeholders as keys and its values
	 */
	public static HashMap<String, String> generateCategory (String category, Contact contact, int version)
	{
		if (version == DocumentController.PH_VERSION_NEW)
			throw new BadVersionException("Placeholder version "+version+" does not support the generateCategory(String,Contact,int) method!\n" +
					"Please use getPlaceholdersMap(List,Collection,int) instead.");
		else if (version == DocumentController.PH_VERSION_OLD)
			return OldPlaceholdersConfig.generateCategory(category, contact);
		else
			throw new BadVersionException(version);
	}
	
	
	/**
	 * <b>NOTICE:</b> <i>This method is only supported for placeholder version 0, 
	 * as the newer once need to get the exact placeholder names and will not 
	 * fetch the values of all existing placeholders (of a category).</i> 
	 * 
	 * @param contact
	 * @param version
	 * @return
	 */
	public static Map<String, String> getPlaceholdersMap (Contact contact, int version)
	{
		if (version == DocumentController.PH_VERSION_NEW)
			throw new BadVersionException("Placeholder version "+version+" does not support the getPlaceholdersMap(Contact,int) method!\n" +
					"Please use getPlaceholdersMap(List,Collection,int) instead.");
		else if (version == DocumentController.PH_VERSION_OLD)
			return OldPlaceholdersConfig.getPlaceholdersMap(contact);
		else
			throw new BadVersionException(version);
	}
	
	
	/**
	 * <b>NOTICE:</b> <i>This method is only supported for placeholder version 1 and higher, 
	 * as the old version does not support multiple contacts.</i> 
	 * 
	 * @param contacts All contacts to send to
	 * @param placeholders The placeholders existing in the text
	 * @param version The placeholder version
	 * @return A map with all placeholders as keys and its values
	 */
	public static Map<String, String> getPlaceholdersMap(List<Contact> contacts, Collection<String> placeholders, int version) throws WrongJavaVersionException, BadVersionException
	{
		if (version == DocumentController.PH_VERSION_NEW)
			return NewPlaceholdersConfig.getPlaceholdersMap(contacts, placeholders);
		else if (version == DocumentController.PH_VERSION_OLD)
			throw new BadVersionException("Multi contacts are not supported by version "+version+".");
		else
			throw new BadVersionException(version);
	}
	
	
	public static String getValue (String key, String category, int version)
	{
		return getValue(key, category, null, version);
	}
	
	
	public static String getValue(String key, String category, Contact contact, int version)
	{
		if (version == DocumentController.PH_VERSION_NEW)
			return NewPlaceholdersConfig.getValue(key, category, contact);
		else if (version == DocumentController.PH_VERSION_OLD)
			return OldPlaceholdersConfig.getValue(key, category, contact);
		else
			throw new BadVersionException(version);
	}
	
	
	public static List<String> getContactPlaceholders (int version)
	{
		if (version == DocumentController.PH_VERSION_NEW)
			return NewPlaceholdersConfig.getContactPlaceholders();
		else if (version == DocumentController.PH_VERSION_OLD)
			return OldPlaceholdersConfig.getPlaceHolders().get(OldPlaceholdersConfig.CATEGORY_CONTACT);
		else
			throw new BadVersionException(version);
	}
	
	
	/**
	 * @return All placeholders of the latest placeholder version.
	 */
	public static HashMap<String, List<String>> getPlaceHolderNames ()
	{
		return NewPlaceholdersConfig.getPlaceHolderNames();
	}
	
	
	public static HashMap<String, Vector<String>> getOldPlaceHolderNames ()
	{
		return OldPlaceholdersConfig.getPlaceHolders();
	}
	
	
	/**
	 * @return All placeholders of the latest placeholder version.
	 */
	public static HashMap<String, List<LetterPlaceholder>> getPlaceHolders ()
	{
		return NewPlaceholdersConfig.getPlaceHolders();
	}
	
	
	/**
	 * @return The placeholder categories of the latest placeholder version
	 */
	public static List<String> getPlaceHolderCategories ()
	{
		return NewPlaceholdersConfig.getPlaceHolderCategories();
	}
	
	
	public static LetterPlaceholderInterface getManager ()
	{
		return NewPlaceholdersConfig.getManager();
	}
	
	
	public static Map<String, String> getOld2NewMap ()
	{
		LetterPlaceholderInterface	placeholderManager;
		List<String>				validNames;
		StringBuilder				missingPlaceholders;
		Collection<String>			newPlaceholderNames;
		
		
		if (old2NewMap == null)
		{
			old2NewMap = new HashMap<String, String>();
			
			// Category PATIENT
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_FIRSTNAME,				"[PAT_FIRST_NAMES]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_SURNAME,				"[PAT_LAST_NAME]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_MAIDENNAME,			"[PAT_MAIDEN_NAME]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_TITLE,					"[PAT_TITLE_SHORT]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_PATIENT,				"[PAT_FULL_NAME_AND_ADDRESS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HOMEADDRESS,			"[PAT_FULL_ADDRESS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_SOCIALSECURITYNUMBER,	"[PAT_SSN]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_ACTIVEPROBLEMS,		"[PAT_ACTIVE_PROBLEMS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_ALLERGIES,				"[PAT_ALLERGIES]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_ANTECEDENTS,			"[PAT_ANTECEDENTS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_CHRONICALTREATMENTS,	"[PAT_CHRONIC_TREATMENTS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_LAST_INVOICE_NUMBER,	"[PAT_LAST_INVOICE_NUMBER]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_LAST_INVOICE_DATE,		"[PAT_LAST_INVOICE_DATE]");
			// PATIENT_HISTORY
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_LAST_CONSULTATION,		"[PAT_HISTORY_LAST_CONSULTATION]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_3_DAYS,		"[PAT_HISTORY_3_DAYS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_7_DAYS,		"[PAT_HISTORY_7_DAYS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_30_DAYS,		"[PAT_HISTORY_30_DAYS]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_THIS_DAY,		"[PAT_HISTORY_TODAY]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_LAST_DAY,		"[PAT_HISTORY_YESTERDAY]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_THIS_WEEK,		"[PAT_HISTORY_THIS_WEEK]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_LAST_WEEK,		"[PAT_HISTORY_LAST_WEEK]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_THIS_MONTH,	"[PAT_HISTORY_THIS_MONTH]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_LAST_MONTH,	"[PAT_HISTORY_LAST_MONTH]");
			old2NewMap.put(OldPlaceholdersConfig.PATIENT_HISTORY_ALL,			"[PAT_HISTORY_ALL]");
			
			// Category PHYSICIAN
			old2NewMap.put(OldPlaceholdersConfig.PHYSICIAN_PHYICIAN,			"[PHYS_FULL_NAME]");
			old2NewMap.put(OldPlaceholdersConfig.PHYSICIAN_MOBILEPHONE,			"[PHYS_MOBILE]");
			old2NewMap.put(OldPlaceholdersConfig.PHYSICIAN_PHONE,				"[PHYS_PHONE]");
			old2NewMap.put(OldPlaceholdersConfig.PHYSICIAN_FAX,					"[PHYS_FAX]");
			old2NewMap.put(OldPlaceholdersConfig.PHYSICIAN_UCM,					"[PHYS_CNS_CODE]");
			old2NewMap.put(OldPlaceholdersConfig.PHYSICIAN_ADDRESS,				"[PHYS_FULL_ADDRESS]");
			
			// Category CONTACT
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_NAME,					"[CONT_FULL_NAME]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_ADDRESS,				"[CONT_FULL_ADDRESS]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_ADDRESS_LINE,			"[CONT_FULL_ADDRESS_SINGLE_LINE]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_EMAIL,					"[CONT_EMAIL]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_FAX,					"[CONT_FAX]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_LASTNAME,				"[CONT_LAST_NAME]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_FIRSTNAME,				"[CONT_FIRST_NAMES]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_MOBILEPHONE,			"[CONT_MOBILE]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_PHONE_PRIVATE,			"[CONT_TEL_PRIVATE]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_PHONE_WORK,			"[CONT_TEL_WORK]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_TITLE,					"[CONT_TITLE]");
			old2NewMap.put(OldPlaceholdersConfig.CONTACT_UCM,					"[CONT_CNS_CODE]");
			
			// Category GENERAL
			old2NewMap.put(OldPlaceholdersConfig.GENERAL_DATE,					"[GEN_DATE]");
			old2NewMap.put(OldPlaceholdersConfig.GENERAL_TIME,					"[GEN_TIME]");
		}
		
		
		// check, which placeholders are missing in the database and log them
		newPlaceholderNames	= new TreeSet<String>(old2NewMap.values());
		placeholderManager	= (LetterPlaceholderInterface) ManagerFactory.getRemote(LetterPlaceholderBean.class);
		validNames			= placeholderManager.getPlaceholderNamesByName(newPlaceholderNames);
		
		missingPlaceholders	= null;
		for (String name : newPlaceholderNames)
		{
			if (!validNames.contains(name))
			{
				if (missingPlaceholders == null)
					 missingPlaceholders = new StringBuilder();
				else missingPlaceholders.append("\n");
				missingPlaceholders.append(name);
			}
		}
		
		if (missingPlaceholders != null)
		{
			logger.warn("The following letter placeholder are supposed to replace former used placeholders, " +
					"but they don't exist in the database!" +
					"\n   --------------------\n" + 
					missingPlaceholders.toString() + 
					"\n   --------------------\n");
		}
		
		
		return old2NewMap;
	}
}
