/*
 * Element.java
 *
 */

package com.uvigo.tMaestro.SCOCreator.tool.metadata;
import java.math.BigDecimal;
import com.uvigo.tMaestro.SCOCreator.tool.MainFrame;

/**
 * La clase mantiene informacion sobre un elemento de los metadatos
 * presentados por el formulario. Es una clase auxiliar que se utilza en
 * la generacion del formulario de metadatos y que se utiliza para leer sus
 * valores en el momento de la creacion del fichero .xml de metadatos
 * @author raul
 * @version 0.1
 */
public class Element {
    
    /*
     * Estas constantes se utilizan para identificar el tipo del elemento
     */
    final public static int INTEGER=0;
    final public static int REAL=1;
    final public static int BOOLEAN=2;
    final public static int TEXT=3;
    final public static int ENUMERATION=4;
    final public static int COMPLEX=5;
    final public static int LANCODE=6;
    
    
    /**
     * Parte del nombre jerarquico del elemento que no imcluye su nombre simple
     */
    private String sPrefixName;
    
    /**
     * Nombre simple del elemento
     */
    private String sName;
    
    
    /**
     * Nombre para mostrar en pantalla
     */
    private String sScreenName;
    
    /**
     * El Tipo del parametro. Ver las variables estaticas definidas al principio
     * de esta clase
     */
    private int iType;
    
    
    /**
     * Valor miimos permitido para el parametro si es de tipo numerico
     */
    private BigDecimal oMin;
    
    
    /**
     * Valor maximo permitido para el parametro si es de tipo numerico
     */
    private BigDecimal oMax;
    
    /**
     * Lista de valores validos del parametro si es de tipo enumerado
     *
     */
    private java.util.List oList;
    
    
    /**
     * Referencia al elemento grafico que permite elegir un valor para este elemento
     */
    private java.awt.Component oRef;
    
    /**
     * Inicializa la clase
     * @param sPefixName Prefijo del nombre jerarquico del elemento  que no incluye el nombre simple
     * @param sName El nombre del elemento
     * @param sScreenName El nombre para mostrar en pantalla del elemento
     * @param iType El tipo del elemento
     * @param fMin Valor minimo si el elemento es numerico. Si no es num�rico debe valer null.
     * @param fMax Valor maximo si el elemento es numerico. Si no es num�rico debe valer null.
     * @param oList La lista de valores (si es enumerado)
     * @throws Exception Si el nombre del parametro es null o vacio
     */
    private void init(String sPrefixName,String sName,String sScreenName,int iType,BigDecimal oMin,BigDecimal oMax,java.util.List oList) throws Exception {
        if (sName==null || sName.equals("")) throw new Exception("Element must be named");
        this.sName = new String(sName);
        this.iType = iType;
        this.oMax= oMax;
        this.oMin = oMin;
        this.oList = oList;
        this.sScreenName=sScreenName;
        this.sPrefixName=sPrefixName;
        
    }
    
    /**
     * Constructor para los elementos numericos.
     * @param sPefixName Prefijo del nombre jerarquico del elemento  que no incluye el nombre simple
     * @param sName El nombre del elemento
     * @param sScreenName El nombre para mostrar en pantalla
     * @param iType El tipo del elemento (INTEGER o REAL)
     * @param fMin Valor minimo
     * @param fMax Valor maximo
     * @throws Exception Si el tipo es incorrecto o el nombre es null, etc
     */
    public Element(String sPrefixName,String sName,String sScreenName,int iType, BigDecimal oMin,BigDecimal oMax) throws Exception {
        if (iType!=INTEGER && iType!=REAL) throw new Exception("This contructor is not suitable for this Element");
        init(sPrefixName,sName,sScreenName,iType,oMin,oMax,null);
    }
    
