package lu.tudor.santec.gecamed.address.ejb.entity.beans;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedEntityBean;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.PatientAddress;
import lu.tudor.santec.i18n.Translatrix;

/**
 * Abstract Entity Bean which all Address Entity Beans should inherit from.
 * This class provides an <b>id property which is mapped to the id column of the 
 * referenced db table. This column has to be the primary key of the table</b>.
 * Additionally it provides properties for the address typic fields such as:
 * String streetName;
 * String streetNumber;
 * String zip;
 * String locality;
 * Integer localityId;
 * String country;
 * String type;
 * Date date;
 * 
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 *
 * @version
 * <br>$Log: GECAMedAddressBean.java,v $
 * <br>Revision 1.11  2013-10-31 12:51:14  ferring
 * <br>Adress print style changed
 * <br>
 * <br>Revision 1.10  2013-10-29 13:42:43  ferring
 * <br>bug fixes when showing patient DSPs to link to
 * <br>
 * <br>Revision 1.9  2013-10-28 16:51:59  ferring
 * <br>toString for addresses added
 * <br>
 * <br>Revision 1.8  2010-07-19 12:30:05  troth
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.7  2010-07-19 12:15:22  hermen
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2010-05-18 13:37:27  gbosch
 * <br>changed address sorting
 * <br>
 * <br>Revision 1.5  2010-04-27 14:57:10  mack
 * <br>Added useful helper methods for formatting
 * <br>
 * <br>Revision 1.4  2009-10-07 15:43:33  mack
 * <br>Removed Country prefix of ZIP codes
 * <br>
 * <br>Revision 1.3  2009-06-29 12:43:40  hermen
 * <br>changed getting Zipcode for Printing
 * <br>
 * <br>Revision 1.2  2009-02-11 14:05:53  hermen
 * <br>added management of sites to the office admin tab
 * <br>
 * <br>Revision 1.1  2009-02-04 16:03:11  hermen
 * <br>added bean and table for site and site_address
 * <br>created GECAMedAddressBean which all addresses should extend
 * <br>
 *
 */
