/*
 * NAT - An universal Translator
 * Copyright (C) 2005 Bruno Mascret
 * Contact: bmascret@free.fr
 * 
 * This program 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 2
 * of the License.
 * 
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package nat.convertisseur;

import nat.Nat;
import nat.Transcription;
import gestionnaires.GestionnaireErreur;

//***  java.io ***
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

public class ConvertisseurTexteXML extends ConvertisseurTexte
{
	public ConvertisseurTexteXML(String source, String cible)
	{
		super(source, cible);
		sourceEncoding = "UTF-8";
	}
	
	public ConvertisseurTexteXML(String source, String cible,String sEncoding)
	{
		super(source, cible);
		sourceEncoding = sEncoding;
	}

	public boolean convertir(GestionnaireErreur gest)
	{
		boolean retour=true;
		
		tempsExecution = System.currentTimeMillis();
		nbCars = 0;
		nbMots = 0;
		nbPhrases = 0;
		//marche pas sous windows: String longDTD = System.getProperty("user.dir") + "/xsl/" + ConfigNat.getCurrentConfig().getDTD();
		//dans Convertisseur: String longDTD = "./xsl/" + ConfigNat.getCurrentConfig().getDTD();
		try
		{
			gest.AfficheMessage("** Création du fichier de travail " + Transcription.fTempEntetes +" à partir du source: " + source + " ...",Nat.LOG_VERBEUX);
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(source),sourceEncoding));
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(Transcription.fTempEntetes),"UTF-8"));
			gest.AfficheMessage("ok\n** Ajout des entêtes XML à la copie du fichier source ...",Nat.LOG_NORMAL);
			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
			bw.write("<!DOCTYPE doc:doc SYSTEM \"" + "../" + DTD +"\">\n");
			bw.write("<doc>\n");
			String ligne;
			while((ligne=br.readLine())!=null){bw.write(ligne+"\n");}
			bw.write("</doc>");
			bw.close();
			br.close();

			 // Création d'un nouveau DOM pour la sortie
			gest.AfficheMessage("ok\n** Création d'un DOM à partir de " + Transcription.fTempEntetes+ " ...",Nat.LOG_VERBEUX);
            DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
            fabrique.setValidating(false);
            fabrique.setNamespaceAware(true);
            fabrique.setExpandEntityReferences(true);
            fabrique.setXIncludeAware(false);
            DocumentBuilder constructeur = fabrique.newDocumentBuilder();
            Document document = constructeur.parse(new File(Transcription.fTempEntetes));
            
            gest.AfficheMessage("ok\n** Création d'un DOM pour la conversion au format interne ...",Nat.LOG_VERBEUX);
            Document document2 = constructeur.newDocument();
            // Propriétés du DOM
            document2.setXmlVersion("1.0");
            document2.setXmlStandalone(false);
            document2.setStrictErrorChecking(true);  

            gest.AfficheMessage("ok\n** Conversion au format interne ...",Nat.LOG_VERBEUX);
            Element racineDoc = document2.createElement("doc:doc");
            racineDoc.setAttribute("xmlns:doc","espaceDoc");
            Element base = document.getDocumentElement();
            //System.out.println("Racine:" + base.getNodeName());
            NodeList list = base.getChildNodes();
            //NodeList list = base.getElementsByTagName("*");
            Element element;
            Element racine = document2.createElement("phrase");
            for (int i=0; i<list.getLength(); i++)
            {
              Node node = list.item(i);
              if(node.getNodeType()==Node.ELEMENT_NODE)
              {
	              element = (Element)node;
	              //System.out.println("******"+element.getNodeName()+ "******");
	              // recopiage des maths sans les semantics
	              if (element.getNodeName().equals("math"))
	              {
	            	  NodeList list2 = element.getElementsByTagName("*");
	            	  Element fils = (Element)list2.item(0);
	            	  if (fils.getNodeName().equals("semantics"))
	                  {
	            		  NodeList list3 = fils.getElementsByTagName("*");
	                	  fils = (Element)list3.item(0);
	                	  element = document2.createElementNS("http://www.w3.org/1998/Math/MathML","math");
	                	  fils = (Element)document2.adoptNode(fils);
	                	  element.appendChild(fils);
	                	  i = i + list2.getLength()-1;
	                  }            	  
	              }
	              racine.appendChild(element);
              }
              else
              {
            	  element = document2.createElement("lit");
            	  String contenu = node.getTextContent();
            	  String phrase[] = contenu.split("\n");
            	  for(int j =0; j<phrase.length;j++)
            	  {
            		  ligneLit(phrase[j], gest,element,document2);
            		  racine.appendChild(element);
            		  racineDoc.appendChild(racine);
            		  racine = document2.createElement("phrase");
            		  element = document2.createElement("lit");
            	  }
              }
            }
            /* On a fini: écriture de la racine */
            document2.appendChild(racineDoc);
            
            Source source = new DOMSource(document2);
            gest.AfficheMessage("ok\n** Création du fichier de sortie " +  cible+ " ...",Nat.LOG_VERBEUX);
            // Création du fichier de sortie
            File f = new File(cible);
            Result resultat = new StreamResult(f);
            
            // Configuration du transformer
            TransformerFactory tfabrique = TransformerFactory.newInstance();
            Transformer transformer = tfabrique.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");   
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,DTD);
            // Transformation
            transformer.transform(source, resultat);
            gest.AfficheMessage("ok\n** Conversion au format interne terminée",Nat.LOG_VERBEUX);
            retour = true;
		}
		catch (ParserConfigurationException pce) 
		{
			gest.setException(pce);
			gest.GestionErreur();
			gest.AfficheMessage("\n**Utilisation du convertisseur texte mixte", Nat.LOG_SILENCIEUX);
			gest.setException(null);
			Convertisseur c =new ConvertisseurTexteMixte(source, cible, sourceEncoding);
			retour = c.convertir(gest);
		} 
		catch (TransformerConfigurationException tce) 
		{
			gest.setException(tce);
			gest.GestionErreur();
			retour = false;
		} 
		catch (TransformerException te) 
		{
			gest.setException(te);
			gest.GestionErreur();
			retour = false;
		} 
		catch (UnsupportedEncodingException uee) 
		{
			gest.setException(uee);
			gest.GestionErreur();
			retour = false;
		} 
		catch (FileNotFoundException fnfe) 
		{
			gest.setException(fnfe);
			gest.GestionErreur();
			retour = false;
		} 
		catch (IOException ioe) 
		{
			gest.setException(ioe);
			gest.GestionErreur();
			retour = false;
		} 
		catch (SAXException se) 
		{
			gest.setException(se);
			gest.GestionErreur();
			gest.AfficheMessage("\n**Utilisation du convertisseur texte mixte", Nat.LOG_SILENCIEUX);
			gest.setException(null);
			Convertisseur c =new ConvertisseurTexteMixte(source, cible, sourceEncoding);
			retour = c.convertir(gest);
		}
		tempsExecution = System.currentTimeMillis() - tempsExecution;
		gest.AfficheMessage("----Conversion texte xml terminée en " + tempsExecution + " msec.\n",Nat.LOG_VERBEUX);
		return retour;
	}
	private void ligneLit(String ligne, GestionnaireErreur gest,Element base, Document doc)
	{
		int i=0;
		int j=0;
		String [] mots = null;
		//feinte pour pas s'emmm... avec les points de suspensions et les tab:
		ligne = ligne.replace("...","…");
		ligne = ligne.replace("\t"," ");
		if (ligne != null && ligne.length()>0)
		{
			mots=ligne.split(" ");
			if (mots.length == 0) // si il n'y a qu'un seul mot dans la ligne
			{
				mots = new String[1];
				mots[0] = ligne;
			}
			//System.out.println("ligne:" + ligne + " mot0:" + mots[0]);
		}
		if ((mots != null) && !(mots.length==1 && mots[0] == " "))// changer avec taille split:fait
		{
			nbMots = nbMots + mots.length;
			while (i<mots.length)
			{
				j=0;
				boolean trouve=false;
				boolean suivant = false;
				//int debutMot = 0;
				while (!trouve && j<ponctuationDebut.length)
				{
					if (mots[i].startsWith(ponctuationDebut[j])||mots[i]==ponctuationDebut[j])
					{		//mots[i].length()-1
						Element element = doc.createElement("ponctuation");
						element.setTextContent(""+mots[i].charAt(0));
						base.appendChild(element);
						if (mots[i].length()>1)
						{
							mots[i] = mots[i].substring(1,mots[i].length());
						}
						else
						{
						//c'est fini, on passe au mot suivant
							suivant = true;
						}
						nbCars = nbCars + 1;
						trouve=true;
					}
					j++;
				}
				j=0;
				trouve = false;
				if(!suivant)
				{
					while (!trouve && j<ponctuationFin.length)
					{
						if (mots[i].endsWith(ponctuationFin[j])||mots[i]==ponctuationFin[j])
						{			
							if (mots[i].length()>1)
							{
								Element element = doc.createElement("mot");
								element.setTextContent(mots[i].substring(0,mots[i].length()-1).replace("&","&amp;").replace("<","&lt;"));
								base.appendChild(element);
							}
							Element element = doc.createElement("ponctuation");
							element.setTextContent(""+mots[i].charAt(mots[i].length()-1));
							base.appendChild(element);
							nbCars = nbCars + mots[i].length() + 1;
							trouve=true;
						}
						j++;
					}				
					if(!trouve)
					{
						Element element = doc.createElement("mot");
						element.setTextContent(mots[i].replace("&","&amp;").replace("<","&lt;"));
						base.appendChild(element);
						nbCars = nbCars + mots[i].length();
					}
				}
				i++;
			}
			i=0;
		}
	}
}