/*
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.modele.lemmatiseurs;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import fr.cnrs.liris.drim.grt.modele.ProcedeLemmatisation;
import fr.cnrs.liris.drim.grt.modele.listes.Liste;
import fr.cnrs.liris.drim.grt.ihm.GestionnaireErreurs;
import fr.cnrs.liris.drim.grt.modele.listes.OrdreAlphabetiqueGrec;

/**
 *
 * @author Sam
 */
public class Perseus implements ProcedeLemmatisation, Liste {
    private final static Perseus instance = new Perseus();

    private Map<String, String[]> liste;
    Set<String> listeLemmes;
    
    private Perseus() {
        liste = new HashMap<>();
        listeLemmes = new HashSet<>();
    }
    
    public static Perseus getInstance() {
        return instance;
    }
    
    @Override
    public String[] getListeFormes() {
        String[] resultat = new String[getListe().keySet().size()];
        getListe().keySet().toArray(resultat);
        return resultat;
    }
    
    private Map<String, String[]> getListe() {
        if(liste.isEmpty()) {
            // chargement du fichier
            File fichier = new File("lemmesPerseus.txt");
            if(fichier.exists()) {
                try {
                    BufferedReader lecteur = new BufferedReader(new InputStreamReader(new FileInputStream(fichier), "UTF-8"));
                    while(lecteur.ready()) {
                        String[] ligne = lecteur.readLine().split("=="); // on manipule du beta code, on ne prend pas de risque avec un = simple
                        if(ligne.length>1) {
                            if(ligne[0].contains("\"") || ligne[0].contains(".") || ligne[0].contains(";")) {
                                System.err.println("Suppression de " + ligne[0] + " et de ses lemmes ("+Arrays.toString(ligne)+").");
                            } else {
                                liste.put(ligne[0], ligne[1].split(";;"));
                                //System.err.println(ligne[0] + " -> " + Arrays.toString(ligne[1].split(";;")));
                                listeLemmes.addAll(Arrays.asList(ligne[1].split(";;")));
                            }
                        } else if(ligne.length>0 ) {
                            if(ligne[0].contains("\"") || ligne[0].contains(".") || ligne[0].contains(";")) {
                                System.err.println("Suppression de " + ligne[0] + ".");
                            } else {
                                liste.put(ligne[0], new String[]{});
                            }
                        } else { // une ligne vide
                            
                        }
                    }
                } catch (IOException ex) {
                    GestionnaireErreurs.getInstance().affiche("Erreur d'application", 
                            "<html><p>Le fichier lemmesPerseus.txt est présent mais illisible.</p>"
                            + "<ul><li>Choix 1 : veuillez corriger la situation si vous savez comment ;</li>"
                            + "<li>Choix 2 : veuillez le supprimer, et on recommencera à zéro la lemmatisation.</li></ul>"
                            + "<p>Pour information, l'erreur est</p>"
                            + "<p>"+ex.getClass()+" : "+ex.getMessage()+"</p></html>");
                }
            } else {
                // pas de fichier ? Pas grave, on en crée un vide
                try {
                    fichier.createNewFile();
                } catch (IOException ex) {
                    GestionnaireErreurs.getInstance().affiche("Erreur d'application", 
                            "<html><p>Nous n'avons pas trouvé le fichier lemmesPerseus.txt qui contient la liste des lemmes.</p>"
                            + "<p>Nous avons essayé de le créer, sans succès.</p>"
                            + "<p>Nous vous recommandons de nous permettre d'écrire un tel fichier avant de continuer.</p>"
                            + "<p>Pour information, l'erreur est</p>"
                            + "<p>"+ex.getClass()+" : "+ex.getMessage()+"</p></html>");
                }
            }
        }
        return liste;
    }
    
    public void addLemme(String terme, String lemme) {
        if(getListe().containsKey(terme)) {
            Set<String> listeLemmes = new HashSet<>(Arrays.asList(liste.get(terme)));
            listeLemmes.add(lemme);
            String[] nlleListe = new String[listeLemmes.size()];
            listeLemmes.toArray(nlleListe);
            liste.put(terme, nlleListe);
        } else {
            liste.put(terme, new String[]{lemme});
        }
    }
    
    @Override
    public boolean contientLemme(String lemme) {
        getListe();
        return listeLemmes.contains(lemme);
    }
    
    @Override
    public String[] getFormesLemmatisees(String terme) {
        if(!(getListe().containsKey(terme))) {
            //System.err.println("Introuvable : " + terme);
            return new String[]{};
        }
        return getListe().get(terme);
    }

