/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.addressbook.ejb.session.beans;

import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import lu.tudor.santec.gecamed.addressbook.ejb.entity.beans.Contact;
import lu.tudor.santec.gecamed.addressbook.ejb.session.interfaces.AddressbookInterface;

import org.jboss.annotation.security.SecurityDomain;

@Remote ({AddressbookInterface.class})
@Stateless
@SecurityDomain ("gecamedLoginDS")
public class AddressbookManager implements AddressbookInterface {

	@Resource SessionContext sessionContext;

	@PersistenceContext(unitName ="gecam")
	protected EntityManager em;

	public void deleteContact(Contact contact) {
	    Contact c = em.find(Contact.class, contact.getId());
	    em.remove(c);
	}
	
	public Contact saveContact(Contact contact) {
	    return em.merge(contact);
	}

	@SuppressWarnings("unchecked")
	public Collection<Contact> findContacts(String nameSearch, String addressSearch, String type, int limit) {
	    // long start = System.currentTimeMillis();
		
	    // replace evil chars
	    nameSearch = nameSearch.replaceAll("\'", "\'\'");
	    addressSearch = addressSearch.replaceAll("\'", "\'\'");

		// create the query
	        StringBuffer querryString = new StringBuffer("\n SELECT DISTINCT OBJECT(contact) FROM Contact contact ");

	        // split the name search into single words
	        String[] searchNameStrings = nameSearch.split(" ");
	        
	        // create the where clause for the name search
	        for (int i = 0; i < searchNameStrings.length; i++) {
	            	// get the singe search word
	            	String searchWord = searchNameStrings[i];
	            	// break if it is empty
	        	if (searchWord == null || "".equals(searchWord) ) {
	        		break;
	        	}
	        	
	        	// append the right word....
        	        if (i == 0) {
                		querryString.append(" WHERE \n");
                	} else {
                		querryString.append(" AND \n");
                	}
    	        
            	// search MED.PRES
            	querryString.append("\tupper(contact.medpres) LIKE upper('" + searchWord + "%') OR \n");

        		// else search the name fields
        		querryString.append(" ( \n");
        		// search from column start
        		querryString.append("\tupper(contact.nameFirst) LIKE upper('" + searchWord + "%') OR \n");
        		querryString.append("\tupper(contact.name) LIKE upper('" + searchWord + "%') OR \n");
        		// search from word start
        		querryString.append("\tupper(contact.nameFirst) LIKE upper('% " + searchWord + "%') OR \n");
        		querryString.append("\tupper(contact.name) LIKE upper('% " + searchWord + "%') \n");
        		querryString.append(" ) \n");
	        
	        }
		
	        // split the address search into single words
	        String[] searchAddressStrings = addressSearch.split(" ");
	        
	        // create the where clause for the name search
	        for (int i = 0; i < searchAddressStrings.length; i++) {
	            	// get the singe search word
	            	String searchWord = searchAddressStrings[i];
	            	// break if it is empty
	        	if (searchWord == null || "".equals(searchWord) ) {
	        			break;
	        	}
	        	
	        	// append the right word....
        	        if (querryString.toString().indexOf("WHERE") <= 0) {
                		querryString.append(" WHERE \n");
                	} else {
                		querryString.append(" AND \n");
                	}
        	        
        	        // if searchword is a number, search the zip and phone
        	        try {
				Long.parseLong(searchWord);
				querryString.append(" ( \n");
				// for zip search (start of column)
				querryString.append("\t contact.address.zip LIKE '" + searchWord+ "%'  OR \n");
				// for phone search (start of column)
				querryString.append("\t contact.phonePrivate LIKE '" + searchWord+ "%'  OR \n");
				querryString.append("\t contact.phoneWork LIKE '" + searchWord+ "%'  OR \n");
				querryString.append("\t contact.phoneMobile LIKE '" + searchWord+ "%'  OR \n");
				querryString.append("\t contact.fax LIKE '" + searchWord+ "%'  \n");
				querryString.append(" ) \n");
			// else search the address fields
			} catch (Exception e) {
				// search for locality and street
			    	querryString.append(" ( \n");
				querryString.append("\tupper(contact.comment) LIKE upper('" + searchWord + "%') OR \n");
				querryString.append("\tupper(contact.comment) LIKE upper('% " + searchWord + "%') OR \n");
				querryString.append("\tupper(contact.comment) LIKE upper('%\\n" + searchWord + "%') OR \n");
			    	querryString.append("\tupper(contact.address.locality) LIKE upper('" + searchWord + "%') OR \n");
				querryString.append("\tupper(contact.address.locality) LIKE upper('% " + searchWord + "%') OR \n");
				querryString.append("\tupper(contact.address.streetName) LIKE upper('" + searchWord + "%') OR \n");
				querryString.append("\tupper(contact.address.streetName) LIKE upper('% " + searchWord + "%') \n");

				querryString.append(" ) \n");
			}
	        }
	        
	        if (type != null && !type.equals("")) {
	        	// append the right word....
        	        if (querryString.toString().indexOf("WHERE") <= 0) {
                		querryString.append(" WHERE \n");
                	} else {
                		querryString.append(" AND \n");
                	}
        	        querryString.append(" ( \n");
			querryString.append("\tupper(contact.contactType) LIKE upper('" + type + "%') \n");
			querryString.append(" ) \n");
	        }
	        
	        
	        querryString.append(" ORDER BY contact.name");
//	        System.out.println("--------------------------------------------------------------");
//	        System.out.println(querryString.toString());
//	        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
	        Query q = em.createQuery(querryString.toString());
	        q.setMaxResults(limit);
			/* -------------------------------------------------------------------- */
		List l = q.getResultList();
//		long now = System.currentTimeMillis();
//		System.out.print("  Query took: "+ (now-start) + " for " + l.size() + " results");
		return l;
	}

	@SuppressWarnings("unchecked")
	public Collection<String> getContactTypes() {
	    return em.createQuery("SELECT DISTINCT contact.contactType FROM Contact contact").getResultList();
	}

	@SuppressWarnings("unchecked")
	public Collection<Contact> getMedPres() {
		return em.createQuery("SELECT OBJECT(o) FROM Contact o where o.medpres IS NOT NULL ORDER BY o.medpres").getResultList();
	}
    
}
