package com.fp.base.persistence.util.db;

import java.util.Map;

import com.fp.core.exception.CoreException;
import com.fp.persistence.commondb.HqlStatement;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.commondb.cache.CacheManager;
import com.fp.persistence.pgeneral.gene.TgeneCreditType;
import com.fp.persistence.pgeneral.gene.TgeneCurrency;
import com.fp.persistence.pgeneral.gene.TgeneFrequency;
import com.fp.persistence.pgeneral.installment.TgeneInstallmentType;
import com.fp.persistence.pgeneral.safe.TsafeUser;
import com.fp.persistence.pgeneral.trans.TgeneTransactionItem;

/**
 * Clase que se encarga de manejo de sentencias SQL o HQL con la base de datos, Existe ciertas tablas con informacion
 * estatica, las cuales se cargan a memoria. <br>
 * Otras tablas se define para que se cargue a cache la informacion de ciertos regitros que esten marcados con
 * ManageCache.
 * 
 * @author Jorge Vaca
 * @version 2.1
 */
public class DataHelper {
    /** Almacena una instancia de DataHelper. */
    private static DataHelper cache;

    /**
     * Entrega una instancia de DataHelper.
     * 
     * @return DataHelper
     */
    public static DataHelper getInstance() {
        if (DataHelper.cache != null) {
            return DataHelper.cache;
        }
        synchronized (DataHelper.class) {
            if (DataHelper.cache == null) {
                DataHelper.cache = new DataHelper();
            }
        }
        return DataHelper.cache;
    }

    private static final String VMODULECODE = "modulecode";

    /** Sentencia que devuelve un registro de TgeneCreditType. */
    private static final String HQL_CREDIT_TYPE = "from TgeneCreditType t  " + " where t.pk = :credittypecode ";

    /**
     * Metodo que entrega la definicion de TgeneCreditType.
     * 
     * @param pCreditType Codigo de tipo de credito a obtener datos.
     * @return TgeneCreditType
     * @throws Exception
     */
    public TgeneCreditType getTgeneCreditType(String pCreditType) throws Exception {
        TgeneCreditType tgeneCreditType = null;
        CacheManager cm = CacheManager.getInstance();
        tgeneCreditType = (TgeneCreditType) cm.getData("TgeneCreditType", pCreditType);
        if (tgeneCreditType == null) {
            HqlStatement hql = new HqlStatement();
            hql.setSentence(DataHelper.HQL_CREDIT_TYPE);
            hql.setString("credittypecode", pCreditType);
            tgeneCreditType = (TgeneCreditType) hql.getObject();
            Map<String, Object> m = cm.getMapDefinition("TgeneCreditType");
            m.put(pCreditType, tgeneCreditType);
            cm.putData("TgeneCreditType", m);
        }
        return tgeneCreditType;
    }

    /** Sentencia que devuelve un registro de TgeneInstallmentType. */
    private static final String HQL_INSTALLMENT_TYPE = "from TgeneInstallmentType t  " + " where t.pk.installmenttype = :installmenttype "
            + " and t.pk.modulecode = :modulecode ";

    /**
     * Metodo que entrega la definicion de TgeneInstallmentType
     * 
     * @param TgeneInstallmentType Codigo de tipo de tabla de amortizacion.
     * @return TgeneInstallmentType
     * @throws Exception
     */
    public TgeneInstallmentType getTgeneInstallmentType(String pInstallmentType, String pModule) throws Exception {
        String key = pInstallmentType + pModule;
        TgeneInstallmentType tgeneInstallmentType = null;
        CacheManager cm = CacheManager.getInstance();
        tgeneInstallmentType = (TgeneInstallmentType) cm.getData("TgeneInstallmentType", key);
        if (tgeneInstallmentType == null) {
            HqlStatement hql = new HqlStatement();
            hql.setSentence(DataHelper.HQL_INSTALLMENT_TYPE);
            hql.setString("installmenttype", pInstallmentType);
            hql.setString(DataHelper.VMODULECODE, pModule);
            hql.setReadonly(true);
            tgeneInstallmentType = (TgeneInstallmentType) hql.getObject();
            if (tgeneInstallmentType == null) {
                throw new CoreException("CORE-0022", "TIPO TABLA DE AMORTIZACION NO DEFINIDA EN TGENEINSTALLMENTTYPE :{0}", pInstallmentType);
            }

            Map<String, Object> m = cm.getMapDefinition("TgeneInstallmentType");
            m.put(key, tgeneInstallmentType);
            cm.putData("TgeneInstallmentType", m);
        }
        return tgeneInstallmentType;
    }

    /** Sentencia que devuelve un registro de TgeneFrequency. */
    private static final String HQL_FREQUENCY = "from TgeneFrequency t  " + " where t.pk = :frequencycode ";

