package fr.shortcircuit.tp9.web.util;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
	
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.BeanPredicate;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.comparators.ReverseComparator;
import org.apache.commons.collections.functors.AllPredicate;
import org.apache.commons.collections.functors.EqualPredicate;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SelectableDataModel;
import org.primefaces.model.SortOrder;

import fr.shortcircuit.tp9.business.definition.IProductBO;
import fr.shortcircuit.tp9.model.Product;

/** @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
 */

/** 
 * LazyDataModel implementation using a ProductBO as datasource interface. 
 */  
public class LazyProductDataModel extends LazyDataModel<Product> implements SelectableDataModel<Product> 
{
	private IProductBO 		productBO;
	
  
    public LazyProductDataModel(IProductBO productBO) 
    {  
        this.productBO 		= productBO;
    }  

    // Used by row selection/edit
    public Product getRowData(String rowKey) 
    {	
		Product p 							= productBO.getProduct(new BeanPredicate("id", new EqualPredicate(Integer.parseInt(rowKey))));
		
    	//System.out.println("LazyProductDataModel: getRowData: found product=" + p + " for rowKey=" + rowKey);
    	
		return p; 
    }  
  
    // Used by row selection/edit
    public String getRowKey(Product product) 
    {  
        return "" + product.getId();  
    }  
   
    /**
     * Main Method for PrimeFaces Table feeding, based on ProductBO->ProductDAO delegation.
     * 
     * This algorithm is using:
     *   
     * - (Reversed) BeanComparator for Bean Property sorting (Ascendant, Descendant)
     * 
     * - Composite Predicate (AllPredicate [BeanPredicate -> EqualPredicate (Numeric, BigDecimal), StartsWithPredicate (String)] 
     *   for Filter Mapping
     * 
     * Both parameters family are providing hereby consistent/efficient BEAN LEVEL structures' for ProductBO->ProductDAO getAllProduct(...) calls.
     */
    public List<Product> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) 
    {//System.out.println("LazyProductDataModel: load: enter, load first=" + first + ", pageSize=" + pageSize + ", sortField=" + sortField + ", sortOrder=" + sortOrder + ", filters=" + filters);

        List<Product> listResults 					= null;
        
        if (filters.isEmpty())
        {
        	listResults 							= productBO.getAllProduct(sortOrder.equals(SortOrder.ASCENDING)? new BeanComparator(sortField) : new ReverseComparator(new BeanComparator(sortField)), first, pageSize);
        	
        	this.setRowCount(productBO.getList().size()); //for pages quantity, all list 
        }
        else
        {
        	List<Predicate> listPredicateFilters 	= new ArrayList<Predicate>();
        	
        	for (String filterProperty : filters.keySet()) 
        	{
        		String strFilterValue 				= (String) filters.get(filterProperty);
        		
        		if (filterProperty.equalsIgnoreCase("id") || filterProperty.equalsIgnoreCase("type") || filterProperty.equalsIgnoreCase("annee"))
        			listPredicateFilters.add(new BeanPredicate(filterProperty, new EqualPredicate(Integer.parseInt(strFilterValue))));
        		else if (filterProperty.equalsIgnoreCase("price"))
        			listPredicateFilters.add(new BeanPredicate(filterProperty, new EqualPredicate(new BigDecimal(strFilterValue))));
        		else
        			listPredicateFilters.add(new BeanPredicate(filterProperty, new StartsWithPredicate(strFilterValue)));
        	}
        	
        	Predicate allPredicateFilters			= new AllPredicate((Predicate[]) listPredicateFilters.toArray(new Predicate[] {})); //AnyPredicate
        	Comparator sortComparator 				= sortOrder.equals(SortOrder.ASCENDING)? new BeanComparator(sortField) : new ReverseComparator(new BeanComparator(sortField));
        	listResults 							= productBO.getAllProduct(sortComparator, allPredicateFilters, first, pageSize);

        	this.setRowCount(productBO.count(allPredicateFilters)); //for pages quantity, list 4 predicate
        }

        //System.out.println("LazyProductDataModel: load: listResults.size=" + listResults.size());
        
        return listResults;
    }  
} 
