package com.fp.common.exception;

import java.sql.SQLException;

import com.fp.common.helper.FkException;
import com.fp.common.logger.APPLogger;

/**
 * Clase que se encarga del manejo de excepciones de base de datos.
 *
 * @author Jorge Vaca.
 * @version 2.1
 */
public class SQLExceptionManager extends ExceptionManager {

    /**
     * campos requeridos
     */
    private static final int NOT_NULL = 1400;
    /**
     * pk duplicado
     */
    private static final int UNIQUE = 1;
    /**
     * pk duplicado
     */
    private static final int UNIQUE_SYBASE = 2601;
    /**
     * pk duplicado
     */
    private static final int UNIQUE_INFORM = -239;
    /**
     * pk duplicado
     */
    private static final int UNIQUE_INFORMIX = -268;
    /**
     * pk duplicado
     */
    private static final int UNIQUE_ID = -100;
    /**
     * pk duplicado
     */
    private static final int UNIQUE_IDINF = -346;
    /**
     * Error cuando se agrega un registro en Oracle y esta tiene referencia en
     * una tabla padre y no se encuentra definida
     */
    private static final int FKOracle = 2291;
    /**
     * Error cuando se agrega un registro en Sybase y esta tiene referencia en
     * una tabla padre y no se encuentra definida
     */
    private static final int FKSybase = 546;
    /**
     * Error cuando se elimina un registro en oracle y este tiene referencia en
     * una tabla hija
     */
    private static final int FK1Oracle = 2292;
    /**
     * Error cuando se elimina un registro en sybase y este tiene referencia en
     * una tabla hija
     */
    private static final int FK1Sybase = 547;
    /**
     * Error cuando se elimina un registro en informix y este tiene referencia en
     * una tabla hija
     */
    private static final int FK1Informix = -692;
    /**
     * Error de referencia FK
     */    
    private static final int LOCKSYBASE = 12205;
    /**
     * Error en oracle cuando se ingresa en un campo numerico mayor a la
     * longitud permitida
     */
    private static final int VALUELARGERNUMBER = 1438;
    /**
     * Error en informix cuando se ingresa en un campo numerico mayor a la
     * longitud permitida 
     */
    private static final int LARGENUBER_INFORM= -1226;
    /**
     * Error en oracle cuando se ingresa en un campo de texto mayor a la
     * longitud permitida
     */
    private static final int VALUELARGERSTRING = 12899;

    /**
     * Metodo que entrega el mensaje de usuario.
     *
     * @param pException
     * @return
     */
    @Override
    public String getUserMessage(Throwable pException) {
        SQLException exception;
        try {
            exception = (SQLException) pException;
        } catch (Exception e) {
            return pException.getLocalizedMessage();
        }
        try {
            if (exception.getErrorCode() == NOT_NULL) {
                String data = exception.getMessage();
                data = data.substring(data.indexOf('(') + 1, data.indexOf(')')).replaceAll("\"", "");
                data = data.substring(data.indexOf('.') + 1);
                String[] param = data.split("\\.");
                return super.getMessage("sql-not-null", param[0], param[1]);
            }
            if (exception.getErrorCode() == UNIQUE) {
                String data = exception.getMessage();
                data = data.substring(data.indexOf('.') + 1, data.indexOf(')'));
                return super.getMessage("sql.unique", data);
            }
            if (exception.getErrorCode() == UNIQUE_INFORM || exception.getErrorCode() == UNIQUE_INFORMIX) {
                String data = exception.getMessage();
                data = data.substring(data.indexOf(':') + 1, data.indexOf(')'));
                return super.getMessage("sql.unique", data);
            }
            if (exception.getErrorCode() == UNIQUE_SYBASE) {
                //"Attempt to insert duplicate key row in object 'TGENECATALOG' with unique index 'PKTGENECATALOG' "
                String data = exception.getMessage();
                data = data.substring(data.indexOf("'") + 1, data.indexOf("' "));
                return super.getMessage("sql.unique", data);
            }
            if (exception.getErrorCode() == UNIQUE_ID) {
                //"Attempt to insert duplicate key row in object 'TGENECATALOG' with unique index 'PKTGENECATALOG' "
                String data = exception.getMessage();
                data = data.substring(data.indexOf(":") + 1, data.indexOf("."));
                return super.getMessage("sql.uniqueID", data);
            }
            if (exception.getErrorCode()==UNIQUE_IDINF) {                
                String data = exception.getMessage();                
                return super.getMessage("sql.uniqueIDINF");
            }
            if (exception.getErrorCode() == FKOracle || exception.getErrorCode() == FKSybase) {
                String data = this.getFk(exception);
                if (data == null) {
                    return exception.getMessage();
                }
                return data;
            }
            if (exception.getErrorCode() == FK1Oracle || exception.getErrorCode() == FK1Sybase) {
                String data = this.getFk1(exception);
                if (data == null) {
                    return exception.getMessage();
                }
                return data;
            }
            if (exception.getErrorCode()==FK1Informix) {
                String data = exception.getMessage();
                data = data.substring(data.indexOf(".") + 1, data.indexOf(")"));
                return super.getMessage("fk.informix", data);
            }
            if (exception.getErrorCode() == LOCKSYBASE) {
                String data = this.getFk(exception);
                if (data == null) {
                    return super.getMessage("lock", data);
                }
                return data;
            }
            if (exception.getErrorCode() == VALUELARGERNUMBER) {
                return super.getMessage("valuelarger");
            }
            if (exception.getErrorCode() == LARGENUBER_INFORM) {
                return super.getMessage("valuelarger");
            }
            if (exception.getErrorCode() == VALUELARGERSTRING) {
                String mensaje = exception.getMessage();
                int a = mensaje.indexOf("\"");
                mensaje = mensaje.substring(a, mensaje.length());
                mensaje = mensaje.replaceAll("\"", "");
                String[] codes = mensaje.split("\\.");
                if (codes.length == 3) {
                    String campo = codes[2].substring(0, codes[2].indexOf("(")).trim();
                    String longitud = codes[2].substring(codes[2].indexOf("("), codes[2].length());
                    longitud = longitud.replace("actual", "Longitud ingresada");
                    longitud = longitud.replace("maximum", "Longitud permitida");
                    return super.getMessage("valueLargerWithValue", codes[1], campo, longitud);
                } else {
                    return super.getMessage("valuelarger");
                }
            }
        } catch (Exception e) {
            APPLogger.getLogger().warn(e);
        }
        return exception.getLocalizedMessage();
    }