    @Override
    public String getStats() {
        Map<String, String[]> listeLemmesParTerme = getListe();
        Map<Integer, Integer> tableauNbLemmesParTerme = new HashMap<>();
        for(String terme : listeLemmesParTerme.keySet()) {
            String[] lemmes = listeLemmesParTerme.get(terme);
            Integer nb = new Integer(lemmes.length);
            if(tableauNbLemmesParTerme.get(nb) != null) {
                tableauNbLemmesParTerme.put(nb, new Integer(tableauNbLemmesParTerme.get(nb).intValue() + 1));
            } else {
                tableauNbLemmesParTerme.put(nb, new Integer(1));
            }
        }
        String rapport = "";
        int comptes = 0;
        for(int i=0; i<10; i++) {
            int qt = 0;
            try {
                qt = tableauNbLemmesParTerme.get(i).intValue();
            } catch(NullPointerException npe) {
                // aucun terme n'a ce nombre de lemmes différents : on reste à 0
            }
            comptes += qt;
            rapport += i + " lemmes parmi lesquels choisir : " + qt + " termes différents ("+
                    (int)(1000.0*qt/listeLemmesParTerme.keySet().size())/10.0+"%).\n";
        }
        rapport += "10 lemmes et plus parmi lesquels choisir : " + (listeLemmesParTerme.keySet().size() - comptes) + " termes différents ("+
                    (int)(1000.0*(listeLemmesParTerme.keySet().size() - comptes)/listeLemmesParTerme.keySet().size())/10.0+"%).\n";
        return rapport;
    }

    @Override
    public String[] listeTermesSansLemme() {
        ArrayList<String> resultat = new ArrayList<>();
        for(String terme : getListe().keySet()) {
            if(getListe().get(terme).length == 0) {
                resultat.add(terme);
            }
        }
        String[] res = new String[resultat.size()];
        resultat.toArray(res);
        Arrays.sort(res, new OrdreAlphabetiqueGrec());
        return res;
    }
    
    public void lemmatiseLemmes() {
        Map<String, String[]> liste0 = getListe();
        Set<String> lemmes = new HashSet<>();
        for(String[] lLemmes: liste0.values()) {
            lemmes.addAll(Arrays.asList(lLemmes));
        }
        
        for(String lemme: lemmes) {
            String[] lLemmes;
            if(liste0.containsKey(lemme)) {
                lLemmes = liste0.get(lemme);
            } else {
                lLemmes = new String[]{};
            }
            ArrayList<String> lLemmes2 = new ArrayList<>(Arrays.asList(lLemmes));
            System.err.println("Ajout du lemme " + lemme);
            lLemmes2.add(0, lemme);
            String[] lLemmes3 = new String[lLemmes2.size()];
            lLemmes2.toArray(lLemmes3);
            liste0.put(lemme, lLemmes3);
        }
        archive();
        dedoublonne();
    }
    
    public void dedoublonne() {
        liste.clear();
        listeLemmes.clear();
        getListe();
        archive();
    }
    
    @Override
    public void archive() {
        sauvegarde();
    }
    
    private void sauvegarde() {
        File fichier = new File("lemmesPerseus.txt");
        if(!(fichier.exists())) {
            // pas de fichier ? Pas grave, on en crée un vide
            try {
                fichier.createNewFile();
            } catch (IOException ex) {
                GestionnaireErreurs.getInstance().affiche("Erreur d'application", 
                            "<html><p>Nous n'avons pas trouvé le fichier lemmesPerseus.txt qui contient la liste des lemmes.</p>"
                            + "<p>Nous avons essayé de le créer, sans succès.</p>"
                            + "<p>Nous vous recommandons de nous permettre d'écrire un tel fichier avant de continuer.</p>"
                            + "<p>Pour information, l'erreur est</p>"
                            + "<p>"+ex.getClass()+" : "+ex.getMessage()+"</p></html>");
            }
        }
        try {
            BufferedWriter lecteur = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fichier), "UTF-8"));
            for(String terme: liste.keySet()) {
                String[] lemmes = liste.get(terme);
                String l = "";
                for(int i=0; i<lemmes.length; i++) {
                    l += lemmes[i];
                    if(i < lemmes.length-1) {
                        l += ";;";
                    }
                }
                lecteur.write(terme+"=="+l + "\n"); // on risque de manipuler du beta code, on ne prend pas de risque avec un = simple
            }
            lecteur.flush();
        } catch (IOException ex) {
            GestionnaireErreurs.getInstance().affiche("Erreur d'application", 
                            "<html><p>Le fichier lemmesPerseus.txt est présent mais nous en pouvons pas l'alimenter.</p>"
                            + "<p>Veuillez corriger la situation si vous savez comment.</p>"
                            + "<p>Pour information, l'erreur est</p>"
                            + "<p>"+ex.getClass()+" : "+ex.getMessage()+"</p></html>");
        }
    }
    
}
