/*
Copyright 2012-2014 Samuel Gesche

This file is part of the Greek Reuse Toolkit.

The Greek Reuse Toolkit is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

The Greek Reuse Toolkit is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with the Greek Reuse Toolkit.  If not, see <http://www.gnu.org/licenses/>.
*/

package fr.cnrs.liris.drim.grt.ihm;

import fr.cnrs.liris.drim.grt.ihm.exceptions.InteractionRefuseeException;
import fr.cnrs.liris.drim.grt.modele.Citation;
import fr.cnrs.liris.drim.grt.modele.OrdreStrict;
import fr.cnrs.liris.drim.grt.modele.Passage;
import fr.cnrs.liris.drim.grt.modele.Reference;
import fr.cnrs.liris.drim.grt.modele.exceptions.ListeStatistiqueNonInitialiseeException;
import fr.cnrs.liris.drim.grt.modele.listes.Lemmatiseurs;
import fr.cnrs.liris.drim.grt.proc.exceptions.DOMCreationFailureException;
import fr.cnrs.liris.drim.grt.proc.parsers.ImportFichier;
import fr.cnrs.liris.drim.grt.proc.parsers.PassageType;
import fr.cnrs.liris.drim.grt.proc.parsers.References;
import fr.cnrs.liris.drim.grt.proc.parsers.Temps;
import fr.cnrs.liris.drim.grt.proc.recherche.Recherche;
import fr.cnrs.liris.drim.grt.proc.recherche.RechercheNLexes;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.Timer;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLEditorKit;

/**
 *
 * @author Sam
 */
public class FenetreRecherche extends javax.swing.JFrame {
    private PassageType citant;
    private PassageType cite;
    private RechercheNLexes recherche;
    private final Timer timerRecherche;
    private long debut = System.currentTimeMillis();
    
    private final static String CSS = "body {"
                + "font-family:\""+new Font("Calibri", Font.PLAIN, 16).getFamily()+"\", serif, monospace;}" +
                "p.number{"
                + "font-size:1.6em;"
                + "font-weight:bold;}" +
                "p.title{"
                + "font-size:1.2em;"
                + "font-weight:bold;}" +
                "span.title{"
                + "text-decoration:underline;}" +
                "span.ref{"
                + "font-style:italic;}" + 
                "span.cit{"
                + "font-weight:bold;}" +
                "span.lemmemanquant{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "color:#000000;}" +
                "span.hlv{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "color:#808080;}" +
                "span.hlu{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "color:#008000;}" +
                "span.hlr{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "color:#000080;}" +
                "span.hln{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "color:#000000;}" +  
                "span.hnv{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "text-decoration:underline;"
                + "color:#808080;}" +
                "span.hnu{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "text-decoration:underline;"
                + "color:#008000;}" +
                "span.hnr{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "text-decoration:underline;"
                + "color:#000080;}" +
                "span.hnn{"
                + "font-weight:normal;"
                + "font-size:0.9em;"
                + "text-decoration:underline;"
                + "color:#000000;}" +  
                "span.clv{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "color:#808080;}" +
                "span.clu{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "color:#008000;}" +
                "span.clr{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "color:#000080;}" +
                "span.cln{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "color:#000000;}" +  
                "span.cnv{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "text-decoration:underline;"
                + "color:#808080;}" +
                "span.cnu{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "text-decoration:underline;"
                + "color:#008000;}" +
                "span.cnr{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "text-decoration:underline;"
                + "color:#000080;}" +
                "span.cnn{"
                + "font-weight:bold;"
                + "font-size:1.2em;"
                + "text-decoration:underline;"
                + "color:#000000;}";
    
