package com.fp.dto.query;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fp.common.helper.BeanManager;
import com.fp.dto.AbstractData;

/**
 * @author Jorge Vaca
 * @version 2.1
 */
/**
 * @author jorge
 * 
 */
public class QueryBean extends AbstractData {

    /** Version de la clase */
    private static final long serialVersionUID = 1L;

    /** Paquete clase asociado al bena. */
    private String beanName;

    /** Numero de registros a consultar por pagina, se utiliaz en la paginacion en una pantalla */
    private int pageSize = 10;

    /** Numero de pagina en que se encuentra la consulta */
    private int page = 1;

    /** true, indica que la consulta entrega mas de un registro. */
    private boolean multirecord = true;

    /** Codigo de query alias, se utiliza para ejecutar consultas por codigo de consulta. */
    private String queryalias;

    /** Tipo de consulta, T transacion, P codigo de consulta */
    private String querytype;

    /** Lista de criterios asociados a al querybean */
    private List<QueryCriteria> criteria = new ArrayList<QueryCriteria>();

    /** Lista de query adicionales, utilizados para entregar informacion adicional asociada al bean principal */
    private List<AdditionalQuery> additionalQuery = new ArrayList<AdditionalQuery>();

    /**
     * Entrega el valor de: beanName
     * 
     * @return String
     */
    public String getBeanName() {
        return this.beanName;
    }

    /**
     * Fija el valor de: beanName
     * 
     * @param beanName
     */
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public List<AdditionalQuery> getAdditionalQuery() {
        return this.additionalQuery;
    }

    public void setAdditionalQuery(List<AdditionalQuery> additionalQuery) {
        this.additionalQuery = additionalQuery;
    }

    /**
     * Entrega el valor de: criteria
     * 
     * @return List<QueryCriteria>
     */
    public List<QueryCriteria> getCriteria() {
        return this.criteria;
    }

    /**
     * Fija el valor de: criteria
     * 
     * @param criteria
     */
    public void setCriteria(List<QueryCriteria> criteria) {
        this.criteria = criteria;
    }

    public QueryBean(String beanName) {
        this.beanName = beanName;
    }

    public QueryBean() {
    }

    /**
     * Entrega el valor de: pageSize
     * 
     * @return int
     */
    public int getPageSize() {
        return this.pageSize;
    }

    /**
     * Fija el valor de: pageSize
     * 
     * @param pageSize
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * Entrega el valor de: page
     * 
     * @return int
     */
    public int getPage() {
        return this.page;
    }

    /**
     * Fija el valor de: page
     * 
     * @param page
     */
    public void setPage(int page) {
        this.page = page;
    }

    /**
     * Entrega el valor de un criterio.
     * 
     * @param pProperty Nombre del parametro de criterio.
     * @return Object
     * @throws Exception
     */
    public Object getCriteriaValue(String pProperty) throws Exception {
        Object value = null;
        QueryCriteria obj = null;
        for (QueryCriteria queryCriteria : this.criteria) {
            if (queryCriteria.getProperty().compareTo(pProperty) == 0) {
                obj = queryCriteria;
            }
        }
        if (obj != null) {
            value = obj.getValue();
        }
        return value;
    }

    /**
     * Entrega el valor de un criterio.
     * 
     * @param pProperty Nombre del parametro de criterio.
     * @return Object
     * @throws Exception
     */
    public boolean isNotin(String pProperty) throws Exception {
        boolean exists = false;
        String aux = "not in";
        QueryCriteria obj = null;
        for (QueryCriteria queryCriteria : this.criteria) {
            if (queryCriteria.getProperty().compareTo(pProperty) == 0) {
                obj = queryCriteria;
            }
        }
        if (obj != null) {
            exists = obj.getOperation().toLowerCase().compareTo(aux) == 0;
        }
        return exists;
    }

    /**
     * Metodo que fija un valor de un criterio.
     * 
     * @param pProperty Nombre del criterio.
     * @param pValue Valor a almacenar en el criterio.
     * @throws Exception
     */
    public void setCriteriaValue(String pProperty, Object pValue) throws Exception {
        for (QueryCriteria obj : this.criteria) {
            if (obj.getProperty().compareTo(pProperty) == 0) {
                BeanManager.setBeanAttributeValue(obj, "value", pValue);
            }
        }
    }

    /**
     * Metodo que entrega una lista de criterios ordenada.
     * 
     * @param pAsc true entrega una lista de criterios ordenada ascendentemente, false entrega una lista de criterios
     *            ordenada descendentemente.
     * @return List<QueryCriteria>
     */
    public List<QueryCriteria> getOrder(boolean pAsc) {
        List<QueryCriteria> order = new ArrayList<QueryCriteria>();
        Map<Integer, QueryCriteria> aux = new HashMap<Integer, QueryCriteria>();
        List<Integer> key = new ArrayList<Integer>();
        for (QueryCriteria queryCriteria : this.criteria) {
            if (pAsc) {
                if (queryCriteria.getOrder() > 0) {
                    if (key.contains(Math.abs(queryCriteria.getOrder()))) {
                        continue;
                    }
                    key.add(Math.abs(queryCriteria.getOrder()));
                    aux.put(Math.abs(queryCriteria.getOrder()), queryCriteria);
                }
            } else {
                if (queryCriteria.getOrder() < 0) {
                    if (key.contains(Math.abs(queryCriteria.getOrder()))) {
                        continue;
                    }
                    key.add(Math.abs(queryCriteria.getOrder()));
                    aux.put(Math.abs(queryCriteria.getOrder()), queryCriteria);
                }
            }
        }
        Collections.sort(key);
        for (Integer k : key) {
            order.add(aux.get(k));
        }
        return order;
    }

    /**
     * Entrega el valor de: multirecord
     * 
     * @return boolean
     */
    public boolean isMultirecord() {
        return this.multirecord;
    }

    /**
     * Fija el valor de: multirecord
     * 
     * @param multirecord
     */
    public void setMultirecord(boolean multirecord) {
        this.multirecord = multirecord;
    }

    /**
     * Entrega el valor de: queryalias
     * 
     * @return String
     */
    public String getQueryalias() {
        return this.queryalias;
    }

    /**
     * Fija el valor de: queryalias
     * 
     * @param queryalias
     */
    public void setQueryalias(String queryalias) {
        this.queryalias = queryalias;
    }

    /**
     * @return the querytype
     */
    public String getQuerytype() {
        return this.querytype;
    }

    /**
     * @param querytype the querytype to set
     */
    public void setQuerytype(String querytype) {
        this.querytype = querytype;
    }

}
