/*
 * PropertiesCellEditor.java
 *
 */
package com.uvigo.tMaestro.SCOCreator.tool.properties;

import com.uvigo.tMaestro.SCOCreator.tool.*;
import java.net.URL;

/**
 * Esta clase es la encargada de llamar al CellEditor adecuado de acuerdo
 * con el tipo de objeto que se le pasa.
 * Averigua la clase de la propiedad y busca si tiene alg�n TableCellEditor
 * para ese tipo de propiedad.  Si no lo tiene intenta ver si el PropertyEditorManager
 * del paquete javabeans puede proporcionar uno. Si lo proporciona crea un editor
 * delegado que sirve de intermediario entre este CellEditor y el PropertyEditor
 * proporcionado por el PropertyEditorManager.
 * Esta clase carga dinamicamente del paquete
 * com.uvigo.tMaestro.SCOCreator.tool.properties.cellEditors todos los editors que
 * se deseen utilizar.
 * Los editors que se encuentren en dicho paquete deben implementar la interfaz
 * CellEditor.
 * Nota: no osbtante, esta aplicaci�n, en principio, est� dise�ada para funcionar
 * con las clases del paquete com.uvigo.mhp, con lo que diferenciaremos las propiedades
 * no s�lo por su tipo, sino por su nombre. Por ejemplo, la clase hImage tiene una propiedad
 * que es imageURL. Esta propiedad es de tipo String, no obstante interesar� mostrar al usuario
 * un cell editor que le permita elegir la localizaci�n de la imagen en el �rbol de directorios.
 * Es importante que esta distinci�n por el nombre de las propiedades, s�lo se debe hacer con las clases
 * del paquete com.uvigo.mhp
 * @author raul
 * @version 0.1
 */
public class PropertiesCellEditor extends javax.swing.AbstractCellEditor implements javax.swing.table.TableCellEditor {

    /**
     * Esta variable guarda una relaci�n entre las clases de una propiedad y los
     * TableCellEditors adecuados para su edici�n en la celda de una JTable
     */
    private java.util.HashMap<Class, javax.swing.table.TableCellEditor> oEditors;
    /**
     * Editor en el que delegamos para la edici�n de una determinada propiedad
     */
    private javax.swing.table.TableCellEditor oDelegado;

    /**
     * Constructor de la clase. Carga los editors del paquete de renders.
     */
    public PropertiesCellEditor() {
        oEditors = new java.util.HashMap<Class, javax.swing.table.TableCellEditor>();

        //Cargamos din�micamente los editors del directorio de cellEditors
        try {
            //Buscamos los ficheros .class que sean CellEditors
            //Programamos dos comportamientos: si la aplicaci�n se ejecuta desde
            //un jar o desde el �rbol de directorios
            java.net.URI oURI = (this.getClass().getResource("")).toURI();
            java.util.ArrayList<String> oClasses = new java.util.ArrayList<String>();
            if (oURI.getScheme().equals("jar")) { //La aplicaci�n se ejecuta desde el jar
                //SSSS cambiamos SCOCreator.jar
                //TODO cambiamos JarFile por JarInputStream
                //java.util.jar.JarFile oJarFile = new java.util.jar.JarFile("ReloadTotalv4.jar", false);
                String packageUrl = this.getClass().getClassLoader().getResource(this.getClass().getPackage().getName().replace(".", "/")).toString();
                String reloadUrl = packageUrl.substring(packageUrl.indexOf(":") + 1, packageUrl.indexOf("!"));
                java.util.jar.JarInputStream oJarInputStream = new java.util.jar.JarInputStream(new URL(reloadUrl).openStream(), false);
                //String[] aRenders = oJarFile.getManifest().getMainAttributes().getValue("CellEditors").split(" ");
                String[] aRenders = oJarInputStream.getManifest().getMainAttributes().getValue("CellEditors").split(" ");
                oClasses.addAll(java.util.Arrays.asList(aRenders));
            } else { // La aplicaci�n se ejecuta desde el �rbol de directorios
                java.io.File oProperties = new java.io.File((this.getClass().getResource("")).toURI());
                MyDirectoryFilter oFiltro = new MyDirectoryFilter();
                oFiltro.vAddName("cellEditors");
                java.io.File oCellEditors = oProperties.listFiles(oFiltro)[0]; //Directorio cellEditors
                java.io.File[] oNombres = oCellEditors.listFiles();
                int i = 0;
                for (i = 0; i < oNombres.length; i++) {
                    oClasses.add(oNombres[i].getName());
                }
            }

            int i = 0;
            for (i = 0; i < oClasses.size(); i++) { //Cargamos cada una de las classes correspondientes a un CellEditor
                //Descartamos los ficheros que no sean .class
                if (!oClasses.get(i).contains(".class")) {
                    continue;
                }
                String sNombre = (oClasses.get(i).split(".class"))[0]; //Nos quedamos con el nombre de la clase
                Class oClase = Class.forName("com.uvigo.tMaestro.SCOCreator.tool.properties.cellEditors." + sNombre);
                //Instanciamos el CellEditor y lo a�adimos a la hastable
                if (!oClase.getName().contains("$")) {//M: evitamos pretender instanciar inner classes
                    CellEditor oInstancia = (CellEditor) oClase.newInstance();
                    oInstancia.setDelegation(this);
                    oEditors.put(oInstancia.getTypeEditor(), oInstancia);
                }
            }
        } catch (Exception oE) {
            oE.printStackTrace();
            java.awt.Toolkit.getDefaultToolkit().beep();
            MyOptionPane.showMessageDialog(MainFrame.oMainFrame, MainFrame.oMainFrame.getMessage("Error3"), MainFrame.oMainFrame.getMessage("Title2"), javax.swing.JOptionPane.WARNING_MESSAGE);
            System.exit(-1);
        }
    }

