/*
editeurconfig - Editeur de Fichiers de Config de Jaxe

Copyright (C) 2011 Observatoire de Paris-Meudon

Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier conformément aux dispositions de la Licence Publique Générale GNU, telle que publiée par la Free Software Foundation ; version 2 de la licence, ou encore (à votre choix) toute version ultérieure.

Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION A UN OBJET PARTICULIER. Pour plus de détail, voir la Licence Publique Générale GNU .

Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis.
*/

package editeurconfig;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.border.*;
import java.util.*;
import org.w3c.dom.*;
import javax.swing.text.BadLocationException;
import javax.swing.filechooser.FileFilter;
import java.io.*;


/**
* Classe pour créer ou éditer l'élément ENREGISTREMENT du fichier de config
*/
public class EditeurEnregistrement extends JFrame {
	private FenetreEdition fe;
    private Document doc;
    private Element racine;
    private Element enregistrement;
    
    private JPanel panelBoutonsBas;
    
    private JPanel panelEnregistrement;
    private JPanel listePanelPrefixeEspace;   
    
    
    public EditeurEnregistrement(final FenetreEdition fe, final Document doc, final Element racine) {
        super(Strings.get("titre.EditeurEnregistrement"));
        this.fe = fe;
        this.doc = doc;
        this.racine = racine;
        
        Element langage = Outils.premierEnfantDeNom(racine, "LANGAGE");
        enregistrement = Outils.premierEnfantDeNom(racine, "ENREGISTREMENT");
        
        if (enregistrement == null) {
            enregistrement = doc.createElement("ENREGISTREMENT");
            if(langage.getNextSibling() != null)
                racine.insertBefore(enregistrement, langage.getNextSibling());
            else
                racine.appendChild(enregistrement);
        }
        
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        afficher();
    }
    
    
    private void afficher() {
        
        setLayout(new BorderLayout());
        //setPreferredSize(new Dimension(700,400));
        
        panelEnregistrement = new JPanel();
        panelEnregistrement.setLayout(new BoxLayout(panelEnregistrement, BoxLayout.Y_AXIS));
        final JScrollPane defilementEnregistrement = new JScrollPane(panelEnregistrement);
        add(defilementEnregistrement,BorderLayout.CENTER);
        
        creerPanelEnregistrement();
        
        final JPanel panelBoutonsBas = new JPanel(new FlowLayout());
        add(panelBoutonsBas,BorderLayout.SOUTH);
        final JButton bTester = new JButton(new AbstractAction("Tester") {
            public void actionPerformed(ActionEvent e) {
                EditeurFichierConfig.convertToString(doc);
            }
        });
        //panelBoutonsBas.add(bTester);
        
        final JButton bFermer = new JButton(new AbstractAction(Strings.get("bouton.Fermer")) {
            public void actionPerformed(ActionEvent e) {
                nettoyerDOM();
                setVisible(false);
                fe.afficher();
            }
        });
        panelBoutonsBas.add(bFermer);
        
        pack();
        final Dimension dim = getSize();
        final Dimension ecran = getToolkit().getScreenSize();
        setLocation((ecran.width - dim.width)/2, (ecran.height - dim.height)/2);
        setVisible(true);
    }
       
        
    /**
    * Crée le panel Enregistrement
    */
    private void creerPanelEnregistrement() {
        creerPanelEncodage();
        creerPanelDoctype();
        creerPanelSchemaLocation();
        
        listePanelPrefixeEspace = new JPanel();
        listePanelPrefixeEspace.setLayout(new BoxLayout(listePanelPrefixeEspace, BoxLayout.Y_AXIS));
        panelEnregistrement.add(listePanelPrefixeEspace);
        recupererPrefixeEspace();
    }
    