    /**
     * Contructor para los tipos enumerados o complex
     * @param sPefixName Prefijo del nombre jer�rquico del elemento  que no incluye el nombre simple
     * @param sName el nombre
     * @param sScreenName El nombre para mostrar en pantalla
     * @param Los posibles valores
     * @throws Exception Si el tipo es incorrecto o oList es null
     */
    public Element(String sPrefixName,String sName,String sScreenName,int iType,java.util.List oList) throws Exception {
        if (iType!=ENUMERATION && iType!=COMPLEX) throw new Exception("This contructor is not suitable for this Element");
        if ((oList==null) || (oList.size()==0)) throw new Exception("There are not values");
        init(sPrefixName,sName,sScreenName,iType, null,null, oList);
    }
    
    
    /**
     * Constructor para los tipos Boolean y Text
     *  @param sPefixName Prefijo del nombre jerarquico del elemento  que no incluye el nombre simple
     * @param sName El nombre
     * @param sScreenName El nombre para mostrar en pantalla
     * @throws Exception Si el tipo es incorrecto
     */
    public Element(String sPrefixName,String sName,String sScreenName,int iType) throws Exception {
        if (iType!=BOOLEAN && iType!=TEXT &&  iType!=LANCODE) throw new Exception("This contructor is not suitable for this Element");
        init(sPrefixName,sName,sScreenName, iType, null, null, null);
    }
    
    /**
     * Metodo que devuelve el nombre del elemento
     */
    public String getName() {
        return this.sName;
    }
    
    /**
     * Metodo que devuelve el nombre para mostrar en pantalla del elemento
     */
    public String getScreenName() {
        return sScreenName;
    }
    
    /**
     * Metodo que devuelve el tipo del elemento
     */
    public int getType() {
        return iType;
    }
    
    
    /**
     * Devuelve el componente grafico que permitira al usuario
     * elegir el valor para este elemento
     * @param z El indice del grupo de metadatos al que pertenece este elementos
     * @return El componente para elegir el valor
     * Null si es el tipo complex
     */
    public java.awt.Component getComponent(int z) {
        
        //if (oRef!=null) return oRef;
        Object oValue=null;
        switch(this.iType) {
            case ENUMERATION:
                javax.swing.JComboBox oCombo=new javax.swing.JComboBox();
                oCombo.setModel(new javax.swing.DefaultComboBoxModel(oList.toArray()));
                oCombo.insertItemAt("",0);
                oCombo.setSelectedItem("");
                oCombo.setEditable(true);
                oCombo.setPreferredSize(new java.awt.Dimension(30,19));
                //Cargamos el valor previo del elemento
                oValue=MainFrame.oMainFrame.getMetadata(sPrefixName+"."+sName,z);
                if (oValue!=null) oCombo.setSelectedItem(oValue);
                oRef= oCombo;
                break;
            case INTEGER:
                javax.swing.JSpinner oSpinner=new javax.swing.JSpinner();
                int iMin=Integer.MIN_VALUE;
                int iMax=Integer.MAX_VALUE;
                if (oMin!=null) iMin=oMin.intValue();
                if (oMax!=null) iMax=oMax.intValue();
                oSpinner.setModel(new javax.swing.SpinnerNumberModel(iMin-1,iMin-1,iMax, 1));
                oSpinner.setPreferredSize(new java.awt.Dimension(30,19));
                //Cargamos el valor previo del elemento
                oValue=MainFrame.oMainFrame.getMetadata(sPrefixName+"."+sName,z);
                if (oValue!=null) oSpinner.setValue(oValue);
                oRef= oSpinner;
                break;
            case REAL:
                javax.swing.JSpinner oSpinnerR=new javax.swing.JSpinner();
                double dMin=-(Double.MAX_VALUE);
                double dMax=Double.MAX_VALUE;
                if (oMin!=null) dMin=oMin.doubleValue();
                if (oMax!=null) dMax=oMax.doubleValue();
                //Ponemos el valor anterior en una unidad al minimo como valor inicial (no es valido)
                //Lo hacemos para distinguir los campos que no han sido modificados por el usuario
                oSpinnerR.setModel(new javax.swing.SpinnerNumberModel(dMin-1,dMin-1,dMax, 0.1));
                oSpinnerR.setPreferredSize(new java.awt.Dimension(30,19));
                //Cargamos el valor previo del elemento
                oValue=MainFrame.oMainFrame.getMetadata(sPrefixName+"."+sName,z);
                if (oValue!=null) oSpinnerR.setValue(oValue);
                oRef= oSpinnerR;
                break;
            case LANCODE:
                javax.swing.JComboBox oComboL=new javax.swing.JComboBox();
                oComboL.setModel(new javax.swing.DefaultComboBoxModel(java.util.Locale.getISOLanguages()));
                oComboL.setPreferredSize(new java.awt.Dimension(30,19));
                oComboL.setEditable(true);
                oComboL.insertItemAt("",0);
                oComboL.setSelectedItem("");
                //Cargamos el valor previo del elemento
                oValue=MainFrame.oMainFrame.getMetadata(sPrefixName+"."+sName,z);
                if (oValue!=null) oComboL.setSelectedItem(oValue);
                oRef= oComboL;
                break;
            case BOOLEAN:
                javax.swing.JComboBox oComboB =new javax.swing.JComboBox();
                String[] oBoolean = {"true","false"};
                oComboB.setModel(new javax.swing.DefaultComboBoxModel(oBoolean));
                oComboB.insertItemAt("",0);
                oComboB.setSelectedItem("");
                //Cargamos el valor previo del elemento
                oValue=MainFrame.oMainFrame.getMetadata(sPrefixName+"."+sName,z);
                if (oValue!=null) oComboB.setSelectedItem(oValue);
                oRef= oComboB;
                break;
            case TEXT:
                javax.swing.JTextField oTextField=new javax.swing.JTextField();
                //Cargamos el valor previo del elemento
                oValue=MainFrame.oMainFrame.getMetadata(sPrefixName+"."+sName,z);
                if (oValue!=null) oTextField.setText((String)oValue);
                oRef= oTextField;
                break;
            case COMPLEX: oRef=null;
            
        }
        return oRef;
    }
    