    /**
     * Creates new form FenetreRecherche
     */
    public FenetreRecherche() {
        initComponents();
        HTMLEditorKit html = new HTMLEditorKit();
        html.getStyleSheet().addRule(CSS);
        tResultats.setContentType("text/html");
        tResultats.setEditorKit(html);
        
        
        timerRecherche = new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                lStatutRecherche.setText("[" + Temps.getTexte(System.currentTimeMillis()-debut) + "] " + 
                        recherche.getStatut() + " (" +
                        ((int)(recherche.getAvancement()*10000))/100.0 + "%).");
            }
        });
        
        pCite.setVisible(false);
        pParametres.setVisible(false);
        pack();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        groupeTraitementLangue = new javax.swing.ButtonGroup();
        groupeTolerance = new javax.swing.ButtonGroup();
        tpPrincipal = new javax.swing.JTabbedPane();
        pParams = new javax.swing.JPanel();
        pCitant = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        lTexteCitant = new javax.swing.JLabel();
        tTexteCitant = new javax.swing.JTextField();
        bChoixTexteCitant = new javax.swing.JButton();
        jPanel6 = new javax.swing.JPanel();
        lStatutCitant = new javax.swing.JLabel();
        pCite = new javax.swing.JPanel();
        jPanel7 = new javax.swing.JPanel();
        lTexteCite = new javax.swing.JLabel();
        tTexteCite = new javax.swing.JTextField();
        bChoixTexteCite = new javax.swing.JButton();
        jPanel8 = new javax.swing.JPanel();
        lStatutCite = new javax.swing.JLabel();
        pParametres = new javax.swing.JPanel();
        pTitre = new javax.swing.JPanel();
        jLabel10 = new javax.swing.JLabel();
        pTolerance = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        tTailleInitiale = new javax.swing.JFormattedTextField();
        jLabel5 = new javax.swing.JLabel();
        jPanel11 = new javax.swing.JPanel();
        jLabel11 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        rbStricte = new javax.swing.JRadioButton();
        jPanel3 = new javax.swing.JPanel();
        rbAbsolue = new javax.swing.JRadioButton();
        tSeuilAbsolu = new javax.swing.JFormattedTextField();
        jLabel3 = new javax.swing.JLabel();
        jPanel4 = new javax.swing.JPanel();
        rbRelative = new javax.swing.JRadioButton();
        tSeuilRelatif = new javax.swing.JFormattedTextField();
        jLabel4 = new javax.swing.JLabel();
        pTraitement = new javax.swing.JPanel();
        pSansMotsVides = new javax.swing.JPanel();
        cbSansMotsVides = new javax.swing.JCheckBox();
        pImportanceOrdre = new javax.swing.JPanel();
        cbImportanceOrdre = new javax.swing.JCheckBox();
        pTraitementLangue = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        rbBrut = new javax.swing.JRadioButton();
        rbNorm = new javax.swing.JRadioButton();
        rbLemm = new javax.swing.JRadioButton();
        pFinition = new javax.swing.JPanel();
        pFiltrerNonCitations = new javax.swing.JPanel();
        cbFiltrerNonCitations = new javax.swing.JCheckBox();
        pFusion = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        tSeuilFusion = new javax.swing.JFormattedTextField();
        jLabel7 = new javax.swing.JLabel();
        pTailleMax = new javax.swing.JPanel();
        jLabel8 = new javax.swing.JLabel();
        tTailleMax = new javax.swing.JFormattedTextField();
        jLabel9 = new javax.swing.JLabel();
        jPanel15 = new javax.swing.JPanel();
        jLabel12 = new javax.swing.JLabel();
        tTailleContexte = new javax.swing.JFormattedTextField();
        jLabel13 = new javax.swing.JLabel();
        pLancer = new javax.swing.JPanel();
        jPanel9 = new javax.swing.JPanel();
        bLancer = new javax.swing.JButton();
        jPanel10 = new javax.swing.JPanel();
        lStatutRecherche = new javax.swing.JLabel();
        pResultats = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        tResultats = new javax.swing.JEditorPane();
        jPanel12 = new javax.swing.JPanel();
        jPanel13 = new javax.swing.JPanel();
        bExportHTML = new javax.swing.JButton();
        jPanel14 = new javax.swing.JPanel();
        lStatutExport = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Greek Reuse Toolkit - Recherche de citations");

        pParams.setLayout(new javax.swing.BoxLayout(pParams, javax.swing.BoxLayout.PAGE_AXIS));

        pCitant.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pCitant.setLayout(new java.awt.GridLayout(2, 1));

        lTexteCitant.setText("Texte citant : ");
        jPanel5.add(lTexteCitant);

        tTexteCitant.setEditable(false);
        tTexteCitant.setColumns(50);
        jPanel5.add(tTexteCitant);

        bChoixTexteCitant.setText("...");
        bChoixTexteCitant.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bChoixTexteCitantActionPerformed(evt);
            }
        });
        jPanel5.add(bChoixTexteCitant);

        pCitant.add(jPanel5);

        jPanel6.add(lStatutCitant);

        pCitant.add(jPanel6);

        pParams.add(pCitant);

        pCite.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pCite.setLayout(new java.awt.GridLayout(2, 1));

        lTexteCite.setText("Texte cité : ");
        jPanel7.add(lTexteCite);

        tTexteCite.setEditable(false);
        tTexteCite.setColumns(50);
        jPanel7.add(tTexteCite);

        bChoixTexteCite.setText("...");
        bChoixTexteCite.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bChoixTexteCiteActionPerformed(evt);
            }
        });
        jPanel7.add(bChoixTexteCite);

        pCite.add(jPanel7);

        jPanel8.add(lStatutCite);

        pCite.add(jPanel8);

        pParams.add(pCite);

        pParametres.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pParametres.setLayout(new javax.swing.BoxLayout(pParametres, javax.swing.BoxLayout.PAGE_AXIS));

        jLabel10.setText("Veuillez maintenant définir les paramètres de la recherche de citations :");
        pTitre.add(jLabel10);

        pParametres.add(pTitre);

        pTolerance.setBorder(javax.swing.BorderFactory.createTitledBorder("Tolérance"));
        pTolerance.setLayout(new java.awt.GridLayout(5, 1));

        jLabel2.setText("Ne pas considérer les passages similaires ayant moins de");
        jPanel1.add(jLabel2);

        tTailleInitiale.setColumns(3);
        tTailleInitiale.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        tTailleInitiale.setText("3");
        jPanel1.add(tTailleInitiale);

        jLabel5.setText("termes identiques");
        jPanel1.add(jLabel5);

        pTolerance.add(jPanel1);

        jLabel11.setText("Chercher les bornes des citations en : ");
        jPanel11.add(jLabel11);

        pTolerance.add(jPanel11);

        groupeTolerance.add(rbStricte);
        rbStricte.setSelected(true);
        rbStricte.setText("Conservant des passages strictement identiques");
        rbStricte.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rbStricteActionPerformed(evt);
            }
        });
        jPanel2.add(rbStricte);

        pTolerance.add(jPanel2);

        groupeTolerance.add(rbAbsolue);
        rbAbsolue.setText("Acceptant jusqu'à");
        jPanel3.add(rbAbsolue);

        tSeuilAbsolu.setColumns(3);
        tSeuilAbsolu.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        tSeuilAbsolu.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        tSeuilAbsolu.setText("3");
        jPanel3.add(tSeuilAbsolu);

        jLabel3.setText("termes différents entre citant et cité");
        jPanel3.add(jLabel3);

        pTolerance.add(jPanel3);

        groupeTolerance.add(rbRelative);
        rbRelative.setText("Acceptant jusqu'à");
        jPanel4.add(rbRelative);

        tSeuilRelatif.setColumns(3);
        tSeuilRelatif.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        tSeuilRelatif.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        tSeuilRelatif.setText("60");
        jPanel4.add(tSeuilRelatif);

        jLabel4.setText("% de termes différents entre citant et cité");
        jPanel4.add(jLabel4);

        pTolerance.add(jPanel4);

        pParametres.add(pTolerance);

        pTraitement.setBorder(javax.swing.BorderFactory.createTitledBorder("Traitement du texte"));
        pTraitement.setLayout(new java.awt.GridLayout(3, 1));

        cbSansMotsVides.setSelected(true);
        cbSansMotsVides.setText("Supprimer les mots vides avant l'analyse (recommandé)");
        pSansMotsVides.add(cbSansMotsVides);

        pTraitement.add(pSansMotsVides);

        cbImportanceOrdre.setSelected(true);
        cbImportanceOrdre.setText("L'ordre des mots est important dans le texte");
        pImportanceOrdre.add(cbImportanceOrdre);

        pTraitement.add(pImportanceOrdre);

        jLabel1.setText("Utiliser");
        pTraitementLangue.add(jLabel1);

        groupeTraitementLangue.add(rbBrut);
        rbBrut.setText("le texte brut");
        pTraitementLangue.add(rbBrut);

        groupeTraitementLangue.add(rbNorm);
        rbNorm.setText("le texte normalisé");
        pTraitementLangue.add(rbNorm);

        groupeTraitementLangue.add(rbLemm);
        rbLemm.setSelected(true);
        rbLemm.setText("le texte lemmatisé");
        pTraitementLangue.add(rbLemm);

        pTraitement.add(pTraitementLangue);

        pParametres.add(pTraitement);

        pFinition.setBorder(javax.swing.BorderFactory.createTitledBorder("Finitions"));
        pFinition.setLayout(new java.awt.GridLayout(4, 1));

        cbFiltrerNonCitations.setSelected(true);
        cbFiltrerNonCitations.setText("Abandonner les citations qui n'ont en commun que des termes courants dans la langue ou le corpus (recommandé)");
        pFiltrerNonCitations.add(cbFiltrerNonCitations);

        pFinition.add(pFiltrerNonCitations);

        jLabel6.setText("Fusionner les citations successives quand les passages cités et citants sont jusqu'à");
        pFusion.add(jLabel6);

        tSeuilFusion.setColumns(3);
        tSeuilFusion.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        tSeuilFusion.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        tSeuilFusion.setText("5");
        pFusion.add(tSeuilFusion);

        jLabel7.setText("mots de distance");
        pFusion.add(jLabel7);

        pFinition.add(pFusion);

        jLabel8.setText("Abandonner les citations longues de plus de ");
        pTailleMax.add(jLabel8);

        tTailleMax.setColumns(4);
        tTailleMax.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        tTailleMax.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        tTailleMax.setText("100");
        pTailleMax.add(tTailleMax);

        jLabel9.setText("mots");
        pTailleMax.add(jLabel9);

        pFinition.add(pTailleMax);

        jLabel12.setText("Afficher jusqu'à ");
        jPanel15.add(jLabel12);

        tTailleContexte.setColumns(3);
        tTailleContexte.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        tTailleContexte.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        tTailleContexte.setText("20");
        jPanel15.add(tTailleContexte);

        jLabel13.setText("mots de contexte avant et après les passages");
        jPanel15.add(jLabel13);

        pFinition.add(jPanel15);

        pParametres.add(pFinition);

        pLancer.setLayout(new java.awt.GridLayout(2, 1));

        bLancer.setText("Lancer la recherche de citations");
        bLancer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bLancerActionPerformed(evt);
            }
        });
        jPanel9.add(bLancer);

        pLancer.add(jPanel9);

        jPanel10.add(lStatutRecherche);

        pLancer.add(jPanel10);

        pParametres.add(pLancer);

        pParams.add(pParametres);

        tpPrincipal.addTab("Recherche", pParams);

        pResultats.setLayout(new java.awt.BorderLayout());

        tResultats.setEditable(false);
        tResultats.setContentType("text/html"); // NOI18N
        jScrollPane1.setViewportView(tResultats);

        pResultats.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jPanel12.setLayout(new java.awt.GridLayout(2, 1));

        bExportHTML.setText("Exporter en HTML...");
        bExportHTML.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bExportHTMLActionPerformed(evt);
            }
        });
        jPanel13.add(bExportHTML);

        jPanel12.add(jPanel13);

        jPanel14.add(lStatutExport);

        jPanel12.add(jPanel14);

        pResultats.add(jPanel12, java.awt.BorderLayout.PAGE_END);

        tpPrincipal.addTab("Résultats", pResultats);

        getContentPane().add(tpPrincipal, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void bChoixTexteCitantActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bChoixTexteCitantActionPerformed
        try {
            final File fCitant = Demandes.demandeFichier("Veillez choisir le texte citant", 
                    new String[]{"rtf", "txt", "xml"}, 
                    new String[]{"Fichier patristique RTF (.rtf)", "Fichier d'export biblique Bibleworks (.txt)", "Fichier biblique ou patristique xml (.xml)"});
            new Thread() {
                @Override
                public void run() {
                    bLancer.setEnabled(false);
                    bChoixTexteCitant.setEnabled(false);
                    bChoixTexteCite.setEnabled(false);
                    lStatutCitant.setText("Chargement en cours");
                    try {
                        if(fCitant.getName().endsWith("rtf")) {
                            citant = new PassageType(ImportFichier.importPatristiqueRTF(fCitant), PassageType.PASSAGE_PATRISTIQUE);
                        } else if(fCitant.getName().endsWith("txt")) {
                            citant = new PassageType(ImportFichier.importBibleTexteOuMorphoTXT(fCitant), PassageType.PASSAGE_BIBLIQUE);
                        } else {
                            Passage p = ImportFichier.importUnicodeXML(fCitant);
                            if(p.getSousCoordonneeMinimale().getSysteme().equals(OrdreStrict.getInstance(OrdreStrict.LIVRES_BIB)) || 
                               p.getSousCoordonneeMinimale().getSysteme().equals(OrdreStrict.getInstance(OrdreStrict.LIVRES_LXX)) || 
                               p.getSousCoordonneeMinimale().getSysteme().equals(OrdreStrict.getInstance(OrdreStrict.LIVRES_NTG))) {
                                citant = new PassageType(p, PassageType.PASSAGE_BIBLIQUE);
                            } else if(p.getSousCoordonneeMinimale().getSysteme().equals(OrdreStrict.getInstance(OrdreStrict.LIVRES_PHI))) {
                                citant = new PassageType(p, PassageType.PASSAGE_PHILON);
                            } else {
                                citant = new PassageType(p, PassageType.PASSAGE_PATRISTIQUE);
                            }
                        }
                        tTexteCitant.setText(fCitant.getAbsolutePath());
                        lStatutCitant.setText("Fichier chargé");
                        pCite.setVisible(true);
                        pack();
                    } catch(IOException | BadLocationException | DOMCreationFailureException ex) {
                        lStatutCitant.setText("Erreur : " + ex.getClass() + " - " + ex.getMessage());
                    }
                    bLancer.setEnabled(true);
                    bChoixTexteCitant.setEnabled(true);
                    bChoixTexteCite.setEnabled(true);
                }
            }.start();
        } catch (InteractionRefuseeException ex) {
            
        }
    }//GEN-LAST:event_bChoixTexteCitantActionPerformed

    private void bChoixTexteCiteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bChoixTexteCiteActionPerformed
        try {
            final File fCite = Demandes.demandeFichier("Veillez choisir le texte cité", 
                    new String[]{"txt", "xml"}, 
                    new String[]{"Fichier d'export biblique Bibleworks (.txt)", "Fichier biblique ou patristique xml (.xml)"});
             new Thread() {
                @Override
                public void run() {
                    bLancer.setEnabled(false);
                    bChoixTexteCitant.setEnabled(false);
                    bChoixTexteCite.setEnabled(false);
                    lStatutCite.setText("Chargement en cours");
                    try {
                        if(fCite.getName().endsWith("txt")) {
                            cite = new PassageType(ImportFichier.importBibleTexteOuMorphoTXT(fCite), PassageType.PASSAGE_BIBLIQUE);
                        } else {
                            cite = new PassageType(ImportFichier.importUnicodeXML(fCite), PassageType.PASSAGE_BIBLIQUE);
                        }
                        tTexteCite.setText(fCite.getAbsolutePath());
                        lStatutCite.setText("Fichier chargé");
                        pParametres.setVisible(true);
                        pack();
                    } catch(IOException | DOMCreationFailureException ex) {
                        lStatutCite.setText("Erreur : " + ex.getClass() + " - " + ex.getMessage());
                    }
                    bLancer.setEnabled(true);
                    bChoixTexteCitant.setEnabled(true);
                    bChoixTexteCite.setEnabled(true);
                }
            }.start();
        } catch (InteractionRefuseeException ex) {
            
        }
    }//GEN-LAST:event_bChoixTexteCiteActionPerformed

    
    private void bLancerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bLancerActionPerformed
        // TODO add your handling code here:
        tResultats.setText("");
        bLancer.setEnabled(false);
        bChoixTexteCitant.setEnabled(false);
        bChoixTexteCite.setEnabled(false);
        new Thread() {
            @Override
            public void run() {
                recherche = new RechercheNLexes(cite, citant, OrdreStrict.getInstance(OrdreStrict.MOTS), OrdreStrict.getInstance(OrdreStrict.MOTS));
                recherche.setImportanceOrdreMots(
                        cbImportanceOrdre.isSelected()?
                        Recherche.L_ORDRE_DES_MOTS_COMPTE:
                        Recherche.L_ORDRE_DES_MOTS_NE_COMPTE_PAS);
                recherche.setFiltrageMotsVides(
                        cbSansMotsVides.isSelected()?
                        Recherche.TEXTE_SANS_MOTS_VIDES:
                        Recherche.TEXTE_AVEC_MOTS_VIDES);
                recherche.setFiltrageExpressionsVides(
                        cbFiltrerNonCitations.isSelected()?
                        Recherche.FILTRAGE_SANS_LEMMES_NI_EXPRESSIONS_VIDES:
                        Recherche.FILTRAGE_AVEC_LEMMES_ET_EXPRESSIONS_VIDES);
                recherche.setTraitementTermes(
                        rbBrut.isSelected()?
                        Recherche.TERMES_BRUTS:
                        (rbNorm.isSelected()?
                        Recherche.TERMES_NORMALISES:
                        Recherche.TERMES_LEMMATISES));
                recherche.setToleranceCorrespondance(
                        rbStricte.isSelected()?
                        Recherche.CORRESPONDANCE_STRICTE:
                        (rbAbsolue.isSelected()?
                        Recherche.CORRESPONDANCE_SEUILLEE_EN_VALEUR:
                        Recherche.CORRESPONDANCE_SEUILLEE_EN_POURCENTAGE)
                        , 
                        rbStricte.isSelected()?
                        0:
                        (rbAbsolue.isSelected()?
                        Integer.parseInt(tSeuilAbsolu.getText()):
                        Integer.parseInt(tSeuilRelatif.getText())));
                recherche.setSeuilFusion(Integer.parseInt(tSeuilFusion.getText()));
                recherche.setNbMotsMaxParCitation(Integer.parseInt(tTailleMax.getText()));
                recherche.setTailleFenetre(Integer.parseInt(tTailleInitiale.getText()));
                debut = System.currentTimeMillis();
                lStatutRecherche.setText("Recherche de citations en cours (0%)");
                timerRecherche.start();
                try {
                    Citation[] resultats = recherche.chercheCitations();
                    timerRecherche.stop();
                    System.gc();
                    System.out.println(recherche.getLogExecution());
                    lStatutRecherche.setText("Production des résultats");
                    StringBuilder s = new StringBuilder();
                    s.append("<html><head></head><body><p class=\"title\">").
                            append(resultats.length).
                            append(" citations de ").
                            append(cite.getPassage().getTitre()).
                            append(" dans ").
                            append(citant.getPassage().getTitre()).
                            append(" ont été trouvées.</p>");
                    s.append("<p><span class=\"title\">Légende</span></p>").
                            append("<ul>").
                            append("<li><span class=\"hln\">terme significatif</span></li>").
                            append("<li><span class=\"hlr\">terme récurrent dans le corpus</span></li>").
                            append("<li><span class=\"hlu\">terme usuel</span></li>").
                            append("<li><span class=\"hlv\">terme vide</span></li>").
                            append("</ul><ul>").
                            append("<li><span class=\"hln\">terme lemmatisé</span></li>").
                            append("<li><span class=\"hnn\">terme sans lemme</span></li>").
                            append("</ul><ul>").
                            append("<li><span class=\"cln\">la citation elle-même</span></li>").
                            append("<li><span class=\"hln\">contexte de la citation</span></li>").
                            append("</ul><hr/>");
                    for(int i=0; i<resultats.length; i++) {
                        lStatutRecherche.setText("Production des résultats (citation " + (i+1) + "/" + resultats.length + ")");
                        // System.err.println("Citation " + (i+1));
                        // System.err.println(" Cité");
                        Citation resultat = resultats[i];
                        // System.err.println("  Base : " + resultat.getCite().getAllMots().length + " mots");
                        for(int a=0; a<resultat.getCite().getAllMots().length-1; a++) {
                            int dist = cite.getPassage().getDistance(resultat.getCite().getAllMots()[a], resultat.getCite().getAllMots()[a+1]);
                            if(dist<=0) {
                                // System.err.println("   /!\\ distance négative ou nulle (" + dist + " entre " + 
                                //         resultat.getCite().getAllMots()[a].getTexteCompletAvecRefs() + " et " + 
                                //         resultat.getCite().getAllMots()[a+1].getTexteCompletAvecRefs());
                            }
                        }
                        Reference refCite0 = resultat.getCite().getAllMots()[0].getReferenceInitialeDans(cite.getPassage());
                        Reference refCite1 = resultat.getCite().getAllMots()[resultat.getCite().getAllMots().length-1].getReferenceInitialeDans(cite.getPassage());
                        // System.err.println("   Rassemblement");
                        // System.err.println("    Ref0 : " + refCite0.toString());
                        // System.err.println("    Ref1 : " + refCite1.toString());
                        Passage[] motsCite0 = cite.getPassage().rassemblePassage(
                                References.parseReference(
                                References.toReference(refCite0, refCite1, cite.getType()), 
                                cite.getType())).getAllMots();
                        // System.err.println("   Rassemblement terminé");
                        int index0 = 0, index1 = motsCite0.length-1;
                        // System.err.println("   Découpage");
                        for(int a=0; a<motsCite0.length; a++) {
                            if(Arrays.asList(resultat.getCite().getAllMots()).contains(motsCite0[a])) {
                                index0 = a;
                                break;
                            }
                        }
                        // System.err.println("   Découpage 50%");
                        for(int a=motsCite0.length-1; a>=0; a--) {
                            if(Arrays.asList(resultat.getCite().getAllMots()).contains(motsCite0[a])) {
                                index1 = a;
                                break;
                            }
                        }
                        // System.err.println("   Découpage terminé");
                        ArrayList<Passage> motsCite1 = new ArrayList<>();
                        for(int a=index0; a<=index1; a++) {
                            motsCite1.add(motsCite0[a]);
                        }
                        Passage[] motsCite = new Passage[motsCite1.size()];
                        motsCite1.toArray(motsCite);
                        // System.err.println("  Rassemblé : " + motsCite.length + " mots");
                        ArrayList<Passage> motsAvantCite = new ArrayList<>();
                        Passage courant = motsCite[0];
                        for(int a=0; a<Integer.parseInt(tTailleContexte.getText()); a++) {
                            courant = cite.getPassage().getMotPrecedent(courant);
                            if(courant == null) {
                                break;
                            }
                            motsAvantCite.add(0, courant);
                        }
                        ArrayList<Passage> motsApresCite = new ArrayList<>();
                        courant = motsCite[motsCite.length-1];
                        for(int a=0; a<Integer.parseInt(tTailleContexte.getText()); a++) {
                            courant = cite.getPassage().getMotSuivant(courant);
                            if(courant == null) {
                                break;
                            }
                            motsApresCite.add(courant);
                        }
                        // System.err.println("  Extension faite");
                        
                        String scite = "";
                        for(Passage mot: motsAvantCite) {
                            String classe = "h";
                            String smot = mot.getContenu().getExpression();
                            String slemme = Lemmatiseurs.getFormeLemmatisee(smot);
                            if(Lemmatiseurs.aLemmePour(smot)) {
                                classe += "l";
                            } else {
                                classe += "n";
                                slemme = "";
                            }
                            if(fr.cnrs.liris.drim.grt.modele.listes.LemmesVides.contientTerme(mot.getContenu())) {
                                classe += "v";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesUsuels.contientTerme(mot.getContenu())) {
                                classe += "u";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesRecurrents.contientTerme(mot.getContenu())) {
                                classe += "r";
                            } else {
                                classe += "n";
                            }
                            scite += "<span title=\"" + slemme + "\" class=\"" + classe + "\">" + smot + "</span> ";
                        }
                        for(Passage mot: motsCite) {
                            String classe = "c";
                            String smot = mot.getContenu().getExpression();
                            String slemme = Lemmatiseurs.getFormeLemmatisee(smot);
                            if(Lemmatiseurs.aLemmePour(smot)) {
                                classe += "l";
                            } else {
                                classe += "n";
                                slemme = "";
                            }
                            if(fr.cnrs.liris.drim.grt.modele.listes.LemmesVides.contientTerme(mot.getContenu())) {
                                classe += "v";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesUsuels.contientTerme(mot.getContenu())) {
                                classe += "u";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesRecurrents.contientTerme(mot.getContenu())) {
                                classe += "r";
                            } else {
                                classe += "n";
                            }
                            scite += "<span title=\"" + slemme + "\" class=\"" + classe + "\">" + smot + "</span> ";
                        }
                        for(Passage mot: motsApresCite) {
                            String classe = "h";
                            String smot = mot.getContenu().getExpression();
                            String slemme = Lemmatiseurs.getFormeLemmatisee(smot);
                            if(Lemmatiseurs.aLemmePour(smot)) {
                                classe += "l";
                            } else {
                                classe += "n";
                                slemme = "";
                            }
                            if(fr.cnrs.liris.drim.grt.modele.listes.LemmesVides.contientTerme(mot.getContenu())) {
                                classe += "v";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesUsuels.contientTerme(mot.getContenu())) {
                                classe += "u";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesRecurrents.contientTerme(mot.getContenu())) {
                                classe += "r";
                            } else {
                                classe += "n";
                            }
                            scite += "<span title=\"" + slemme + "\" class=\"" + classe + "\">" + smot + "</span> ";
                        }
                        scite = scite.trim();
                        String sRefCite = References.minimiseRefsFR(resultat.getCite().getNumerosCompletsSousPassages(), cite.getType());
                        // System.err.println("  HTML généré");
                        
                        
                        // System.err.println(" Citant");
                        // System.err.println("  Base : " + resultat.getCiteur().getAllMots().length + " mots");
                        Reference refCitant0 = resultat.getCiteur().getAllMots()[0].getReferenceInitialeDans(citant.getPassage());
                        Reference refCitant1 = resultat.getCiteur().getAllMots()[resultat.getCiteur().getAllMots().length-1].getReferenceInitialeDans(citant.getPassage());
                        Passage[] motsCitant = citant.getPassage().rassemblePassage(
                                References.parseReference(
                                References.toReference(refCitant0, refCitant1, citant.getType()), 
                                citant.getType())).getAllMots();
                        ArrayList<Passage> motsAvantCitant = new ArrayList<>();
                        courant = motsCitant[0];
                        for(int a=0; a<Integer.parseInt(tTailleContexte.getText()); a++) {
                            courant = citant.getPassage().getMotPrecedent(courant);
                            if(courant == null) {
                                break;
                            }
                            motsAvantCitant.add(0, courant);
                        }
                        ArrayList<Passage> motsApresCitant = new ArrayList<>();
                        courant = motsCitant[motsCitant.length-1];
                        for(int a=0; a<Integer.parseInt(tTailleContexte.getText()); a++) {
                            courant = citant.getPassage().getMotSuivant(courant);
                            if(courant == null) {
                                break;
                            }
                            motsApresCitant.add(courant);
                        }
                        String scitant = "";
                        // System.err.println("  Extension faite");
                        for(Passage mot: motsAvantCitant) {
                            String classe = "h";
                            String smot = mot.getContenu().getExpression();
                            if(Lemmatiseurs.aLemmePour(smot)) {
                                classe += "l";
                            } else {
                                classe += "n";
                            }
                            if(fr.cnrs.liris.drim.grt.modele.listes.LemmesVides.contientTerme(mot.getContenu())) {
                                classe += "v";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesUsuels.contientTerme(mot.getContenu())) {
                                classe += "u";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesRecurrents.contientTerme(mot.getContenu())) {
                                classe += "r";
                            } else {
                                classe += "n";
                            }
                            scitant += "<span class=\"" + classe + "\">" + smot + "</span> ";
                        }
                        for(Passage mot: motsCitant) {
                            String classe = "c";
                            String smot = mot.getContenu().getExpression();
                            if(Lemmatiseurs.aLemmePour(smot)) {
                                classe += "l";
                            } else {
                                classe += "n";
                            }
                            if(fr.cnrs.liris.drim.grt.modele.listes.LemmesVides.contientTerme(mot.getContenu())) {
                                classe += "v";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesUsuels.contientTerme(mot.getContenu())) {
                                classe += "u";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesRecurrents.contientTerme(mot.getContenu())) {
                                classe += "r";
                            } else {
                                classe += "n";
                            }
                            scitant += "<span class=\"" + classe + "\">" + smot + "</span> ";
                        }
                        for(Passage mot: motsApresCitant) {
                            String classe = "h";
                            String smot = mot.getContenu().getExpression();
                            if(Lemmatiseurs.aLemmePour(smot)) {
                                classe += "l";
                            } else {
                                classe += "n";
                            }
                            if(fr.cnrs.liris.drim.grt.modele.listes.LemmesVides.contientTerme(mot.getContenu())) {
                                classe += "v";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesUsuels.contientTerme(mot.getContenu())) {
                                classe += "u";
                            } else if(fr.cnrs.liris.drim.grt.modele.listes.LemmesRecurrents.contientTerme(mot.getContenu())) {
                                classe += "r";
                            } else {
                                classe += "n";
                            }
                            scitant += "<span class=\"" + classe + "\">" + smot + "</span> ";
                        }
                        scitant = scitant.trim();
                        String sRefCitant = References.minimiseRefsFR(resultat.getCiteur().getNumerosCompletsSousPassages(), citant.getType());
                        // System.err.println("  HTML généré");
                        
                        s.append("<p class=\"number\">Citation ").
                                append(i+1).
                                append(" :</p>").
                                append("<p><span class=\"title\">Passage citant</span> : ").
                                append("<span class=\"passage\">").
                                append(sRefCitant).
                                append("</span></p><p class=\"citation\">").
                                append(scitant).
                                append("</p>" + "<p><span class=\"title\">Passage cité</span> : ").
                                append("<span class=\"passage\">").
                                append(sRefCite).
                                append("</span></p><p class=\"citation\">").
                                append(scite).
                                append("</p><hr/>");
                    }
                    
                    s.append("<p class=\"number\">Lemmes manquants : </p><ul>");
                    for(String forme: Lemmatiseurs.listeFormesDemandeesSansLemme()) {
                        s.append("<li><span class=\"lemmemanquant\">").
                                append(forme).
                                append("</span></li>");
                    }
                    s.append("</ul>");
                    s.append("</body></html>");
                    lStatutRecherche.setText("Affichage des résultats");
                    tResultats.setText(s.toString());
                    lStatutRecherche.setText(resultats.length + " citations trouvées en " + Temps.getTexte(recherche.getTempsExecution()) + ".");
                    bLancer.setEnabled(true);
                    bChoixTexteCitant.setEnabled(true);
                    bChoixTexteCite.setEnabled(true);
                } catch(ListeStatistiqueNonInitialiseeException lnie) {
                    lStatutRecherche.setText("La recherche a échoué (liste statistique non initialisée).");
                }
            }
        }.start();
    }//GEN-LAST:event_bLancerActionPerformed

    private void bExportHTMLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bExportHTMLActionPerformed
        try {
            // TODO add your handling code here:
            File destination = Demandes.demandeFichier("Veuillez spécifier la destination de cet export.",
                    new String[]{"html"},
                    new String[]{"Fichier html (.html)"});
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destination), "UTF-8"))) {
                writer.write(
                        "<html><head><style rel=\"stylesheet\" type=\"text/css\">" + 
                        CSS + 
                        "</style>" + 
                        tResultats.getText().substring(15)
                );
            }
            lStatutExport.setText("L'export est terminé.");
        } catch (InteractionRefuseeException ex) {
            
        } catch (IOException ex) {
            lStatutExport.setText(ex.getClass() + " - " + ex.getMessage());
        }
    }//GEN-LAST:event_bExportHTMLActionPerformed

    private void rbStricteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rbStricteActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_rbStricteActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton bChoixTexteCitant;
    private javax.swing.JButton bChoixTexteCite;
    private javax.swing.JButton bExportHTML;
    private javax.swing.JButton bLancer;
    private javax.swing.JCheckBox cbFiltrerNonCitations;
    private javax.swing.JCheckBox cbImportanceOrdre;
    private javax.swing.JCheckBox cbSansMotsVides;
    private javax.swing.ButtonGroup groupeTolerance;
    private javax.swing.ButtonGroup groupeTraitementLangue;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JPanel jPanel12;
    private javax.swing.JPanel jPanel13;
    private javax.swing.JPanel jPanel14;
    private javax.swing.JPanel jPanel15;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel lStatutCitant;
    private javax.swing.JLabel lStatutCite;
    private javax.swing.JLabel lStatutExport;
    private javax.swing.JLabel lStatutRecherche;
    private javax.swing.JLabel lTexteCitant;
    private javax.swing.JLabel lTexteCite;
    private javax.swing.JPanel pCitant;
    private javax.swing.JPanel pCite;
    private javax.swing.JPanel pFiltrerNonCitations;
    private javax.swing.JPanel pFinition;
    private javax.swing.JPanel pFusion;
    private javax.swing.JPanel pImportanceOrdre;
    private javax.swing.JPanel pLancer;
    private javax.swing.JPanel pParametres;
    private javax.swing.JPanel pParams;
    private javax.swing.JPanel pResultats;
    private javax.swing.JPanel pSansMotsVides;
    private javax.swing.JPanel pTailleMax;
    private javax.swing.JPanel pTitre;
    private javax.swing.JPanel pTolerance;
    private javax.swing.JPanel pTraitement;
    private javax.swing.JPanel pTraitementLangue;
    private javax.swing.JRadioButton rbAbsolue;
    private javax.swing.JRadioButton rbBrut;
    private javax.swing.JRadioButton rbLemm;
    private javax.swing.JRadioButton rbNorm;
    private javax.swing.JRadioButton rbRelative;
    private javax.swing.JRadioButton rbStricte;
    private javax.swing.JEditorPane tResultats;
    private javax.swing.JFormattedTextField tSeuilAbsolu;
    private javax.swing.JFormattedTextField tSeuilFusion;
    private javax.swing.JFormattedTextField tSeuilRelatif;
    private javax.swing.JFormattedTextField tTailleContexte;
    private javax.swing.JFormattedTextField tTailleInitiale;
    private javax.swing.JFormattedTextField tTailleMax;
    private javax.swing.JTextField tTexteCitant;
    private javax.swing.JTextField tTexteCite;
    private javax.swing.JTabbedPane tpPrincipal;
    // End of variables declaration//GEN-END:variables
}
