package com.fp.common.exception;

import java.util.Locale;
import java.util.ResourceBundle;

import javax.ejb.ApplicationException;

import com.fp.common.helper.Constant;

/**
 * Clase generica del manejo de excepciones aplicativas.
 * 
 * @author Jorge Vaca.
 * @version 2.1
 */
@ApplicationException(rollback = true)
public class APPException extends RuntimeException {

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

    /**
     * Codigo de mensaje aplicativo.
     */
    protected String code;

    /**
     * Arreglo de parametros a mostrar en la aplicacion como numero de cuenta, tipo de saldo etc...
     */
    protected Object[] parameters;

    /**
     * Crea una instancia de excepcion aplicativa.
     * 
     * @param code Codigo de mensaje aplicativo.
     * @param message Mensaje aplicativo.
     * @param pParameters Arreglo de parametros a presentar adcionales al mensaje aplicativo.
     */
    public APPException(String code, String message, Object... pParameters) {
        super(code + ": " + message);
        this.code = code;
        parameters = pParameters;
    }

    /**
     * Crea una intancia de excepcion aplicativa.
     * 
     * @param code Codigo de mensaje aplicativo.
     * @param message Mensaje aplicativo.
     * @param pCause Excepcion original, cuando esta no se origina en api's de terceros.
     * @param pParameters Arreglo de parametros a presentar adcionales al mensaje aplicativo.
     */
    public APPException(String code, String message, Exception pCause, Object... pParameters) {
        super(code + ": " + message);
        super.initCause(pCause);
        this.code = code;
        parameters = pParameters;
    }

    /**
     * Entrega el valor del codigo de mensaje aplicativo.
     * 
     * @return String
     */
    public String getCode() {
        return code;
    }

    /**
     * Entrega el mensaje de la excepcion.
     * 
     * @see java.lang.Throwable#getMessage()
     * @return String
     */
    @Override
    public String getMessage() {
        String message = this.getMessage(new Locale("es"));
        return message;
    }

    /**
     * Retorna el mensaje de la excepcion.
     * 
     * @param pLocale Codigo de Locale a utilizar para presentar el mensaje traducido.
     * @return String
     */
    public String getMessage(Locale pLocale) {
        try {
            ResourceBundle resource = ResourceBundle.getBundle("userMessages", pLocale);
            String msg = resource.getString(code);
            if (parameters != null) {
                msg = Constant.formatMessage(msg, parameters);
            }
            return msg;
        } catch (Exception e) {

            try {
                String msg = super.getMessage() + " <*>";
                msg = Constant.formatMessage(msg, parameters);
                return msg;
            } catch (Exception e1) {
                return super.getMessage() + " <*>";
            }

        }
    }

    /**
     * Cambia los parametros del mensaje por los de la excepcion.
     * 
     * @param message
     * @return
     */
    public String getUserMessage(String language) {
        String msg = "";
        try {
            AbstractExceptionMessage m = (AbstractExceptionMessage) Class.forName("com.fp.general.exception.ExceptionMessage").newInstance();
            msg = m.getMessage(this.getCode(), language.toUpperCase());
        } catch (APPException e) {
            msg = super.getMessage();
        } catch (Exception e) {
            return "NO PUEDE OBTENER DESCRIPCION DE MENSAJE APLICATIVO EN TGENERESULT CODIGO " + this.getCode() + " IDIOMA " + language;
        }
        try {
            if (parameters != null) {
                msg = Constant.formatMessage(msg, parameters);
            }
        } catch (Exception e) {
            // no tomar accion
        }
        return msg;
    }
}
