package com.fitbank.common;

import com.fitbank.common.Helper;
import com.fitbank.common.conectivity.HbSession;
import com.fitbank.common.exception.FitbankException;
import com.fitbank.common.logger.FitbankLogger;
import org.hibernate.SQLQuery;
/**
 * Clase que implementa la transformación de números en letras. Toma un número
 * analiza las decenas, centenas, unidades de mil, etc; toma un esa separación y
 * comienza a generar el número en letas.
 * 
 * @author FITBANK LB
 * @version 1.0 Octubre 2005
 */
public class NumberToLetter {
    public int    flag;
    protected int  numero;
    private String numletra;
    private String numletram;
    private String numletradm;
    private String numletracm;
    private String numletramm;
    private String numletradmm;
    //Query que trae la descripcion de la moneda oficial del cliente parametrizada en la tabla TCOMPANIASLICENCIADASID
    private static final String SQL_MONEDAOFICIAL = "SELECT tm.DESCRIPCION" 
            + " FROM TMONEDAS tm, TCOMPANIASLICENCIADASID tcl"
            + " WHERE tm.CMONEDA = tcl.CMONEDA_OFICIAL"
            + " AND tcl.CPERSONA_COMPANIA = :company"
            + " AND tm.FHASTA = :expiredate";

    /**
     * Constructor por default de la clase coloca en cero el número a
     * transformar y encera el flag de la clase.
     */
    public NumberToLetter() {
        this.numero = 0;
        this.flag = 0;
    }

    /**
     * Método que transforma números de tres dígitos de números a letras.
     * 
     * @param numero
     *            Número que se va a transformar
     * @return Número en letras
     */
    private String centena(int numero) throws Exception {
        if (numero >= 100) {
            if ((numero >= 900) && (numero <= 999)) {
                this.numletra = "novecientos ";
                if (numero > 900) {
                    this.numletra = this.numletra.concat(this.decena(numero - 900));
                }
            } else {
            	if ((numero >= 800) && (numero <= 899)) {
	                this.numletra = "ochocientos ";
	                if (numero > 800) {
	                    this.numletra = this.numletra.concat(this.decena(numero - 800));
	                }
            	}else {
	            	this.numletra = centena2(numero);
            	}
            }
        } else {
            this.numletra = this.decena(numero);
        }

        return this.numletra;
    }
    public String centena2(int numero) throws Exception{
    	if ((numero >= 700) && (numero <= 799)) {
            this.numletra = "setecientos ";
            if (numero > 700) {
                this.numletra = this.numletra.concat(this.decena(numero - 700));
            }
        } else {
        	if ((numero >= 600) && (numero <= 699)) {
                this.numletra = "seiscientos ";
                if (numero > 600) {
                    this.numletra = this.numletra.concat(this.decena(numero - 600));
                }
            } else {
            	this.numletra = centena3(numero);
            }
        }
    	return this.numletra;
    }
    public String centena3(int numero) throws Exception{
    	if ((numero >= 500) && (numero <= 599)) {
            this.numletra = "quinientos ";
            if (numero > 500) {
                this.numletra = this.numletra.concat(this.decena(numero - 500));
            }
        } else {
        	if ((numero >= 400) && (numero <= 499)) {
                this.numletra = "cuatrocientos ";
                if (numero > 400) {
                    this.numletra = this.numletra.concat(this.decena(numero - 400));
                }
            } else {
            	this.numletra = centena4(numero);
            }
        }
    	return this.numletra;
    }
    public String centena4(int numero) throws Exception{
    	if ((numero >= 300) && (numero <= 399)) {
            this.numletra = "trescientos ";
            if (numero > 300) {
                this.numletra = this.numletra.concat(this.decena(numero - 300));
            }
        } else {
        	if ((numero >= 200) && (numero <= 299)) {
                this.numletra = "doscientos ";
                if (numero > 200) {
                    this.numletra = this.numletra.concat(this.decena(numero - 200));
                }
            } else{ 
            	this.numletra = centena5(numero);
            }
        }
    	return this.numletra;
    }
    public String centena5(int numero) throws Exception{
    	if ((numero >= 100) && (numero <= 199)) {
            if (numero == 100) {
                this.numletra = "cien ";
            } else {
                this.numletra = "ciento ".concat(this.decena(numero - 100));
            }
    	}
    	return this.numletra;
    }
    /**
     * Método que transforma número de cinco dígitos en letras.
     * 
     * @param numero
     *            Número a transformar
     * @return Número en letras
     */
    private String cienmiles(int numero) throws Exception {
        if (numero == 100000) {
            this.numletracm = "cien mil";
        }

        if ((numero >= 100000) && (numero < 1000000)) {
            this.flag = 1;
            this.numletracm = this.centena(numero / 1000).concat(" mil ").concat(this.centena(numero % 1000));
        }
        if (numero < 100000) {
            this.numletracm = this.decmiles(numero);
        }

        return this.numletracm;
    }

