/*
Jaxe - Editeur XML en Java

Copyright (C) 2008 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 xpages;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.Position;

import jaxe.JaxeDocument;
import jaxe.JaxeElement;
import jaxe.JaxeResourceBundle;

import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;


/**
 * Plugin pour éditer des équations TeX à l'aide d'un serveur distant.
 * Les images des équations sont encodées en base64 et enregistrées dans le XML. 
 *
 * paramètre: serveur: l'URL du script tex.php qui convertit les équations en images
 * paramètre: texteAtt: le nom de l'attribut donnant le texte de l'équation
 * paramètre: labelAtt: le nom de l'attribut donnant le label de l'image
 *
 * Peut utiliser des éléments DEFCMDTEX pour définir des commandes TeX.
 * DEFCMDTEX doit avoir les attributs commande, nb-params et remplacement.
 */
public class JEEquaTeXMemoire extends JaxeElement {

    JLabel label = null;
    private String serveur = null;
    float alignementY = (float)0.70; // 70% du composant au-dessus de la base de la ligne
    private EcouteSouris ecouteur;
    
    public JEEquaTeXMemoire(JaxeDocument doc) {
        this.doc = doc;
    }

    @Override
    public void init(Position pos, Node noeud) {
        Element el = (Element)noeud;
        Element refElement = doc.cfg.getElementRef(el);
        
        serveur = doc.cfg.valeurParametreElement(refElement, "serveur", null);
        
        String contenu = null;
        final Node nTexte = el.getFirstChild();
        if (nTexte != null && nTexte instanceof Text)
            contenu = nTexte.getNodeValue();
        
        BufferedImage img;
        if (contenu == null || "".equals(contenu))
            img = null;
        else
            img = lireImage(contenu);
        
        if (img == null) {
            label = new JLabel(getString("erreur.AffichageImage"));
            label.setBorder(BorderFactory.createLineBorder(Color.darkGray));
        } else {
            ImageIcon icon;
            if (img != null) {
                icon = new ImageIcon(img);
                final int hauteur = img.getHeight(null);
                if (hauteur != -1)
                    alignementY = (float)((hauteur/2.0 + 4) / hauteur);
            } else
                icon = null;
            if (icon == null || icon.getImageLoadStatus() == MediaTracker.ABORTED ||
                icon.getImageLoadStatus() == MediaTracker.ERRORED) {
                label = new JLabel(getString("erreur.AffichageImage"));
                label.setBorder(BorderFactory.createLineBorder(Color.darkGray));
            } else
                label = new JLabel(icon);
        }
        label.setAlignmentY(alignementY);
        
        ecouteur = new EcouteSouris(this, doc.jframe);
        label.addMouseListener(ecouteur);
        final Position newpos = insertComponent(pos, label);
    }
    
    /**
     * Lecture de l'image de l'équation au format PNG encodé en base64 dans l'élément
     */
    protected BufferedImage lireImage(String contenu) {
        try {
            return(ImageIO.read(new DecodeurBase64(new StringReader(contenu))));
        } catch (IOException ex) {
            System.err.println("lireImage(String): IOException: " + ex.getMessage());
            return(null);
        }
    }
    
    @Override
    public Node nouvelElement(Element refElement) {
        serveur = doc.cfg.valeurParametreElement(refElement, "serveur", null);
        String texteAtt = doc.cfg.valeurParametreElement(refElement, "texteAtt", null);
        String labelAtt = doc.cfg.valeurParametreElement(refElement, "labelAtt", null);
        
        Element newel = nouvelElementDOM(doc, refElement);
        
        final DialogueEquaTeX dlg = new DialogueEquaTeX(doc, serveur, "", labelAtt, null);
        if (!dlg.afficher())
            return null;
        final String texte = dlg.getTexte();
        enregistrerImage(newel, DialogueEquaTeX.creerImage(doc.textPane, serveur, texte, doc));
        final String valeurLabel = dlg.getLabel();
        
        try {
            newel.setAttributeNS(doc.cfg.espaceAttribut(texteAtt), texteAtt, texte);
            if (labelAtt != null && valeurLabel != null && !"".equals(valeurLabel))
                newel.setAttributeNS(doc.cfg.espaceAttribut(labelAtt), labelAtt, valeurLabel);
        } catch (final DOMException ex) {
            System.err.println("nouvelElement(Element): DOMException: " + ex.getMessage());
            return null;
        }
        
        return(newel);
    }
    
