package com.fp.general.helper;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.SQLQuery;
import org.hibernate.ScrollableResults;

import com.fp.common.helper.BeanManager;
import com.fp.common.helper.Constant;
import com.fp.dto.rules.QueryRule;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.pgeneral.menu.TgeneMenuLevelDesc;
import com.fp.persistence.pgeneral.menu.TgeneMenuSubLevelDesc;

/**
 * Clase utilitaria del menu.
 * 
 * @author Jorge Vaca
 * @version 2.1
 */
public abstract class MenuHelper extends QueryRule {

    /**
     * Recore el resultset y adiciona transacciones al grupo.
     * 
     * @param pMenuGroupDesc Objeto que contien el codigo de menu y el grupo de menu, a buscar transacciones a asociar
     *            al grupo de menu.
     * @return List<Object>
     * @throws Exception
     */
    protected List<Object> completTransactionByLevel(TgeneMenuLevelDesc pMenuLevelDesc, String languagecode) throws Exception {
        ScrollableResults rSet = this.getTransactions(pMenuLevelDesc);
        List<Object> lData = new ArrayList<Object>();
        try {
            while (rSet.next()) {
                Object[] obj = rSet.get();
                Map<String, Object> m = this.completetransactiondata(obj, languagecode);
                lData.add(m);
            }
            return lData;
        } finally {
            rSet.close();
        }

    }

    /**
     * Recore el resultset y adiciona transacciones al grupo.
     * 
     * @param pMenuSubLevelDesc Objeto que contien el codigo de menu y el grupo de menu, a buscar transacciones a
     *            asociar al grupo de menu.
     * @param mLevel Datos del nivel padre del menu.
     * @throws Exception
     */
    protected void completTransactionBySubLevel(TgeneMenuSubLevelDesc pMenuSubLevelDesc, Map<String, Object> mLevel, String languagecode)
            throws Exception {
        ScrollableResults rSet = this.getTransactions(pMenuSubLevelDesc);
        List<Map<String, Object>> lData = new ArrayList<Map<String, Object>>();
        try {
            while (rSet.next()) {
                Object[] obj = rSet.get();
                Map<String, Object> m = this.completetransactiondata(obj, languagecode);
                lData.add(m);
            }
            mLevel.put("items", lData);
        } finally {
            rSet.close();
        }
    }

    /**
     * Metodo que completa datos del menu por transaccion.
     * 
     * @param pTgeneMenuGroupTran Transaccion a completar datos del menu.
     * @throws Exception
     */
    protected Map<String, Object> completetransactiondata(Object[] pObject, String languagecode) throws Exception {
        Map<String, Object> m = new HashMap<String, Object>();
        String module = (String) pObject[0];
        Integer transaction = BeanManager.convertObject(pObject[1], Integer.class);
        Integer version = BeanManager.convertObject(pObject[2], Integer.class);
        String page = (String) pObject[3];
        String autoquery = (String) pObject[4];
        String title = (String) pObject[5];
        String signature = (String) pObject[6];
        String queryagain = (String) pObject[7];
        String jsfp = (String) pObject[8];
        m.put("t", Constant.capitalize(title));
        m.put("p", page);
        m.put("a", autoquery);
        m.put("m", module);
        m.put("tr", transaction);
        m.put("v", version);
        m.put("f", signature);
        m.put("qa", queryagain);
        m.put("jsfp", jsfp);
        m.put("sg", this.existGlosary(module, transaction, version, languagecode));
        return m;
    }

    /**
     * Sentencia que entrega las transacciones asociadas al grupo del menu.
     */
    private static final String SQL = " select t.TRANSACTIONMODULE, t.TRANSACTIONCODE, t.TRANSACTIONVERSION, t.PAGE, t.AUTOQUERY, t.NAME, t.SIGNATURE, t.QUERYAGAIN, t.JSFPAGE  "
            + " from TGENEMENULEVELTRAN tm,TGENETRANSACTION t "
            + " where tm.TRANSACTIONMODULE = t.TRANSACTIONMODULE "
            + " and tm.TRANSACTIONCODE = t.TRANSACTIONCODE "
            + " and tm.TRANSACTIONVERSION = t.TRANSACTIONVERSION "
            + " and tm.LEVELCODE = :levelcode " + " and tm.MENUCODE = :menucode " + " order by tm.PRESENTATIONORDER";