    /**
     * Entrega el codigo de la excepcion.
     *
     * @param pException
     * @return
     */
    @Override
    public String getCode(Throwable pException) {
        SQLException exception = (SQLException) pException;
        return "SQL-" + exception.getErrorCode();
    }

    /**
     * Metodo que entrega el mensaje de la exception de FK
     *
     * @param exception Datos de SQLException
     * @return String
     */
    private String getFk(SQLException exception) {
        try {
            String data = exception.getMessage();
            int initialposition = data.indexOf('(') + 1;
            int endposition = data.indexOf(')');
            if (initialposition > 0 && endposition > 0) {
                data = data.substring(initialposition, endposition).replaceAll("\"", "");
                data = data.substring(data.indexOf('.') + 1);
                FkException fk = (FkException) Class.forName("com.fp.persistence.commondb.helper.Fkconstraint").newInstance();
                String[] d = fk.getFkData(data);
                return super.getMessage("fk", d[1], d[0]);
            } else if (data.indexOf(", table name = '") > 0) {
                data = data.substring(data.indexOf(", table name = '") + 16, data.length());
                String patherTable = data.substring(0, data.indexOf("'"));
                data = data.substring(data.indexOf(", constraint name = '") + 21, data.length());
                String constraintName = data.substring(0, data.indexOf("'"));
                return super.getMessage("fkg", patherTable, constraintName);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * Metodo que entrega el mensaje de la exception de FK
     *
     * @param exception Datos de SQLException
     * @return String
     */
    private String getFk1(SQLException exception) {
        try {
            String data = exception.getMessage();
            int initialposition = data.indexOf('(') + 1;
            int endposition = data.indexOf(')');
            if (initialposition > 0 && endposition > 0) {
                data = data.substring(initialposition, endposition).replaceAll("\"", "");
                data = data.substring(data.indexOf('.') + 1);
                FkException fk = (FkException) Class.forName("com.fp.persistence.commondb.helper.Fkconstraint").newInstance();
                String[] d = fk.getFkData(data);
                return super.getMessage("fk1", d[1], d[0]);
            } else if (data.indexOf(", table name = '") > 0) {
                data = data.substring(data.indexOf(", table name = '") + 16, data.length());
                String patherTable = data.substring(0, data.indexOf("'"));
                data = data.substring(data.indexOf(", constraint name = '") + 21, data.length());
                String constraintName = data.substring(0, data.indexOf("'"));
                return super.getMessage("fk1g", patherTable, constraintName);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

    }
}
