/*
 * ParameterManager.java
 */

package com.uvigo.tMaestro.SCOCreator.tool.adaptation;

import com.uvigo.tMaestro.SCOCreator.tool.MyOptionPane;
import com.uvigo.tMaestro.SCOCreator.tool.MainFrame;

/**
 * Esta clase es una clase intermedia para la lectura de los parametros
 * de adaptacion y sus valores. Es utilizada por el Assistant para
 * la generacion de las reglas
 * @author raul
 * @version 0.1
 */
public class ParameterManager {
    
    /**
     * ArrayList con los parametros definidos en el vocabulario
     * Los elementos son objetos de la clase Parameter (@see Parameter)
     */
    private java.util.ArrayList<Parameter> oParameters;
    
    /**
     * Los nombre de los parametros (aparecen en el mismo orden que el array oParameters)
     */
    private java.util.ArrayList<String> oParametersName;
    
    /**
     * Componente grafico utilizado para la eleccion de un valor para los parametros
     * de tipo ENUMERATION
     */
    private javax.swing.JComboBox oCombo;
    
    
    /**
     * Componente grafico utilizado para la eleccion de un valor para los parametros
     * de tipo INTEGER o REAL
     */
    private javax.swing.JSpinner oSpinner;
    
    
    /**
     * Componente grafico utilizado para la eleccion de un valor para los parametros
     * de tipo TEXT
     */
    private javax.swing.JTextField oTextField;
    
    /**
     * Componente grafico utilizado para la eleccion de un valor para los parametros
     * de tipo Complex
     */
    private javax.swing.JButton oButtonComplex;
    