    public void afficherDialogue(JFrame jframe) {
        Element el = (Element)noeud;

        final Element refElement = doc.cfg.getElementRef(el);
        final String texteAtt = doc.cfg.valeurParametreElement(refElement, "texteAtt", null);
        final String labelAtt = doc.cfg.valeurParametreElement(refElement, "labelAtt", null);
        String texteEquation = el.getAttribute(texteAtt);
        String valeurLabel1;
        if (labelAtt != null)
            valeurLabel1 = el.getAttribute(labelAtt);
        else
            valeurLabel1 = null;
        final DialogueEquaTeX dlg = new DialogueEquaTeX(doc, serveur, texteEquation, labelAtt, valeurLabel1);
        if (!dlg.afficher())
            return;
        texteEquation = dlg.getTexte();
        enregistrerImage(el, DialogueEquaTeX.creerImage(doc.textPane, serveur, texteEquation, doc));
        final String valeurLabel2 = dlg.getLabel();
        
        try {
            el.setAttributeNS(doc.cfg.espaceAttribut(texteAtt), texteAtt, texteEquation);
            if (labelAtt != null) {
                if (valeurLabel1 != null && "".equals(valeurLabel2))
                    el.removeAttribute(labelAtt);
                else
                    el.setAttributeNS(doc.cfg.espaceAttribut(labelAtt), labelAtt, valeurLabel2);
            }
        } catch (final DOMException ex) {
            System.err.println("afficherDialogue(JFrame): DOMException: " + ex.getMessage());
            return;
        }
        doc.modif = true;
        
        majAffichage();
    }
    
    @Override
    public void majAffichage() {
        String contenu = null;
        final Element el = (Element)noeud;
        final Node nTexte = el.getFirstChild();
        if (nTexte != null && nTexte instanceof Text)
            contenu = nTexte.getNodeValue();
        if (contenu != null && !"".equals(contenu)) {
            Image img = lireImage(contenu);
            boolean erreur = false;
            if (img == null)
                erreur = true;
            if (!erreur) {
                final ImageIcon icon = new ImageIcon(img);
                label.setIcon(icon);
                label.setText(null);
                label.setBorder(null);
                final int hauteur = img.getHeight(null);
                if (hauteur != -1) {
                    alignementY = (float)((hauteur/2.0 + 4) / hauteur);
                    label.setAlignmentY(alignementY);
                }
            } else {
                label.setIcon(null);
                label.setText(getString("erreur.AffichageImage"));
                label.setBorder(BorderFactory.createLineBorder(Color.darkGray));
            }
        } else {
            label.setText(getString("erreur.FichierNonTrouve"));
            label.setIcon(null);
            label.setBorder(BorderFactory.createLineBorder(Color.darkGray));
        }
        doc.imageChanged(label);
    }

    /**
     * Enregistrement de l'image de l'équation au format PNG encodé en base64 dans l'élément
     */
    protected void enregistrerImage(final Element el, final BufferedImage img) {
        try {
            StringWriter sw = new StringWriter();
            EncodeurBase64 encodeur = new EncodeurBase64(sw);
            DialogueEquaTeX.enregistrerImage(img, encodeur);
            encodeur.close();
            Node nTexte = el.getFirstChild();
            if (nTexte == null) {
                nTexte = doc.DOMdoc.createTextNode(sw.toString());
                el.appendChild(nTexte);
            } else
                nTexte.setNodeValue(sw.toString());
        } catch (final IOException ex) {
            System.err.println("enregistrerImage(Element, BufferedImage): IOException: " + ex.getMessage());
            JOptionPane.showMessageDialog(doc.jframe, JaxeResourceBundle.getRB().getString("erreur.Enregistrement") + ": " +
                ex.getMessage(), JaxeResourceBundle.getRB().getString("erreur.Erreur"), JOptionPane.ERROR_MESSAGE);
        }
    }
    
    @Override
    public void selection(final boolean select) {
        super.selection(select);
        label.setEnabled(!select);
    }
    
    @Override
    public void effacer() {
        super.effacer();
        if (ecouteur != null) {
            label.removeMouseListener(ecouteur);
            ecouteur = null;
        }
    }

    class EcouteSouris extends MouseAdapter {
        JEEquaTeXMemoire jei;
        JFrame jframe;
        public EcouteSouris(final JEEquaTeXMemoire obj, final JFrame jframe) {
            super();
            jei = obj;
            this.jframe = jframe;
        }
        @Override
        public void mouseClicked(final MouseEvent e) {
            jei.afficherDialogue(jframe);
        }
    }
    
}