    /**
     * Método que transforma cualquier número en Letras.
     * 
     * @param numero
     *            Número a transformar
     * @return Número en letras.
     */
    
    private String convertirLetras(int numero) throws Exception {
        String numletras="";
        numletras = this.decmillon(numero);
        return numletras;
    }

    /**
     * Método que recibe el número el cual se desea transformar a letras lo
     * procesa y convierte su valor en su equivalente en letras.
     * 
     * @param number
     *            Cadena que contiene el número de que se desea transformar a
     *            letras, este puede venir con decimales.
     * @return Objeto que contiene la cadena con el valor en letras del número
     *         enviado.
     */
    public String convertNumberToLetters(String number, Boolean withMoney) throws Exception {
        String real;
        String decimal;
        int integerPart;
        if (number.contains(".")) {
            real = number.substring(0, number.indexOf('.'));
            decimal = number.substring(number.indexOf('.') + 1);
        } else {
            real = number;
            decimal = "00";
        }
        integerPart = Integer.parseInt(real);
      //Robert
        if (decimal.length()==1){
        	decimal=decimal+ "0";
        }
        String decimalPart = " con " + decimal + "/100 ";
        String letters = this.convertirLetras(integerPart);
        ConvertNumberToLetter cntol = new ConvertNumberToLetter();//nuevo
        letters = cntol.toLetters(String.valueOf(integerPart));//nuevo
        
        if (withMoney.booleanValue()) {
            letters += decimalPart + this.getOfficialClientCurrency();
        } else {
            letters += decimalPart;
        }
        return letters.toUpperCase();
    }

