package lu.tudor.santec.gecamed.address.utils;

import javax.persistence.Transient;

import lu.tudor.santec.gecamed.address.ejb.entity.beans.GECAMedAddressBean;
import lu.tudor.santec.gecamed.address.ejb.session.interfaces.AddressManagerInterface;
import lu.tudor.santec.gecamed.core.utils.BaseFormatter;
import lu.tudor.santec.gecamed.core.utils.StringUtilities;
import lu.tudor.santec.gecamed.core.utils.Translator;
import lu.tudor.santec.gecamed.core.utils.printing.ireport.StringAppender;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

public class AddressFormatter extends BaseFormatter
	{
	private static final long serialVersionUID = 1L;
	
	private Translator m_Translator;

	private AddressManagerInterface	l_Manager;
	
	/**
	 * static logger for this class
	 */
	private static Logger logger = Logger.getLogger(AddressFormatter.class.getName());
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	
	public static final String  c_NotAvailable 	= "AddressFormatter.Unavailable";

//	private static final String c_NewLine = System.getProperty("line.separator");
	private static final String c_NewLine = "\n";

    static 
		{
    	Translatrix.addBundle("lu.tudor.santec.gecamed.address.utils.resources.ServerResources");
		}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public AddressFormatter (AddressManagerInterface p_Manager)	
	{
	super(ORIGINAL);
	l_Manager = p_Manager;
	}

//---------------------------------------------------------------------------

public AddressFormatter (Integer p_PrintMode, AddressManagerInterface p_Manager)	
	{
	super(p_PrintMode);
	l_Manager = p_Manager;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
/**
  * applies the currently applicable print mode to the specified String.
  * @param p_Original specifies the string to apply print mode to.
  * @return a copy of the specified original string formatted according to
  * the currently applicable print mode.
  */
//---------------------------------------------------------------------------

private String applyPrintMode (String p_Original) 
	{
	if ((p_Original == null) || (p_Original.length() == 0)) return p_Original;
	
	switch (printMode) 
		{
		case ORIGINAL		   : return p_Original;
						  
		case CAPITALIZE_WORDS : return StringUtilities.capitalizeWords(p_Original);
	
		case ALL_UPPERCASE	   : return p_Original.toUpperCase();
	
		default                : return p_Original;
		}
	}

//---------------------------------------------------------------------------
/**
 * Translates the name of the foreign country using the language specified
 * for the office country.
 * 
 * @param p_OfficeCountry
 *            specifies the country whose language ought to be used to
 *            translate name of foreign country.
 * @param p_ForeignCountry
 *            specifies the foreign country to get translation for.
 * @return translated name of foreign country.
 */
//---------------------------------------------------------------------------

public String translateCountry (String p_Country) 
	{
	String l_TranslationKey;
	String l_Translation;
	
	l_TranslationKey = "Country." + p_Country.toLowerCase();
	l_Translation    = m_Translator.translate(l_TranslationKey);
	
	if (l_TranslationKey.equals(l_Translation))
		{
		l_Translation = p_Country;
		}
	
	return l_Translation;
    }

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/**
 * sets the print mode applicable for formatting methods.
 * @param printMode specifies the applicable print mode. Possible values are:
 * <ul>
 * <li>ORIGINAL: address fields will be printed as is.
 * <li>CAPITALIZEWORDS: first character of every word in address fields will
 * be printed in capital letters.
 * <li>ALLUPPERCASE: every address field will be printed in uppercase letters.
 * <ul>
 */
//---------------------------------------------------------------------------

public void setPrintMode (Integer p_PrintMode) 
	{
	if ((p_PrintMode >= ORIGINAL) && (p_PrintMode <= ALL_UPPERCASE))
		printMode = p_PrintMode;
	}

//---------------------------------------------------------------------------
/**
 * returns the print mode which is currently set.
 * @return the currently applicable print mode. Possible values are:
 * <ul>
 * <li>ORIGINAL: address fields will be printed as is.
 * <li>CAPITALIZEWORDS: first character of every word in address fields will
 * printed in capital letters.
 * <li>ALLUPPERCASE: every address field will be printed in uppercase letters.
 * <ul>
 * @see #setPrintMode()
 */
//---------------------------------------------------------------------------

public Integer getPrintMode () 
	{
	return printMode;
	}

//---------------------------------------------------------------------------
/**
 * assembles street number and name into a single line, following the convention
 * StreetNr, StreetName.
 */
//---------------------------------------------------------------------------

@Transient
public String formatStreetAddress (GECAMedAddressBean p_Address)
	{	
	StringAppender l_StreetAddress;
	
	if (p_Address == null) return "";
	
	l_StreetAddress = new StringAppender();

	if (   (p_Address.getStreetNumber() != null)
		&& (p_Address.getStreetNumber().length() > 0))
		{
		l_StreetAddress.append(p_Address.getStreetNumber()).append(", ");
		}
	
	l_StreetAddress.append(this.applyPrintMode (p_Address.getStreetName()));
	
	return l_StreetAddress.toString();
	}

//---------------------------------------------------------------------------
/**
 * assembles ZIP code and locality of the specified address into a single line.
 * ZIP code for addresses in Luxembourg will be prefixed with a "L-". 
 * @return a string representation of the ZIP code and the locality of the
 * specified address.
 * <ul>
 * <li><b>L-</b>1234 Locality for an address in Luxembourg
 * <li>12345 Locality for an address outside of Luxembourg
 * </ul>
 */
//---------------------------------------------------------------------------

@Transient
public String formatZipAndLocality (GECAMedAddressBean p_Address)
	{	
	StringAppender			l_ZipAndLocalityLine;
	String					l_PostalCode;
	String					l_Zip;
	
	
	if (p_Address == null) return "";
	
	l_ZipAndLocalityLine = new StringAppender ();
	if(p_Address.getZip() != null) {
		l_Zip = p_Address.getZip().trim();
	} else {
		l_Zip = "";
	}
	
	if (isNumeric(l_Zip))
	{
		if (p_Address.isAddressInLuxembourg()) 
			l_ZipAndLocalityLine.append("L-");
		else
		{
			try {
				l_PostalCode	= l_Manager.getPostalCodeFromCountry(p_Address.getCountry());
				if (l_PostalCode != null && l_PostalCode.length() > 0)
					l_ZipAndLocalityLine.append(l_PostalCode)
					.append("-");					
			} catch (Exception e) {
				logger.warn("Error fetching Postal Code", e);
			}
		}
	}
	
	l_ZipAndLocalityLine.append(l_Zip).append(" ");
	l_ZipAndLocalityLine.append((p_Address.getLocality() != null)?p_Address.getLocality():"");

	return   this.applyPrintMode (l_ZipAndLocalityLine.toString());
	}

//---------------------------------------------------------------------------
/**
 * formats this address instance into a printable address block. 
 * @param p_Abroad specifies whether or not to add the country to the
 * address block. If parameter is set to <code>true</code> the method will
 * add the country at the end of the address block, otherwise the country
 * will be omitted. 
 * @return A printable address block in the following format:
 * STREETNUMBER, STREETNAME
 * ZIP LOCALITY
 * COUNTRY
 * see # formatZipAndLocality()
 */
//---------------------------------------------------------------------------

@Transient	
public String formatAddressBlock (GECAMedAddressBean p_Address, boolean p_IsAbroad)	
	{
	StringAppender l_AddressBlock;
	String		 l_Country;
	
	if (p_Address == null) return "";

	l_AddressBlock = new StringAppender();

	l_AddressBlock.append(this.formatStreetAddress(p_Address));
	l_AddressBlock.append(c_NewLine);
	l_AddressBlock.append(this.formatZipAndLocality(p_Address));
	
	if (p_IsAbroad && (p_Address.getCountry() != null) && (p_Address.getCountry().length() > 0))
		{
		l_Country = this.translateCountry(p_Address.getCountry());
		l_AddressBlock.append(c_NewLine).append(this.applyPrintMode(l_Country));
		}
	
	return l_AddressBlock.toString();
	}

//---------------------------------------------------------------------------
/**
 * formats this address instance into a single printable line. 
 * @return A printable address block in the following format:
 * STREETNUMBER, STREETNAME ZIP LOCALITY, COUNTRY
 * see # formatZipAndLocality()
 */
//---------------------------------------------------------------------------

public String formatAddressLine (GECAMedAddressBean p_Address, boolean p_IsAbroad)	
	{
	StringAppender l_AddressLine;
	
	if (p_Address == null) return "";

	l_AddressLine = new StringAppender();

	l_AddressLine.append(this.formatStreetAddress(p_Address));
	l_AddressLine.append("; ");
	l_AddressLine.append(this.formatZipAndLocality(p_Address));
	
	if (p_IsAbroad && (p_Address.getCountry() != null) && (p_Address.getCountry().length() > 0))
		{
		l_AddressLine.append(", ").append(this.applyPrintMode(p_Address.getCountry()));
		}

	return l_AddressLine.toString();
	}



	private boolean isNumeric(String zip) {
	    if (zip == null || zip.length() == 0) return false;
	    try {
		Long.parseLong(zip);
		return true;
	    } catch (NumberFormatException e) {
		return false;
	    }
	   
	}

	
	public void setTranslator(Translator p_Translator)
	{
		m_Translator = p_Translator;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* End of Class                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	

}