    /**
     * Metodo que entrega la definicion de TgeneFrequency
     * 
     * @param pFrequencyCode Codigo de frecuenia a obtener su definicion.
     * @return TgeneFrequency
     * @throws Exception
     */
    public TgeneFrequency getTgeneFrecuency(Integer pFrequencyCode) throws Exception {
        TgeneFrequency tgeneFrequency = null;
        String key = "" + pFrequencyCode;
        CacheManager cm = CacheManager.getInstance();
        tgeneFrequency = (TgeneFrequency) cm.getData("TgeneFrequency", key);
        if (tgeneFrequency == null) {
            HqlStatement hql = new HqlStatement();
            hql.setSentence(DataHelper.HQL_FREQUENCY);
            hql.setInteger("frequencycode", pFrequencyCode);
            hql.setReadonly(true);
            tgeneFrequency = (TgeneFrequency) hql.getObject();
            if (tgeneFrequency == null) {
                throw new CoreException("CORE-0015", "FRECUENCIA NO DEFINIDA EN TGENEFREQUENCY FRQCODE:{0}", pFrequencyCode);
            }
            Map<String, Object> m = cm.getMapDefinition("TgeneFrequency");
            m.put(key, tgeneFrequency);
            cm.putData("TgeneFrequency", m);
        }
        return tgeneFrequency;
    }

    /**
     * Entrega un objeto con los datos de TsafeUser. Que contiene datos de un usuario.
     * 
     * @param pUserCode Codigo de usuario a obtener un registro.
     * @return TsafeUser
     * @throws CoreException
     * @throws Exception
     */
    public TsafeUser getTsafeUser(String pUserCode) throws CoreException, Exception {
        TsafeUser tsafeUser = TsafeUser.find(PersistenceHelper.getEntityManager(), pUserCode);
        if (tsafeUser == null) {
            throw new CoreException("CORE-0032", "USUARIO {0} NO DEFINIDO EN TSAFEUSER", pUserCode);
        }
        if (tsafeUser.getInternalcode() == null) {
            throw new CoreException("CORE-0033", "CODIGO USUARIO INTERNO NO DEFINIDO EN TSAFEUSER USERCODE: {0}", pUserCode);
        }
        return tsafeUser;
    }

    /**
     * Entrega un registro de tgenecurrency.
     * 
     * @param pCurrency Codigo de moneda a obtener un registro de la base de datos.
     * @return TgeneCurrency
     * @throws Exception
     */
    public TgeneCurrency getTgeneCurrency(String pCurrency) throws Exception {
        TgeneCurrency tgeneCurrency = null;
        CacheManager cm = CacheManager.getInstance();
        tgeneCurrency = (TgeneCurrency) cm.getData("TgeneCurrency", pCurrency);
        if (tgeneCurrency == null) {
            tgeneCurrency = TgeneCurrency.find(PersistenceHelper.getEntityManager(), pCurrency);
            if (tgeneCurrency == null) {
                throw new CoreException("CORE-0017", "MONEDA {0} NO DEFINIDA EN TGENECURRENCY ", pCurrency);
            }
            Map<String, Object> m = cm.getMapDefinition("TgeneCurrency");
            m.put(pCurrency, tgeneCurrency);
            cm.putData("TgeneCurrency", m);
        }
        return tgeneCurrency;
    }

    /**
     * Sentecia que devuelve el rubro de una transaccion
     */
    private static final String HQL_TRANSACTION_ITEMCODE = "from TgeneTransactionItem tt  " + " where tt.pk.transactionmodule = :transactionmodule"
            + " and tt.pk.transactioncode = :transactioncode" + " and tt.pk.transactionversion = :transactionversion"
            + " and tt.pk.itemcode = :itemcode";

    /**
     * Metodo que retorna el rubro de una transaccion
     * 
     * @param transactionmodule Modulo de la transaccion
     * @param transactioncode Codigo de la transaccion
     * @param transactionversion Version de la transaccion
     * @param itemcode Rubro de la transaccion
     * @return
     * @throws Exception
     */
    public TgeneTransactionItem getTgeneTransactionItem(String transactionmodule, Integer transactioncode, Integer transactionversion,
            Integer itemcode) throws Exception {
        TgeneTransactionItem tgeneTransactionItem = null;
        HqlStatement hql = new HqlStatement(DataHelper.HQL_TRANSACTION_ITEMCODE);
        hql.setString("transactionmodule", transactionmodule);
        hql.setInteger("transactioncode", transactioncode);
        hql.setInteger("transactionversion", transactionversion);
        hql.setInteger("itemcode", itemcode);
        tgeneTransactionItem = (TgeneTransactionItem) hql.getObject();
        return tgeneTransactionItem;
    }

}