    /**
     * M�todo que devuelve un componente para la edici�n de la propiedad.
     */
    public java.awt.Component getTableCellEditorComponent(javax.swing.JTable oTable, Object oValue, boolean isSelected, int iRow, int iColumn) {
        //Averiguamos el editor delegado para la clase a la que pertenece esta propiedad
        Propiedad oPropiedad = ((PropertiesTableModel) oTable.getModel()).oGetPropiedad(iRow);
        MainFrame.oMainFrame.setEditionProperty(oPropiedad);
        Class oClase = oPropiedad.oGetClase();
        oDelegado = oEditors.get(oClase);

        //Ahora vemos si la propiedad es una propiedad especial de las clases de com.uvigo.mhp
        if ((oPropiedad.oGetClase().equals(String.class))) {
            if ((oPropiedad.getBean().getClass().getPackage().getName().contains("com.uvigo.mhp")) || (oPropiedad.getBean() instanceof com.uvigo.mhp.Page)) {
                if (oPropiedad.oGetName().toLowerCase().contains("imageurl")) {
                    oDelegado = oEditors.get(com.uvigo.tMaestro.SCOCreator.tool.properties.cellEditors.URLEditor.class);

                }
                if (oPropiedad.oGetName().toLowerCase().contains("file")) {
                    oDelegado = oEditors.get(com.uvigo.tMaestro.SCOCreator.tool.properties.cellEditors.ContentEditor.class);
                }
            }
        }


        //Si no hay un editor para este tipo vemos si el dise�ador del bean ha proporcionado uno o
        //si el PropertyEditorManager puede localizar alguno
        if (oDelegado == null) {
            java.beans.PropertyEditor oPropEditor = oPropiedad.oGetEditor();
            if (oPropEditor == null) {
                oPropEditor = java.beans.PropertyEditorManager.findEditor(oClase);
            }
            if (oPropEditor != null) {
                oDelegado = new DelegateEditor(this, oPropEditor);
            } else {
                System.out.println(oClase + "  NOT EDITABLE"); //NOTA --> arrelgar esto
                oPropiedad.setReadOnly(true);
                fireEditingStopped();
                return null;
            }
        }
        //Llamamos al Editor delegado
        java.awt.Component oComponent = oDelegado.getTableCellEditorComponent(oTable, oValue, isSelected, iRow, iColumn);
        return (oComponent);
    }

    /**
     * Devuelve el valor editado. Este valor es propoercionado
     * por el editor delegado.
     * @return El nuevo valor
     */
    public Object getCellEditorValue() {
        return oDelegado.getCellEditorValue();
    }

    /**
     * Este m�todo es usado por el editor delegado para notificar que
     * ya ha finalizado la edici�n de la propiedad.
     */
    public void vEditado() {
        fireEditingStopped();
    }

    /**
     * Este m�todo es usado por el editor delegado para notificar que
     * no se pueden llevar a cabo los cambios en la propiedad.
     */
    public void vCancel() {
        fireEditingCanceled();
    }
}