@MappedSuperclass
public class GECAMedAddressBean extends GECAMedEntityBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    protected String  streetName;
    protected String  streetNumber;
	protected String  zip;
	protected String  locality;
	protected Integer localityId;
	protected String  country;
	protected String  type;
	protected Date    date;

	private static Pattern 		    
			   LUXEMBOURG = Pattern.compile ("^lux(embourg|emburg)?$",Pattern.CASE_INSENSITIVE);
	
	/**
	 * Get the type.
	 *
	 * @return The type.
	 */
	@javax.persistence.Column(name = "type")
	public String  getType() {
		return type;
	}

	/**
	 * Set the number.
	 *
	 * @param data The number.
	 */
	public void setType(String type) {
		this.type = type;
	}

	/**
	 * @return Returns the country.
	 */
	@javax.persistence.Column(name = "country")
	public String getCountry() {
		return country;
	}

	/**
	 * @param country The country to set.
	 */
	public void setCountry(String country) {
		this.country = country;
	}
	
	@Transient
	public String getCountryLocalized() {
		String key = Country.class.getSimpleName() + "."+ country;
		String translation = Translatrix.getTranslationString(key);
		if (translation == null || translation.equals(key))
			translation = country;
		return translation;
	}

	/**
	 * @return Returns the date.
	 */
	@javax.persistence.Column(name = "date")
	public Date getDate() {
		return date;
	}

	/**
	 * @param date The date to set.
	 */
	public void setDate(Date date) {
		this.date = date;
	}

	/**
	 * @return Returns the locality.
	 */
	@javax.persistence.Column(name = "locality")
	public String getLocality() {
		return locality;
	}

	/**
	 * @param locality The locality to set.
	 */
	public void setLocality(String locality) {
		this.locality = locality;
	}

	/**
	 * @return Returns the streetName.
	 */
	@javax.persistence.Column(name = "streetname")
	public String getStreetName() {
		return streetName;
	}

	/**
	 * @param streetName The streetName to set.
	 */
	public void setStreetName(String streetName) {
		this.streetName = streetName;
	}

	/**
	 * @return Returns the streetNumber.
	 */
	@javax.persistence.Column(name = "streetnumber")
	public String getStreetNumber() {
		return streetNumber;
	}

	/**
	 * @param streetNumber The streetNumber to set.
	 */
	public void setStreetNumber(String streetNumber) {
		this.streetNumber = streetNumber;
	}

	/**
	 * @return Returns the zip.
	 */
	@javax.persistence.Column(name = "zip")
	public String getZip() {
		return zip;
	}

	/**
	 * @param zip The zip to set.
	 */
	public void setZip(String zip) {
		this.zip = zip;
	}
	
	/**
	 * @return Returns the localityId.
	 */
	@javax.persistence.Column(name = "locality_id")
	public Integer getLocalityId() {
		return localityId;
	}

	/**
	 * @param localityId The localityId to set.
	 */
	public void setLocalityId(Integer localityId) {
		this.localityId = localityId;
	}
	
	public String toString ()
	{
		return toString(true);
	}
	
	public String toString (boolean singleLine) 
	{
		StringBuffer sb = new StringBuffer();
		String separator = singleLine ? ", " : "\n";
		
		if (getStreetNumber() != null && getStreetNumber().trim().length() > 0)
			sb.append(getStreetNumber()).append(", ");
		if (getStreetName() != null && getStreetName().trim().length() > 0)
			sb.append(getStreetName()).append(separator);
		if (getZip() != null && getZip().trim().length() > 0)
			sb.append(getZip()).append(" ");
		if (getLocality() != null && getLocality().trim().length() > 0)
			sb.append(getLocality()).append(separator);
		if (getCountry() != null && getCountry().trim().length() > 0)
			sb.append(getCountry()).append(" ");
		return sb.toString().trim();
	}
	
	public static String printAddresses (Collection<PatientAddress> addresses, boolean singleLineAddress)
	{
		StringBuilder address = null;
		
		if (addresses == null || addresses.isEmpty())
			return "";
		
		for (GECAMedAddressBean a : addresses)
		{
			if (address == null)
				address = new StringBuilder();
			else
				address.append("\n --------------- \n");
			address.append(a.toString(singleLineAddress));
		}
		
		return address.toString().trim();
	}
	
	public int compareTo(GECAMedEntityBean o) {
			/* ============================================= */
			Date adrDate1 = getDate();
			Date adrDate2 = (o != null && o instanceof GECAMedAddressBean)?((GECAMedAddressBean)o).getDate():null;
						
			if ((adrDate1 != null) && (adrDate2 != null))
				{
				if (adrDate1.before(adrDate2)) 
					return 1;
				else if (adrDate1.after(adrDate2))
						 return -1;
					else return 0;
				}
			else if ((adrDate1 == null) && (adrDate2 != null)) return 1;
			 	else if ((adrDate1 != null) && (adrDate2 == null)) return -1;
			 		else return 0;

			/* ============================================= */
		}

	
	//---------------------------------------------------------------------------
	/**
	 * checks whether this address instance is an address is luxembourg or not.
	 * @return <code>true</code> if this instance is an address in luxembourg,
	 * <code>false</code> otherwise.
	 */
	//---------------------------------------------------------------------------

	@Transient
	public boolean isAddressInLuxembourg () {
		if (this.getCountry() == null) return false;
		
		Matcher luxMatcher = LUXEMBOURG.matcher(this.getCountry());
		return luxMatcher.matches();
	}
	
	//---------------------------------------------------------------------------
	/**
	 * checks whether this address instance is an address is luxembourg or not.
	 * @return <code>true</code> if this instance is an address in luxembourg,
	 * <code>false</code> otherwise.
	 */
	//---------------------------------------------------------------------------

	@Transient
	public boolean isAbroadRelativeTo (GECAMedAddressBean p_ReferenceAddress) {		
		String referenceCountry;
		String thisCountry;
		
		if ((p_ReferenceAddress == null) || 
			(p_ReferenceAddress.getCountry() == null) ||
			(this.getCountry() == null) )
			return false;
		
		referenceCountry = p_ReferenceAddress.getCountry().toLowerCase();
		thisCountry      = this.getCountry().toLowerCase();
		
		return !referenceCountry.equals(thisCountry);
	}

	//---------------------------------------------------------------------------
	/**
	 * Returns a formatted address string in two lines
	 * @return printable form of this address instance
	 * @see #formatAddressBlock()
	 */
	//---------------------------------------------------------------------------
	
//	@Transient
//	public String getFormattedString () {
//		return this.formatAddressBlock (false);
//	}

	//---------------------------------------------------------------------------
	/**
	 * Returns a formatted address string in two lines
	 * @param p_IsAbroad specifies whether this address instance is to be 
	 * considered as an address abroad or not. By specifying <code>true</code>,
	 * the formatted address block will include this addresses country as well.
	 * When specifying <code>false</code> the country will be omitted.
	 * @return printable form of this address instance
	 * @see formatAddressBlock()
	 */
	//---------------------------------------------------------------------------
	
//	@Transient
//	public String getFormattedString (boolean p_IsAbroad) {
//		return this.formatAddressBlock (p_IsAbroad);
//	}

}