    /**
     * Referencia al Parameter que esta escuchando el ButtonComplex
     */
    private java.awt.event.ActionListener oListenerComplex;
    
    
    /**
     * Constructor de la clase.
     * Lee el fichero de vocabulario de t-Maestro (contiene los parametros, y sus posibles valores)
     * El fichero de vocabulario (tmaestro.xml) es una fichero .xml que sigue el schema vocabulary.xsd
     */
    public ParameterManager() {
        try {
            //Creamos el JAXBContext y el Unmarshaller que nos serviran de ayuda
            //para leer el fichero .xml de vocabulario.
            javax.xml.bind.JAXBContext oJC = javax.xml.bind.JAXBContext.newInstance("com.uvigo.tMaestro.SCOCreator.tool.adaptation");
            javax.xml.bind.Unmarshaller oUn = oJC.createUnmarshaller();
            com.uvigo.tMaestro.SCOCreator.tool.adaptation.Parameters oParametersElement;
            //Buscamos el fichero .xml en el directorio adaptation
            java.io.InputStream oVocabularyFile = this.getClass().getResource("/com/uvigo/tMaestro/SCOCreator/tool/adaptation/tmaestro.xml").openStream();
           
            //Creamos la estructura con los par�metros del vocabulario
            oParameters = new java.util.ArrayList<Parameter>();
            oParametersName = new java.util.ArrayList<String>();
            oParametersElement = (com.uvigo.tMaestro.SCOCreator.tool.adaptation.Parameters) oUn.unmarshal(oVocabularyFile);
            java.util.List oParameterElements = oParametersElement.getParameter();
            for (Object oObject : oParameterElements) {
                com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType oParameterElement = (com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType) oObject;
                if (oParametersName.contains(oParameterElement.getParameterName())) throw new Exception("Parameter name duplicated");
                oParametersName.add(oParameterElement.getParameterName());
                oParameters.add(createParameter(oParameterElement));
            }
            
            
        } catch(Exception oE) {
            oE.printStackTrace();
            java.awt.Toolkit.getDefaultToolkit().beep();
            MyOptionPane.showMessageDialog(MainFrame.oMainFrame,MainFrame.oMainFrame.getMessage("Error23"),"Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            System.exit(-1);
        }
    }
    
    /**
     * Crea un Parameter a partir del ParameterElement (estructura intermedia generada para leer el xml)
     * @return Un Parameter listo para ser a�adido al HashMap de parametros.
     */
    private Parameter createParameter(com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType oParameterElement) throws Exception {
        if (oParameterElement.getParameterType().equals("enumeration")) return new Parameter(oParameterElement.getParameterName(),Parameter.ENUMERATION,oParameterElement.getValues().getValue());
        if (oParameterElement.getParameterType().equals("integer")) {
            return new Parameter(oParameterElement.getParameterName(),Parameter.INTEGER,oParameterElement.getMin(),oParameterElement.getMax());
        }
        if (oParameterElement.getParameterType().equals("real")) {
            return new Parameter(oParameterElement.getParameterName(),Parameter.REAL,oParameterElement.getMin(),oParameterElement.getMax());
        }
        if (oParameterElement.getParameterType().equals("collection")) {
            java.util.List oListParameterElements = oParameterElement.getParameter();
            java.util.ArrayList oSons = new java.util.ArrayList();
            java.util.ArrayList<String> oNames=new java.util.ArrayList<String>();
            com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType oFirstParameter = (com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType)oListParameterElements.get(0);
            if (oFirstParameter.getParameterType().equals("collection")) throw new Exception("Not valid collection Parameter");
            for (int i=0;i<oListParameterElements.size();i++) {
                com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType oSonParameterElement=(com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType)oListParameterElements.get(i);
                if(oNames.contains(oSonParameterElement.getParameterName())) throw new Exception("Parameter name duplicated");
                oNames.add(oSonParameterElement.getParameterName());
                oSons.add(createParameter(oSonParameterElement));
            }
            return new Parameter(oParameterElement.getParameterName(),Parameter.COLLECTION,oSons);
        }
        if (oParameterElement.getParameterType().equals("complex")) {
            java.util.List oListParameterElements = oParameterElement.getParameter();
            java.util.ArrayList oSons = new java.util.ArrayList();
            java.util.ArrayList<String> oNames=new java.util.ArrayList<String>();
            for (int i=0;i<oListParameterElements.size();i++) {
                com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType oSonParameterElement=(com.uvigo.tMaestro.SCOCreator.tool.adaptation.ParameterType)oListParameterElements.get(i);
                if(oNames.contains(oSonParameterElement.getParameterName())) throw new Exception("Parameter name duplicated");
                oNames.add(oSonParameterElement.getParameterName());
                oSons.add(createParameter(oSonParameterElement));
            }
            return new Parameter(oParameterElement.getParameterName(),Parameter.COMPLEX,oSons);
        }
        if (oParameterElement.getParameterType().equals("boolean")) return new Parameter(oParameterElement.getParameterName(),Parameter.BOOLEAN);
        if (oParameterElement.getParameterType().equals("langCode")) return new Parameter(oParameterElement.getParameterName(),Parameter.LANCODE);
        return new Parameter(oParameterElement.getParameterName(),Parameter.TEXT);
    }
    
    
    
    
    /**
     * Devuelve una array con los nombres de los par�metros
     */
    public Object[] getParameterNames() {
        return oParametersName.toArray();
    }
    
    /**
     * Devuelve el objeto parametro de nombre sName
     * @param El indice del parametro
     * @return Un objeto de la clase Parameter (@see Parameter)
     */
    public Parameter getParameter(int iIndex) {
        return oParameters.get(iIndex);
    }
    
    /**
     * Devuelve el componente grafico que permitira al usuario
     * elegir el valor para el parametro de indice iIndex
     * @param iIndex El indice del parametro
     * @return El componente para elegir el valor
     */
    public java.awt.Component getComponent(int iIndex) {
        
        switch(oParameters.get(iIndex).getType()) {
            case Parameter.ENUMERATION:
                if (oCombo==null) oCombo=new javax.swing.JComboBox();
                oCombo.setModel(new javax.swing.DefaultComboBoxModel(oParameters.get(iIndex).getValues()));
                return oCombo;
            case Parameter.INTEGER:
                if (oSpinner==null) oSpinner=new javax.swing.JSpinner();
                int iMin=Integer.MIN_VALUE;
                int iMax=Integer.MAX_VALUE;
                if (oParameters.get(iIndex).getMin()!=null) iMin=oParameters.get(iIndex).getMin().intValue();
                if (oParameters.get(iIndex).getMax()!=null) iMax=oParameters.get(iIndex).getMax().intValue();
                oSpinner.setModel(new javax.swing.SpinnerNumberModel(0,iMin,iMax, 1));
                return oSpinner;
            case Parameter.REAL:
                if (oSpinner==null) oSpinner=new javax.swing.JSpinner();
                double dMin=-(Double.MAX_VALUE);
                double dMax=Double.MAX_VALUE;
                if (oParameters.get(iIndex).getMin()!=null) dMin=oParameters.get(iIndex).getMin().doubleValue();
                if (oParameters.get(iIndex).getMax()!=null) dMax=oParameters.get(iIndex).getMax().doubleValue();
                oSpinner.setModel(new javax.swing.SpinnerNumberModel(0,dMin,dMax, 0.1));
                return oSpinner;
            case Parameter.LANCODE:
                if (oCombo==null) oCombo=new javax.swing.JComboBox();
                oCombo.setModel(new javax.swing.DefaultComboBoxModel(java.util.Locale.getISOLanguages()));
                return oCombo;
            case Parameter.BOOLEAN:
                if (oCombo==null) oCombo=new javax.swing.JComboBox();
                String[] oBoolean = {"true","false"};
                oCombo.setModel(new javax.swing.DefaultComboBoxModel(oBoolean));
                return oCombo;
            case Parameter.TEXT:
                if (oTextField==null) oTextField=new javax.swing.JTextField();
                return oTextField;
            case Parameter.COLLECTION:
            case Parameter.COMPLEX:
                if (oButtonComplex==null) {
                    oButtonComplex = new javax.swing.JButton(MainFrame.oMainFrame.getMessage("Menu2"));
                }
                //Si oListenerComplex es null no se realiza ninguna accion y el metodo no lanza ninguna excepcion
                oButtonComplex.removeActionListener(oListenerComplex);
                oListenerComplex = oParameters.get(iIndex);
                oButtonComplex.addActionListener(oListenerComplex);
                return oButtonComplex;
                
        }
        return null;
    }
    
    
}
