package fr.shortcircuit.tp9.web.annotated;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.model.SelectItem;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.beanutils.BeanPredicate;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.AllPredicate;
import org.apache.commons.collections.functors.EqualPredicate;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import fr.shortcircuit.tp9.business.definition.IProductBO;
import fr.shortcircuit.tp9.model.Product;
import fr.shortcircuit.tp9.web.definition.IProductSearchBean;
import fr.shortcircuit.tp9.web.util.StartsWithPredicate;
import fr.shortcircuit.tp9.web.util.WebHelper;

/** @author Dimitri Dean DARSEYNE (D3), 
 * Published by Short-Circuit under Creative Commons (CC) Licensing: 
 * Authorship/Paternity, NO Commercial Use, NO Derivative
 * Please check for more informations:
 * http://creativecommons.org/licenses/by-nc-nd/2.0/
 *
 * Auteur Dimitri Dean DARSEYNE (D3),
 * Publié par Short-Circuit sous license Creative Commons (CC):
 * Paternité, PAS d'Utilisation Commerciale, pas de Dérivés/Modifications
 * Pour plus d'informations, se rendre sur:
 * http://creativecommons.org/licenses/by-nc-nd/2.0/fr/ 
 * 
 * @since Short-Circuit 1999
 */

public class ProductSearchAnnotatedBean implements IProductSearchBean 
{
	//Injected references
	//@ManagedProperty(value="#{productBO}") 	//JSF2 Managed Bean @nnotation
	@Autowired(required=true)					//Spring 3 @nnotation
	@Getter @Setter
	private IProductBO 				productBO;

	//Simple search criteria parameter
	@Getter @Setter
	private String 					id;
	@Getter @Setter
	private String 					idKey;
	
	//Multiple chained search criteria parameter
	@Getter @Setter
	private String 					selectedProperty 	= "genre";
	@Getter @Setter
	private String 					selectedPropertyItem;
	@Getter @Setter
	private List<SelectItem> 		properties;
	@Getter @Setter
	private List<SelectItem> 		itemsGenre;
	@Getter @Setter
	private List<SelectItem> 		itemsPrice;
	
	//Auto completion
	@Getter @Setter
	private String 					strProduct; 
	
	@Getter @Setter
	private Product 				productResult;
	@Getter @Setter
	private Product 				productKeyResult;

	
	public ProductSearchAnnotatedBean() 
	{
		properties 			= WebHelper.wrapItemsWithLabel(Arrays.asList(new String[]{"genre", "price"}));
	}

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Search methods
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public String search()
	{
		productResult = searchProduct(id);
		//System.out.println("ProductSearchBean: search: exit, productResult=" + productResult);
		return null;
	}	

	public void keySearch()
	{
		productKeyResult = searchProduct(idKey);
		//System.out.println("ProductSearchBean: search: exit, productKeyResult=" + productKeyResult);
	}
	
	private Product searchProduct(String idSearched)
	{//System.out.println("ProductSearchBean: searchProduct: enter, idSearched=" + idSearched);
		
		if (!StringUtils.isEmpty(idSearched))
			try
			{
				List<Predicate> listPredicate  = new ArrayList<Predicate>();
				
				listPredicate.add(new BeanPredicate("id", new EqualPredicate(Integer.parseInt(idSearched))));
				
				Predicate pAll                      =  new AllPredicate((Predicate[]) listPredicate.toArray(new Predicate[] {})); //AnyPredicate
				return productBO.getProduct(pAll);
			}
			catch (Exception e) {System.out.println("ProductSearchBean: searchProduct: catch " + e.toString());}
		
		return null;
	}	

	public List<Product> getMatchingProducts()
	{
		if ((StringUtils.isEmpty(selectedProperty)) || (StringUtils.isEmpty(selectedPropertyItem)))
				return new ArrayList<Product>();
				
		List<Predicate> listPredicate  = new ArrayList<Predicate>();
		
		listPredicate.add(new BeanPredicate(selectedProperty, new EqualPredicate(selectedProperty.equalsIgnoreCase("genre")? selectedPropertyItem : new BigDecimal(selectedPropertyItem))));
		
		Predicate pAll                 =  new AllPredicate((Predicate[]) listPredicate.toArray(new Predicate[] {})); //AnyPredicate
		
		return productBO.getAllProduct(pAll);		
	}
	
	public List<String> complete(String prefix)
	{
	    List<String> matches = new ArrayList<String>();

		if (StringUtils.isEmpty(prefix))
			return matches;
		
		List<Predicate> listPredicate  = new ArrayList<Predicate>();

		listPredicate.add(new BeanPredicate("designation", 	new StartsWithPredicate(prefix)));

		List<Product> matchesProduct = productBO.getAllProduct(new AllPredicate((Predicate[]) listPredicate.toArray(new Predicate[] {})));

		for (Product p : matchesProduct)
			matches.add(p.getDesignation());

	    return matches;
	}
	
	
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Derivated property
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public List<SelectItem> getPropertyItems()  						{return selectedProperty.equalsIgnoreCase("genre")? getItemsGenre() : getItemsPrice();}
	
	public List<SelectItem> getItemsGenre() 							
	{
		if (itemsGenre == null)
			itemsGenre 			= WebHelper.wrapItemsWithLabel(productBO.getListGenre());
			
		return itemsGenre;
	}
	
	public List<SelectItem> getItemsPrice() 							
	{
		if (itemsPrice == null)
			itemsPrice 			= WebHelper.wrapItemsWithLabel(productBO.getListPrice());

		return itemsPrice;
	}
	
	public void setIdKey(String idKey) 									
	{
		this.idKey 				= idKey;
		
		keySearch();
	}
		
}