    /**
     * Entrega un resultset con las transacciones a adicionar al menu.
     * 
     * @param pMenuGroupDesc Objeto que contien el codigo de menu y el grupo de menu, a buscar transacciones a asociar
     *            al grupo de menu.
     * @return ScrollableResults
     * @throws Exception
     */
    protected ScrollableResults getTransactions(TgeneMenuLevelDesc pMenuLevelDesc) throws Exception {
        ScrollableResults rSet = null;
        SQLQuery qry = PersistenceHelper.getSession().createSQLQuery(MenuHelper.SQL);
        qry.setInteger("levelcode", pMenuLevelDesc.getPk().getLevelcode());
        qry.setInteger("menucode", pMenuLevelDesc.getPk().getMenucode());
        rSet = qry.scroll();
        return rSet;
    }

    /**
     * Sentencia que entrega las transacciones asociadas al grupo del menu.
     */
    private static final String SQL_SUBLEVEL = " select t.TRANSACTIONMODULE, t.TRANSACTIONCODE, t.TRANSACTIONVERSION,t.PAGE, t.AUTOQUERY, t.NAME, t.SIGNATURE, t.QUERYAGAIN, t.JSFPAGE  "
            + " from TGENEMENUSUBLEVELTRAN tm, TGENETRANSACTION t "
            + " where tm.TRANSACTIONMODULE = t.TRANSACTIONMODULE "
            + " and tm.TRANSACTIONCODE = t.TRANSACTIONCODE "
            + " and tm.TRANSACTIONVERSION = t.TRANSACTIONVERSION "
            + " and tm.LEVELCODE = :levelcode "
            + " and tm.SUBLEVEL = :sublevel "
            + " and tm.MENUCODE = :menucode "
            + " order by tm.PRESENTATIONORDER";

    /**
     * Entrega un resultset con las transacciones a adicionar al menu.
     * 
     * @param pMenuGroupDesc Objeto que contien el codigo de menu y el grupo de menu, a buscar transacciones a asociar
     *            al grupo de menu.
     * @return ScrollableResults
     * @throws Exception
     */
    protected ScrollableResults getTransactions(TgeneMenuSubLevelDesc pMenuSubLevelDesc) throws Exception {
        ScrollableResults rSet = null;
        SQLQuery qry = PersistenceHelper.getSession().createSQLQuery(MenuHelper.SQL_SUBLEVEL);
        qry.setInteger("levelcode", pMenuSubLevelDesc.getPk().getLevelcode());
        qry.setInteger("sublevel", pMenuSubLevelDesc.getPk().getSublevel());
        qry.setInteger("menucode", pMenuSubLevelDesc.getPk().getMenucode());
        rSet = qry.scroll();
        return rSet;
    }

    /**
     * Sentencia para saber si existe un glosaio disponible para la transaccion
     */
    private static final String HQL = "SELECT count(*) FROM TGENETRANSACTIONGLOSARY" + " where TRANSACTIONMODULE = :transactionmodule"
            + " and TRANSACTIONCODE = :transactioncode" + " and TRANSACTIONVERSION = :transactionversion" + " and LANGUAGECODE= :languagecode";

    /**
     * Metodo que devuelve Y o N si existe glosario en una transaccion
     * 
     * @param module Modulo de la transaccion
     * @param transaction Codigo de transaccion
     * @param version Version de la transaccion
     * @param languagecode Lenguaje a utilizar
     * @return
     * @throws Exception
     */
    private String existGlosary(String module, Integer transaction, Integer version, String languagecode) throws Exception {
        SQLQuery qry = PersistenceHelper.getSession().createSQLQuery(HQL);
        qry.setString("transactionmodule", module);
        qry.setInteger("transactioncode", transaction);
        qry.setInteger("transactionversion", version);
        qry.setString("languagecode", languagecode);
        Object result = qry.uniqueResult();
        String returnValue = "N";
        if (result instanceof Integer) {
            Integer numero = (Integer) result;
            if (numero > 0) {
                returnValue = "Y";
            }
        } else if (result instanceof BigDecimal) {
            Integer numero = ((BigDecimal) result).intValue();
            if (numero > 0) {
                returnValue = "Y";
            }
        }
        return returnValue;
    }
}
