package com.fitbank.schemautils;

import java.util.Collection;

import com.fitbank.util.CaseInsensitiveSet;
import org.apache.commons.lang.StringUtils;

/**
 * Clase Field.
 * 
 * @author FitBank
 */
public class Field {

    private String type = "";

    private boolean required = false;

    private boolean primaryKey = false;

    private DescriptionKey descriptionKey;

    private final Collection<String> childTables = new CaseInsensitiveSet();

    private final Collection<String> parentTables = new CaseInsensitiveSet();

    private String defaultValue = "";

    private String code = "";

    private String name = "";

    private String description = "";

    /**
     * Crea un nuevo objeto Field.
     */
    public Field() {
    }

    /**
     * Cambia el type de este campo.
     * 
     * @param type
     *            String con el type
     */
    public void setType(String tipo) {
        this.type = tipo == null ? "" : tipo;
    }

    /**
     * Obtiene el type de este campo.
     * 
     * @return String con el type
     */
    public String getType() {
        return type;
    }

    /**
     * Obtiene el type de este campo.
     * 
     * @return String con el type
     */
    public int getLength() {
        if (type.indexOf("VARCHAR2(") != -1) {
            return Integer.parseInt(type.substring(9, type.length() - 1));
        } else if (type.indexOf("NUMBER(") != -1) {
            String sub = type.substring(7, type.length() - 1);
            if (sub.indexOf(",") == -1) {
                return Integer.parseInt(sub);
            } else {
                return Integer.parseInt(sub.substring(0, sub.indexOf(",")))
                        + Integer.parseInt(sub.substring(sub.indexOf(",") + 1))
                        + 1;
            }
        } else {
            return 20;
        }
    }

    /**
     * Devuelve un formato para ser usado en cualquier fomateador de java de numeros como DecimalFormat.
     *
     * @return String con el formato como #,##0.000
     */
    public String getNumberFormat() {
        String sub = type.substring("NUMBER(".length(), type.length() - 1);

        if (sub.indexOf(",") == -1) {
            return "0";
        } else {
            int dec = Integer.parseInt(sub.substring(sub.indexOf(",") + 1));

            return "0." + StringUtils.repeat("0", dec);
        }

    }

    /**
     * @deprecated Usar mejor getType
     */
    @Deprecated
    public String getTipoDato() {
        return type;
    }

    /**
     * @deprecated Usar mejor getNumberFormat o getLength
     */
    @Deprecated
    public String getTipoDatoExtra() {
        if (type.indexOf("NUMBER") != -1) {
            String sub = type.substring(7, type.length() - 1);
            if (sub.indexOf(",") != -1) {
                return sub.substring(sub.indexOf(","));
            }
        }
        return "";
    }

    /**
     * Cambia la propiedad de required de este campo.
     * 
     * @param required
     *            String con el nuevo valor
     */
    public void setRequired(boolean mandatorio) {
        this.required = mandatorio;
    }

    /**
     * Obtiene la propiedad required de este campo.
     * 
     * @return String con la propiedad
     */
    public boolean getRequired() {
        return required;
    }

    /**
     * Cambia la propiedad de llave primaria de este campo.
     * 
     * @param primaryKey
     *            String con la nueva propiedad
     */
    public void setPrimaryKey(boolean llavePrimaria) {
        this.primaryKey = llavePrimaria;
    }

    /**
     * Obtiene la propiedad de llave primaria de este campo.
     * 
     * @return String con la propiedad
     */
    public boolean getPrimaryKey() {
        return primaryKey;
    }

    /**
     * Cambia la tabla raiz de este campo.
     *
     * @param parentTable
     *            String con el nuevo nombre de la tabla padre
     */
    public void setDescriptionKey(DescriptionKey descriptionKey) {
        this.descriptionKey = descriptionKey;
    }

    /**
     * Obtiene la tabla raiz de este campo.
     *
     * @return String con el nombre de la tabla padre
     */
    public DescriptionKey getDescriptionKey() {
        return descriptionKey;
    }

    /**
     * Obtiene las tables hijas de este campo.
     *
     * @return String con los nombres de las tables hijas
     */
    public Collection<String> getChildTables() {
        return childTables;
    }

    /**
     * Obtiene las tables hijas de este campo.
     *
     * @return String con los nombres de las tables hijas
     */
    public Collection<String> getParentTables() {
        return parentTables;
    }

    /**
     * Cambia el valor por defecto de este campo.
     * 
     * @param defaultValue
     *            String con el nuevo valor por defecto
     */
    public void setDefaultValue(String valorPorDefecto) {
        this.defaultValue = valorPorDefecto == null ? "" : valorPorDefecto.trim();
    }

    /**
     * Obtiene el valor por defecto de este campo.
     * 
     * @return String con el valor por defecto
     */
    public String getDefaultValue() {
        return defaultValue;
    }

    /**
     * Cambia el name de este objeto.
     * 
     * @param name
     *            String con el nuevo name
     */
    public void setName(String name) {
        this.name = name == null ? "" : name;
    }

    /**
     * Obtiene el name de este objeto.
     * 
     * @return String con el name
     */
    public String getName() {
        return name;
    }

    /**
     * Cambia el número de este objeto.
     * 
     * @param code
     *            String con el nuevo número
     */
    public void setCode(String code) {
        this.code = code == null ? "" : code;
    }

    /**
     * Obtiene el número de este objeto.
     * 
     * @return String con el número
     */
    public String getCode() {
        return code;
    }

    /**
     * Cambia la descripción de este objeto.
     * 
     * @param description
     *            String con la nueva descripción
     */
    public void setDescription(String description) {
        this.description = description == null ? "" : description;
    }

    /**
     * Obtiene la descripción de este objeto.
     * 
     * @return String con la descripción
     */
    public String getDescription() {
        return description;
    }

}