    /**
     * Método que transforma números de dos digitos.
     * 
     * @param numero
     *            Número que se va a transformar
     * @return Decena en Letras
     */
    private String decena(int numero) throws Exception {
        if ((numero >= 90) && (numero <= 99)) {
            this.numletra = "noventa ";
            if (numero > 90) {
                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 90));
            }
        }else{
        	if ((numero >= 80) && (numero <= 89)) {
	            this.numletra = "ochenta ";
	            if (numero > 80) {
	                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 80));
	            }
        	}else {
        		this.numletra=decena2();
        	}
        }
        return this.numletra;
    }
    public String decena2(){
    	if ((numero >= 70) && (numero <= 79)) {
            this.numletra = "setenta ";
            if (numero > 70) {
                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 70));
            }
		} else {
			if ((numero >= 60) && (numero <= 69)) {
	            this.numletra = "sesenta ";
	            if (numero > 60) {
	                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 60));
	            }
			} else {
				this.numletra=decena3();
			}
		}
    	return this.numletra;
    }
    public String decena3(){
    	if ((numero >= 50) && (numero <= 59)) {
            this.numletra = "cincuenta ";
            if (numero > 50) {
                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 50));
            }
		} else {
			if ((numero >= 40) && (numero <= 49)) {
	            this.numletra = "cuarenta ";
	            if (numero > 40) {
	                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 40));
	            }
			} else {
				this.numletra = decena4();
			}
		}
    	return this.numletra;
    }
    public String decena4(){
    	if ((numero >= 30) && (numero <= 39)) {
            this.numletra = "treinta ";
            if (numero > 30) {
                this.numletra = this.numletra.concat("y ").concat(this.unidad(numero - 30));
            }
		}else{ 
			if ((numero >= 20) && (numero <= 29)) {
	            if (numero == 20) {
	                this.numletra = "veinte ";
	            } else {
	                this.numletra = "veinti".concat(this.unidad(numero - 20));
	            }
			}else{
				this.numletra = decena5();
			}
		}
    	return this.numletra;
    }
    public String decena5(){
	    if ((numero >= 10) && (numero <= 19)) {
	    	String valores[] = {"diez","once","doce","trece","catorce","quince","dieciseis","diecisiete","dieciocho","diecinueve"};
	        this.numletra=valores[numero-10];
		} 
		else {
			this.numletra = this.unidad(numero);
		}
	    return this.numletra;
    }
    /**
     * Método que transforma números de cuatro dígitos a letras.
     * 
     * @param numero
     *            Número a transformar
     * @return Número en letras
     */
    private String decmiles(int numero) throws Exception {
        if (numero == 10000) {
            this.numletradm = "diez mil";
        }

        if ((numero > 10000) && (numero < 20000)) {
            this.flag = 1;
            this.numletradm = this.decena(numero / 1000).concat("mil ").concat(this.centena(numero % 1000));
        }
        if ((numero >= 20000) && (numero < 100000)) {
            this.flag = 1;
            this.numletradm = this.decena(numero / 1000).concat(" mil ").concat(this.miles(numero % 1000));
        }
        if (numero < 10000) {
            this.numletradm = this.miles(numero);
        }

        return this.numletradm;
    }

    /**
     * Método que transforma números de siete dígitos en letras.
     * 
     * @param numero
     *            Número a transformar
     * @return Número en letras
     */
    private String decmillon(int numero) throws Exception {
        if (numero == 10000000) {
            this.numletradmm = "diez millones";
        } else if ((numero > 10000000) && (numero < 20000000)) {
            this.flag = 1;
            this.numletradmm = this.decena(numero / 1000000).concat("millones ").concat(
                    this.cienmiles(numero % 1000000));
        }

        else if ((numero >= 20000000) && (numero < 100000000)) {
            this.flag = 1;
            this.numletradmm = this.decena(numero / 1000000).concat(" milllones ").concat(
                    this.millon(numero % 1000000));
        } else if (numero < 10000000) {
            this.numletradmm = this.millon(numero);
        }

        return this.numletradmm;
    }

    /**
     * Méodo que transforma números de tres dígitos de números a letras .
     * 
     * @param numero
     *            Número a transformar
     * @return Número en letras
     */
    private String miles(int numero) throws Exception {
        if ((numero >= 1000) && (numero < 2000)) {
            this.numletram = ("un mil ").concat(this.centena(numero % 1000));
        } else if ((numero >= 2000) && (numero < 10000)) {
            this.flag = 1;
            this.numletram = this.unidad(numero / 1000).concat(" mil ").concat(this.centena(numero % 1000));
        } else if (numero < 1000) {
            this.numletram = this.centena(numero);
        }

        return this.numletram;
    }

    /**
     * Método que transforma números de seis digitos en letras.
     * 
     * @param numero
     *            Número a transformar
     * @return Número en letras
     */
    private String millon(int numero) throws Exception {
        if ((numero >= 1000000) && (numero < 2000000)) {
            this.flag = 1;
            this.numletramm = ("Un millon ").concat(this.cienmiles(numero % 1000000));
        }
        if ((numero >= 2000000) && (numero < 10000000)) {
            this.flag = 1;
            this.numletramm = this.unidad(numero / 1000000).concat(" millones ").concat(
                    this.cienmiles(numero % 1000000));
        }
        if (numero < 1000000) {
            this.numletramm = this.cienmiles(numero);
        }

        return this.numletramm;
    }

    /**
     * Método que transforma números de un dígito de números a letras.
     * 
     * @param numero
     *            Número que se va a transformar
     * @return Número en letras
     */
    private String unidad(int numero) {
        String num="";        
        String valores[] = {"","un","dos","tres","cuatro","cinco","seis","siete","ocho","nueve"};
        num=valores[numero];
        return num;
    }
    
    /**
     * Metodo que consulta la moneda oficial parametrizada para el cliente en la tabla
     * TCOMPANIASLICENCIADASID
     * 
     * @return Descripcion de la moneda
     * */
    private String getOfficialClientCurrency() {
        SQLQuery sql;
        String currency = "";
        try {
            sql = Helper.createSQLQuery(SQL_MONEDAOFICIAL);
            sql.setDate("expiredate", ApplicationDates.DEFAULT_EXPIRY_DATE);
            sql.setInteger("company", 2);
            currency = sql.uniqueResult().toString();
        } catch (FitbankException fe) {
            if ("HB002".equals(fe.getCode())) {
                FitbankLogger.getLogger().debug("SESION HIBERNATE NO ASOCIADA, "
                                    + "CREANDO UNA...", fe);
                Helper.setSession(HbSession.getInstance().openSession());
                sql = Helper.createSQLQuery(SQL_MONEDAOFICIAL);
                sql.setDate("expiredate", ApplicationDates.DEFAULT_EXPIRY_DATE);
                sql.setInteger("company", 2);
                currency = sql.uniqueResult().toString();
                Helper.closeSession();
            } else {
                throw fe;
            }
        }

        return currency;
    }
}