    /**
    * Crée le panel Encodage
    */
    private void creerPanelEncodage() {
        
        Element encodage = Outils.premierEnfantDeNom(enregistrement, "ENCODAGE");
        
        JPanel panEncodage = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panelEnregistrement.add(panEncodage);
        JLabel encodage_l = new JLabel(Strings.get("label.Encodage"));
        JTextField encodage_t = new JTextField(15);
        panEncodage.add(encodage_l);
        panEncodage.add(encodage_t);
        
        if (encodage != null)
            encodage_t.setText(Outils.getValeurElement(encodage));
        
        // écouteur sur encodage
        encodage_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurEncodage(de);
            }
            public void insertUpdate(DocumentEvent de) {
               ecouteurEncodage(de);
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurEncodage(de);
            }
        });
    }
    
    
    /**
    * Crée le panel Doctype
    */
    private void creerPanelDoctype() {
        
        Element doctype = Outils.premierEnfantDeNom(enregistrement, "DOCTYPE");
        
        final JPanel panDoctype = new JPanel(new GridLayout(2,1));
        panelEnregistrement.add(panDoctype);
        panDoctype.setBorder(new TitledBorder(Strings.get("label.Doctype")));
        
        final JPanel panPublicId = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panDoctype.add(panPublicId);
        final JLabel publicId_l = new JLabel(Strings.get("label.PublicId"));
        final JTextField publicId_t = new JTextField(15);
        panPublicId.add(publicId_l);
        panPublicId.add(publicId_t);
        
        if (doctype != null)
            publicId_t.setText(doctype.getAttribute("publicId"));
            
        // écouteur sur publicId
        publicId_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurDoctype(de, "publicId");
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurDoctype(de, "publicId");
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurDoctype(de, "publicId");
            }
        });
        
        final JPanel panSystemId = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panDoctype.add(panSystemId);
        final JLabel systemId_l = new JLabel(Strings.get("label.SystemId"));
        final JTextField systemId_t = new JTextField(15);
        panSystemId.add(systemId_l);
        panSystemId.add(systemId_t);
        
        if (doctype != null)
            systemId_t.setText(doctype.getAttribute("systemId"));
            
        // écouteur sur systemId
        systemId_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurDoctype(de, "systemId");
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurDoctype(de, "systemId");
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurDoctype(de, "systemId");
            }
        });
    }
    
    
    /**
    * Crée le panel Schema Location
    */
    private void creerPanelSchemaLocation() {
        
        Element schemalocation = Outils.premierEnfantDeNom(enregistrement, "SCHEMALOCATION");
        
        final JPanel panSchemaLocation = new JPanel(new GridLayout(2,1));
        panelEnregistrement.add(panSchemaLocation);
        panSchemaLocation.setBorder(new TitledBorder(Strings.get("label.SchemaLocation")));
        
        final JPanel panLocation = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panSchemaLocation.add(panLocation);
        final JLabel schemalocation_l = new JLabel(Strings.get("label.schemaLocation"));
        final JTextField schemalocation_t = new JTextField(15);
        panLocation.add(schemalocation_l);
        panLocation.add(schemalocation_t);
        
        if (schemalocation != null)
            schemalocation_t.setText(schemalocation.getAttribute("schemaLocation"));
            
        // écouteur sur schemaLocation
        schemalocation_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurSchemaLocation(de, "schemaLocation");
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurSchemaLocation(de, "schemaLocation");
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurSchemaLocation(de, "schemaLocation");
            }
        });
        
        final JPanel panNoNameSpace = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panSchemaLocation.add(panNoNameSpace);
        final JLabel noNameSpace_l = new JLabel(Strings.get("label.NoNameSpaceShemaLocation"));
        final JTextField noNameSpace_t = new JTextField(15);
        panNoNameSpace.add(noNameSpace_l);
        panNoNameSpace.add(noNameSpace_t);
        
        if (schemalocation != null)
            noNameSpace_t.setText(schemalocation.getAttribute("noNamespaceSchemaLocation"));
            
        // écouteur sur noNameSpaceSchemaLocation
        noNameSpace_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurSchemaLocation(de, "noNamespaceSchemaLocation");
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurSchemaLocation(de, "noNamespaceSchemaLocation");
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurSchemaLocation(de, "noNamespaceSchemaLocation");
            }
        });
    }

    
    /**
    * Crée le panel Prefixe espace
    */
    private void creerPanelPrefixeEspace(final Element prefixe_espace, final int index) {
        
        final JPanel panPrefixeEspaceTout = new JPanel(new FlowLayout(FlowLayout.LEFT));
        listePanelPrefixeEspace.add(panPrefixeEspaceTout);
        
        final JPanel panPrefixeEspace = new JPanel(new GridLayout(2,1));
        panPrefixeEspaceTout.add(panPrefixeEspace);
        panPrefixeEspace.setBorder(new TitledBorder(Strings.get("label.PrefixeEspace")));
        
        final JPanel panPrefixe = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panPrefixeEspace.add(panPrefixe);
        JLabel prefixe_l = new JLabel(Strings.get("label.Prefixe"));
        final JTextField prefixe_t = new JTextField(15);
        panPrefixe.add(prefixe_l);
        panPrefixe.add(prefixe_t);
        
        if (prefixe_espace != null)
            prefixe_t.setText(prefixe_espace.getAttribute("prefixe"));
            
        // écouteur sur prefixe
        prefixe_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurPrefixeEspace(de, index, "prefixe");
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurPrefixeEspace(de, index, "prefixe");
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurPrefixeEspace(de, index, "prefixe");
            }
        });
        
        final JPanel panURI = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panPrefixeEspace.add(panURI);
        JLabel uri_l = new JLabel(Strings.get("label.URI"));
        final JTextField uri_t = new JTextField(15);
        panURI.add(uri_l);
        panURI.add(uri_t);
        
        if (prefixe_espace != null)
            uri_t.setText(prefixe_espace.getAttribute("uri"));
            
        // écouteur sur uri
        uri_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurPrefixeEspace(de, index, "uri");
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurPrefixeEspace(de, index, "uri");
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurPrefixeEspace(de, index, "uri");
            }
        });
        
        final JPanel panPlusMoins = new JPanel(new FlowLayout());
        panPrefixeEspaceTout.add(panPlusMoins);
        
        //int position = listePanelPrefixeEspace.getComponentZOrder(panPrefixeEspaceTout);
        //System.out.println("position: "+position);
        //if (position == (listePanelPrefixeEspace.getComponentCount()-1))
            
        final JButton boutonPlus = new JButton(new AbstractAction("+") {
            public void actionPerformed(ActionEvent e) {                
                if (!("".equals(prefixe_t.getText()))) {
                    if (!("".equals(uri_t.getText()))) {
                        creerPanelPrefixeEspace(null, listePanelPrefixeEspace.getComponentCount());
                        listePanelPrefixeEspace.revalidate();
                    }
                }
            }
        });
        panPlusMoins.add(boutonPlus);
        
        final JButton boutonMoins = new JButton(new AbstractAction("-") {
            public void actionPerformed(ActionEvent e) {
                if(listePanelPrefixeEspace.getComponentCount() > 1) {
                    listePanelPrefixeEspace.remove(panPrefixeEspaceTout);
                    listePanelPrefixeEspace.revalidate();
                    Element element_prefixe_espace = trouverPrefixeEspace(index);
                    if (element_prefixe_espace != null)
                        element_prefixe_espace.getParentNode().removeChild(element_prefixe_espace);
                }
            }
        });
        panPlusMoins.add(boutonMoins);
    }
    
    /*********************************** Ecouteurs ***********************************************/
    /**
    * Ecouteur sur le champ Encodage
    * @param Un DocumentEvent
    */
    private void ecouteurEncodage(final DocumentEvent de) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texte = source.getText(0, source.getLength());
            enregistrerEncodage(texte);
            
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }
    
    /**
    * Ecouteur sur le champ DOCTYPE
    * @param Un DocumentEvent
    */
    private void ecouteurDoctype(final DocumentEvent de, final String champ) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texte = source.getText(0, source.getLength());
            if ("publicId".equals(champ))
                enregistrerDoctype(texte, null);
            if ("systemId".equals(champ))
                enregistrerDoctype(null, texte);
                
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }
    
    
    /**
    * Ecouteur sur le champ schemaLocation
    * @param Un DocumentEvent
    */
    private void ecouteurSchemaLocation(final DocumentEvent de, final String champ) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texte = source.getText(0, source.getLength());
            if ("schemaLocation".equals(champ))
                enregistrerSchemaLocation(texte, null);
            if ("noNamespaceSchemaLocation".equals(champ))
                enregistrerSchemaLocation(null, texte);
                
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }
    
    
    
    /**
    * Ecouteur sur le champ prefixe
    * @param Un DocumentEvent
    */
    private void ecouteurPrefixeEspace(final DocumentEvent de, final int index, final String champ) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texte = source.getText(0, source.getLength());
            if ("prefixe".equals(champ))
                enregistrerPrefixeEspace(index, texte, null);
            if ("uri".equals(champ))
                enregistrerPrefixeEspace(index, null, texte);
                
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }


    
    /*********************************** Opération DOM *****************************************/
    // ENCODAGE
    private Element enregistrerEncodage(final String texteEncodage) {
        Element doctype = Outils.premierEnfantDeNom(enregistrement, "DOCTYPE");
        Element encodage = Outils.premierEnfantDeNom(enregistrement, "ENCODAGE");
        if (encodage == null) {
            encodage = doc.createElement("ENCODAGE");
            if (doctype != null)
                enregistrement.insertBefore(encodage, doctype);
            else 
                enregistrement.appendChild(encodage);
        }
        if (texteEncodage != null)
            Outils.setValeurElement(doc, encodage, texteEncodage);
            
        return encodage;
    }
    
    
    // DOCTYPE
    private Element enregistrerDoctype(final String publicid, final String systemid) {
        Element schemalocation = Outils.premierEnfantDeNom(enregistrement, "SCHEMALOCATION");
        Element doctype = Outils.premierEnfantDeNom(enregistrement, "DOCTYPE");
        if (doctype == null) {
            doctype = doc.createElement("DOCTYPE");
            if (schemalocation != null)
                enregistrement.insertBefore(doctype, schemalocation);
            else
                enregistrement.appendChild(doctype);
        }
        if (publicid != null)
            doctype.setAttribute("publicId", publicid);
        if (systemid != null)
            doctype.setAttribute("systemId", systemid);
            
        return doctype;
    }
    
    
    // SCHEMALOCATION
    private Element enregistrerSchemaLocation(final String schemaL, final String noNameS) {
        Element prefixe_espace = Outils.premierEnfantDeNom(enregistrement, "PREFIXE_ESPACE");
        Element schemalocation = Outils.premierEnfantDeNom(enregistrement, "SCHEMALOCATION");
        if (schemalocation == null) {
            schemalocation = doc.createElement("SCHEMALOCATION");
            if (prefixe_espace != null)
                enregistrement.insertBefore(schemalocation, prefixe_espace);
            else
                enregistrement.appendChild(schemalocation);
        }
        if (schemaL != null)
            schemalocation.setAttribute("schemaLocation", schemaL);
        if (noNameS != null)
            schemalocation.setAttribute("noNamespaceSchemaLocation", noNameS);
            
        return schemalocation;
    }
    
    
    // PREFIXE_ESPACE
    private Element enregistrerPrefixeEspace(final int index, final String prefixe, final String uri) {
        Element prefixe_espace = trouverPrefixeEspace(index);
        if (prefixe_espace == null) {
            prefixe_espace = doc.createElement("PREFIXE_ESPACE");
            enregistrement.appendChild(prefixe_espace);
        }
        if (prefixe != null)
            prefixe_espace.setAttribute("prefixe", prefixe);
        if (uri != null)
            prefixe_espace.setAttribute("uri", uri);
            
        return prefixe_espace;
    }
    
    private Element trouverPrefixeEspace(int index) {
        if (index == -1)
            return(null);
        if (enregistrement == null)
            return(null);
        int ip = 0;
        for (Node n = enregistrement.getFirstChild(); n != null; n = n.getNextSibling()) {
            if (n instanceof Element && "PREFIXE_ESPACE".equals(n.getNodeName())) {
                if (ip == index)
                    return((Element)n);
                ip++;
            }
        }
        return(null);
    }
    
    
    
    
    /**
    * Remplir le champ Prefixe espace à partir du DOM 
    */
    private void recupererPrefixeEspace() {
        listePanelPrefixeEspace.removeAll();
        if (enregistrement != null) {
            Element prefixe_espace = Outils.premierEnfantDeNom(enregistrement, "PREFIXE_ESPACE");
            creerPanelPrefixeEspace(prefixe_espace, 0);
            
            int enfants = enregistrement.getChildNodes().getLength();
            for (int i = 1; i < enfants ; i++) {
                prefixe_espace = Outils.enfantSuivantDeMemeNom(prefixe_espace);
                if (prefixe_espace != null)
                    creerPanelPrefixeEspace(prefixe_espace, i);
            }
        }
    }
    
    
    // nettoyer le DOM des éléments vide
    private void nettoyerDOM() {
        if (!enregistrement.hasChildNodes())
            racine.removeChild(enregistrement);
        else {
            for (Node n = enregistrement.getFirstChild(); n != null; n = n.getNextSibling())
                if ("ENCODAGE".equals(n.getNodeName()) && (!n.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n))))
                    enregistrement.removeChild(n);
                    
            for (Node n1 = enregistrement.getFirstChild(); n1 != null; n1 = n1.getNextSibling())
                if ( "DOCTYPE".equals(n1.getNodeName()) && (!((Element)n1).hasAttribute("publicId") || !((Element)n1).hasAttribute("systemId") || "".equals(((Element)n1).getAttribute("publicId")) || "".equals(((Element)n1).getAttribute("systemId"))) )
                    enregistrement.removeChild(n1);
                
            for (Node n2 = enregistrement.getFirstChild(); n2 != null; n2 = n2.getNextSibling())
                if ( "SCHEMALOCATION".equals(n2.getNodeName()) && (!((Element)n2).hasAttribute("noNamespaceSchemaLocation") || !((Element)n2).hasAttribute("schemaLocation") || "".equals(((Element)n2).getAttribute("noNamespaceSchemaLocation")) || "".equals(((Element)n2).getAttribute("schemaLocation"))) )
                    enregistrement.removeChild(n2);
                
            for (Node n3 = enregistrement.getFirstChild(); n3 != null; n3 = n3.getNextSibling())
                if ( "PREFIXE_ESPACE".equals(n3.getNodeName()) && (!((Element)n3).hasAttribute("prefixe") || !((Element)n3).hasAttribute("uri") || "".equals(((Element)n3).getAttribute("prefixe")) || "".equals(((Element)n3).getAttribute("uri"))) )
                    enregistrement.removeChild(n3);
        }
    }
    
}