    /**
     * Si el tipo es complex devuelve el elemento hijo
     * de indice iIndex. Null en caso contrario
     */
    public Element getElement(int iIndex) {
        if (iType!=COMPLEX || oList==null) return null;
        return (Element) oList.get(iIndex);
        
    }
    
    /**
     * Devuelve el numero de elementos hijos de este elemento
     */
    public int sizeElements() {
        if (oList==null) return 0;
        return oList.size();
    }
    
    public String getPrefixName() {
        return sPrefixName;
    }
    
    public void setPrefixName(String sPrefixName) {
        this.sPrefixName = sPrefixName;
    }
    
    /**
     * Devuelve el valor del campo de formulario
     */
    public Object getValue() {
        if (oRef==null) return null;
        Object oValue;
        switch(this.iType) {
            case ENUMERATION:
                oValue=((javax.swing.JComboBox) oRef).getSelectedItem();
                if (oValue.equals("")) return null;
                return oValue;
            case INTEGER:
                oValue= ((javax.swing.JSpinner) oRef).getValue();
                if (oValue.equals(oMin.intValue()-1)) return null;
                return oValue;
            case REAL:
                oValue= ((javax.swing.JSpinner) oRef).getValue();
                if (oValue.equals(oMin.doubleValue()-1)) return null;
                return oValue;
            case LANCODE:
                oValue=((javax.swing.JComboBox) oRef).getSelectedItem();
                if (oValue.equals("")) return null;
                return oValue;
            case BOOLEAN:
                oValue=((javax.swing.JComboBox) oRef).getSelectedItem();
                if (oValue.equals("")) return null;
                return oValue;
            case TEXT:
                oValue=((javax.swing.JTextField) oRef).getText();
                if (oValue.equals("")) return null;
                return oValue;
            case COMPLEX:
        }
        return null;
    }
}
