/*
 * 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 ui;

// *** Composants graphiques ***
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;

import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.nio.charset.Charset;
import java.util.Arrays;

import javax.swing.ImageIcon;
import outils.Embosseur;
import outils.EmbosseurInstalle;
import outils.EmbosseurLDC;

//*** Gestionnaires ***
import gestionnaires.GestionnaireOuvrir;
import gestionnaires.GestionnaireErreur;
import gestionnaires.GestionnaireOuvrirFenetre;
import nat.ConfigNat;
import nat.Nat;


public class FenetrePrinc extends JFrame implements ActionListener, FocusListener, WindowListener
{
    /**
     *  Attributs
     */
    private static final long serialVersionUID = 1L;
    //private JLabel lTitre = new JLabel("<html><center><h1>NAT 1.3.2 \"Claude\"</h1></center></html>"); Bruno:plus utilisé?
    private JTextField  entreeXML = new JTextField("./licence.txt",30);
    private JLabel lEntree = new JLabel("Source");
    private JButton ouvrirSource = new JButton("Sélectionner source",new ImageIcon("ui/icon/document-open.png"));
    private JTextField  sortie = new JTextField("",30);
    private JLabel lSortie = new JLabel("Sortie");
    private JButton ouvrirSortie = new JButton("Sélectionner sortie",new ImageIcon("ui/icon/document-open.png"));

    private JButton transcrire = new JButton("Transcrire",new ImageIcon("ui/icon/system-run.png"));
    //private JButton voir_log = new JButton("voir_log");
    private JButton btEditeur = new JButton("Ouvrir le fichier transcrit",new ImageIcon("ui/icon/gtk-edit.png"));

    private JTextField  filtre = new JTextField("xsl.xsl",20);

    private JCheckBox debug = new JCheckBox();
    private JTextArea panneauLog;// = new JTextArea (15,40);

    private JLabel lConfig = new JLabel("Configuration active:");
    private JComboBox jcbConfig = new JComboBox();
    private JButton btOption = new JButton("Options",new ImageIcon("ui/icon/document-properties.png"));
    private JButton btAide = new JButton("Aide",new ImageIcon("ui/icon/help-browser.png"));
    private JButton btAPropos = new JButton("A propos...",new ImageIcon("ui/icon/help-about.png"));
    private JButton btQuitter = new JButton("Quitter",new ImageIcon("ui/icon/exit.png"));
   
    private GestionnaireErreur gestErreur;
    private Nat nat;
    private boolean optionsOuvertes = false;
	
    //constructeur
    public FenetrePrinc(Nat n)
    {
		this.setIconImage(new ImageIcon("ui/nat.png").getImage());
		nat = n;
		gestErreur = new GestionnaireErreur(null,panneauLog,ConfigNat.getCurrentConfig().getNiveauLog());
		gestErreur.setModeDebugage(debug.isSelected());
		fabriqueFenetre();
    }

    //méthodes d'accès
    public JTextField getEntree(){return entreeXML;}
    public JTextField getFiltre(){return filtre;}
    public JTextField getSortie(){return sortie;}
    public void setEntree(String entree){entreeXML.setText(entree);}
    public void setFiltre(String filtre){this.filtre.setText(filtre);}	
    public void setSortie(String sortie)
    {
    	this.sortie.setText(sortie);
    	this.verifieBtEditeur();
    }
    public boolean getOptionsOuvertes(){return optionsOuvertes;}
    public void setOptionsOuvertes(boolean oo){optionsOuvertes=oo;}
	
    //méthodes
    private void fabriqueFenetre()
    {
		// titre de la fenêtre 
		this.setTitle("NAT " + nat.getVersionLong());
		setName("NAT: fenêtre principale");
		getAccessibleContext().setAccessibleName("NAT: fenêtre principale");
		getAccessibleContext().setAccessibleDescription("Transcripteur NAT: Fenêtre principale");
			
		// fichier d'entrée : label, champ, bouton
		lEntree.setLabelFor(entreeXML);
		if(ConfigNat.getCurrentConfig().getFsource().length()>0)
	    {
			entreeXML.setText(ConfigNat.getCurrentConfig().getFsource());
	    }
		lEntree.setDisplayedMnemonic('u');
		entreeXML.setName("Fichier source");
		entreeXML.getAccessibleContext().setAccessibleName("Champ de saisie du fichier source");
		entreeXML.getAccessibleContext().setAccessibleDescription("Entrer l'adresse du fichier à transcrire");
		entreeXML.setToolTipText("Entrer l'adresse du fichier à transcrire");
		entreeXML.addFocusListener(this);
		ouvrirSource.addActionListener(new GestionnaireOuvrir(this,GestionnaireOuvrir.OUVRIR_SOURCE));
		ouvrirSource.setMnemonic('e');
		ouvrirSource.setToolTipText("Sélectionner le fichier à transcrire dans l'arborescence de votre système de fichiers");
			
		// fichier de sortie : label, champ, bouton
		lSortie.setLabelFor(sortie);
		lSortie.setDisplayedMnemonic('r');
		if(ConfigNat.getCurrentConfig().getFcible().length()>0)
	    {
			sortie.setText(ConfigNat.getCurrentConfig().getFcible());
	    }
		sortie.setName("Fichier sortie");
		sortie.getAccessibleContext().setAccessibleName("Champ de saisie du fichier cible");
		sortie.getAccessibleContext().setAccessibleDescription("Entrer l'adresse du fichier transcrit");
		sortie.setToolTipText("Entrer l'adresse de sauvegarde pour le fichier transcrit");
		sortie.addFocusListener(this);
		ouvrirSortie.addActionListener(new GestionnaireOuvrir(this,GestionnaireOuvrir.OUVRIR_SORTIE));
		ouvrirSortie.setMnemonic('s');
		ouvrirSortie.setToolTipText("Sélectionner le fichier de sortie dans l'arborescence de votre système de fichiers");
	
	
		// bouton pour lancer la transcription
		transcrire.addActionListener(this);
		transcrire.setMnemonic('t');
		transcrire.getAccessibleContext().setAccessibleName("Bouton transcrire");
		transcrire.getAccessibleContext().setAccessibleDescription("Valider pour lancer la transcription");
		transcrire.setToolTipText("Lancer la transcription");
		/* c'est quoi ça? 
		 * Bruno: c'est pour cacher / montrer la fenetre de log. C'est pas implémenté: je commente
		 * ********** 
		voir_log.addActionListener(this);
		voir_log.setMnemonic('a');
		voir_log.getAccessibleContext().setAccessibleName("Bouton transcrire2");
		voir_log.getAccessibleContext().setAccessibleDescription("Valider pou2r lancer la transcription");
		voir_log.setToolTipText("Lancer la transcri2ption");
		/* ***********/
		btEditeur.addActionListener(this);
		btEditeur.setMnemonic('l');
		btEditeur.getAccessibleContext().setAccessibleName("Bouton ouvrir le fichier transcrit");
		btEditeur.getAccessibleContext().setAccessibleDescription("Valider pour ouvrir le fichier transcrit avec l'application choisie");
		btEditeur.setToolTipText("Ouvrir le fichier transcrit avec l'application choisie");
		verifieBtEditeur();
		
		// panneau de log
		debug.setText("Debugage actif");
		panneauLog = new JTextArea (15,40);
		panneauLog.setEditable(false);
		panneauLog.setLineWrap(true);
	
		JScrollPane scrollLog = new JScrollPane (panneauLog);
		scrollLog.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scrollLog.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	
		// bouton pour la fenêtre d'options
		btOption.addActionListener(new GestionnaireOuvrirFenetre(GestionnaireOuvrirFenetre.OUVRIR_OPTIONS,this));
		btOption.setMnemonic('o');
		btOption.getAccessibleContext().setAccessibleName("Bouton options");
		btOption.getAccessibleContext().setAccessibleDescription("Valider pour ouvrir la fenêtre de paramétrage");
		btOption.setToolTipText("Ouvrir la fenêtre de paramétrage");
	
		// bouton pour la fenêtre d'aide
		btAide.addActionListener(new GestionnaireOuvrirFenetre(GestionnaireOuvrirFenetre.OUVRIR_AIDE,this));
		btAide.setMnemonic(java.awt.event.KeyEvent.VK_F6);
		btAide.getAccessibleContext().setAccessibleName("Bouton Aide");
		btAide.getAccessibleContext().setAccessibleDescription("Valider pour ouvrir la fenêtre d'aide de NAT");
		btAide.setToolTipText("Ouvrir la fenêtre d'aide");
	
		// bouton pour la fenêtre a propos
		btAPropos.addActionListener(new GestionnaireOuvrirFenetre(GestionnaireOuvrirFenetre.OUVRIR_APROPOS,this));
		btAPropos.setMnemonic(java.awt.event.KeyEvent.VK_F11);
		btAPropos.getAccessibleContext().setAccessibleName("Bouton à propos de NAT");
		btAPropos.getAccessibleContext().setAccessibleDescription("Valider pour ouvrir la fenêtre d'information sur le développement de NAT");
		btAPropos.setToolTipText("Ouvrir la fenêtre d'information sur NAT");
	
		// bouton pour quitter
		btQuitter.addActionListener(this);
		btQuitter.setMnemonic('q');
		btQuitter.getAccessibleContext().setAccessibleName("Bouton Quitter NAT");
		btQuitter.getAccessibleContext().setAccessibleDescription("Valider pour quitter NAT");
		btQuitter.setToolTipText("Quitter NAT");
			
		// label de config
		lConfig.setLabelFor(jcbConfig);
		lConfig.setDisplayedMnemonic('c');
		chargeConfigurations();//jcbConfig);
		jcbConfig.addActionListener(this);
	
		// combo de choix de la config
		jcbConfig.setEditable(false);
		jcbConfig.getAccessibleContext().setAccessibleName("Liste à choix multiples configurations");
		jcbConfig.getAccessibleContext().setAccessibleDescription("Sélectionner à l'aide des flèches la configuration à utiliser");
		jcbConfig.setToolTipText("Sélectionner la configuration");
		jcbConfig.addActionListener(this);
	
		setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		c.insets = new Insets(10,3,3,3);
		// l 1
		c.anchor = GridBagConstraints.LINE_END;
		c.fill = GridBagConstraints.NONE;
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		c.weightx = 0.0;
		add(lEntree,c);
	
		c.fill = GridBagConstraints.HORIZONTAL;
		c.anchor = GridBagConstraints.CENTER;
		c.gridx = 1;
		c.gridy = 1;
		c.gridwidth = 1;
		c.weightx = 1.0;
		add(entreeXML,c);
		
		c.gridx = 2;
		c.gridy = 1;
		c.gridwidth = 1;
		c.weightx = 0.0;
		add(ouvrirSource,c);
	
		// l 2
		c.anchor = GridBagConstraints.LINE_END;
		c.fill = GridBagConstraints.NONE;
		c.gridx = 0;
		c.gridy = 2;
		c.gridwidth = 1;
		add(lSortie,c);
		c.anchor = GridBagConstraints.CENTER;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 1;
		c.gridy = 2;
		c.gridwidth = 1;
		add(sortie,c);
		c.gridx = 2;
		c.gridy = 2;
		c.gridwidth = 1;
		add(ouvrirSortie,c);
	
		// l 3		
		c.gridx = 1;
		c.gridy = 3;
		c.gridwidth = 1;
		add(transcrire,c);
		c.gridx = 2;
		c.gridy = 3;
		c.gridwidth = 1;
		add(btEditeur,c);
	
		// l 4
		c.anchor = GridBagConstraints.LINE_END;
		c.fill = GridBagConstraints.NONE;
		c.gridx = 0;
		c.gridy = 4;
		c.gridwidth = 1;
		c.weightx = 0.0;
		add(lConfig,c);
	
		c.fill = GridBagConstraints.HORIZONTAL;
		c.anchor = GridBagConstraints.CENTER;
		c.gridx = 1;
		c.gridy = 4;
		c.gridwidth = 1;
		c.weightx = 1.0;
		add(jcbConfig,c);
		
		c.gridx = 2;
		c.gridy = 4;
		c.gridwidth = 1;
		c.weightx = 0.0;
		add(btOption,c);
	
		// l 5
		c.gridx = 0;
		c.gridy = 5;
		c.gridwidth = 1;
		//	add(voir_log,c);
		
		 // l 6
		JPanel panneauAffichage = new JPanel();
		panneauAffichage.add(scrollLog);
		//nom et description devraient appartenir au scrollPane scrollLog ?
		panneauAffichage.getAccessibleContext().setAccessibleName("Panneau d'affichage");
		panneauAffichage.getAccessibleContext().setAccessibleDescription("Panneau d'affichage dynamique des traitements (logs)");
		//	panneauAffichage.setPreferredSize(new Dimension(600,300));
	
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 1.0;
		c.weighty = 1.0;
		c.gridx = 0;
		c.gridy = 6;
		c.gridwidth = 3;
		//	add(panneauAffichage,c);
		add(scrollLog,c);
	
		// l 7
		c.fill = GridBagConstraints.NONE;
		c.weightx = 0.0;
		c.weighty = 0.0;
		c.gridwidth = 1;
	
		c.gridx = 0;
		c.gridy = 7;
		add(btAide,c);
	
		c.gridx = 1;
		c.gridy = 7;
		c.gridwidth = 1;
		add(btAPropos,c);
	
		c.gridx = 2;
		c.gridy = 7;
		c.gridwidth = 1;
		add(btQuitter,c);
	
		//c'est la méthode de windowslistener qui va gérer la fermeture
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		addWindowListener(this);
		//position de la fenêtre
		if(ConfigNat.getCurrentConfig().getCentrerFenetre())
		{
			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
			Dimension size = this.getPreferredSize();
			screenSize.height = screenSize.height/2;
			screenSize.width = screenSize.width/2;
			size.height = size.height/2;
			size.width = size.width/2;
			int y = screenSize.height - size.height;
			int x = screenSize.width - size.width;
			setLocation(x, y);
		}
    }
	
    public void chargeConfigurations()//JComboBox jcb)
    {
		File repertoire =new File("configurations");
		//System.out.println ( repertoire.getAbsolutePath());
		File[] listConfs = repertoire.listFiles();
		Arrays.sort(listConfs);
		
		String config = "";
		//jcbConfig.removeActionListener(this);

		/*jcbConfig.removeAllItems();
		jcbConfig.setEnabled(false);*/
		    
		for(int i=0;i<listConfs.length;i++)
	    {
			int nbConfig = 0;
	    	if (listConfs[i].getName().endsWith(".cfg"))
		    {
	    		nbConfig++;
	    		config = listConfs[i].getName().substring(0,listConfs[i].getName().length()-4);
	    		boolean present = false;
	    		int j = 0;
	    		//la config existe-t-elle déjà dans la liste?
	    		while (!present && j<jcbConfig.getItemCount())
	    		{
	    			if(config.equals(jcbConfig.getItemAt(j))){present = true;}
	    			j++;
	    		}
	    		if(!present)
	    		{
	    			j=0;
	    			while(j<jcbConfig.getItemCount() && config.compareTo((String)(jcbConfig.getItemAt(j)))>0)
	    			{
	    				j++;
	    			}
	    			jcbConfig.insertItemAt(config, j);
	    			//System.out.println("configurations/"+listConfs[i].getName()+" yopla " +ConfigNat.getCurrentConfig().getFichierConf());

	    		}	
    			if(("configurations/"+listConfs[i].getName()).equals(ConfigNat.getCurrentConfig().getFichierConf()))
			    {
	    			jcbConfig.setSelectedItem(config);
			    }
		    }
	    }
		/*jcbConfig.setEnabled(true);
		jcbConfig.addActionListener(this);*/
    }

    public void afficheFichier(String nomFichier) 
    {
		Embosseur emb = null;
		if(ConfigNat.getCurrentConfig().getUtiliserCommandeEmbossage())
	    {
			emb = new EmbosseurLDC(nomFichier,gestErreur);
	    }
		else if (ConfigNat.getCurrentConfig().getUtiliserEmbosseuse())
	    {
			emb = new EmbosseurInstalle(nomFichier, gestErreur);
	    }
		Editeur editeur = new Editeur(ConfigNat.getCurrentConfig().getLongueurLigne(),emb);
		String sourceEncoding = ConfigNat.getCurrentConfig().getSortieEncoding();
			
		if (sourceEncoding.equals("automatique"))
	    {
			sourceEncoding = nat.trouveEncodingSource(nomFichier, gestErreur);
			if(sourceEncoding == null||sourceEncoding.equals(""))
		    {
				// pas de bol, on n'a pas réussit à trouver le charset correct
				sourceEncoding = Charset.defaultCharset().name();
				gestErreur.AfficheMessage("\n** Impossible de détecter l'encodage du fichier sortie.\n** Utilisation de l'encodage par défaut: " + sourceEncoding + "\n",Nat.LOG_NORMAL);
		    }
			else
		    {
				gestErreur.AfficheMessage("\n** Détection automatique de l'encodage du fichier sortie: "+sourceEncoding+"\n", Nat.LOG_SILENCIEUX);
		    }
	    }
		editeur.setEncodage(sourceEncoding);
		editeur.setTableBraille(ConfigNat.getCurrentConfig().getTableBraille());
		
		editeur.setAfficheLigneSecondaire(ConfigNat.getCurrentConfig().getAfficheLigneSecondaire());
		editeur.afficheFichier(nomFichier, ConfigNat.getCurrentConfig().getPoliceEditeur(), ConfigNat.getCurrentConfig().getTaillePolice(),ConfigNat.getCurrentConfig().getPolice2Editeur(), ConfigNat.getCurrentConfig().getTaillePolice2());
		editeur.pack();
		editeur.setVisible(true);
    }

	
    //méthodes redéfinies
    public void actionPerformed(ActionEvent evt)
    {
		/*	  if (evt.getSource() == voir_log){
		  panneauAffichage.setVisible(!panneauAffichage.isVisible());
		  panneauLog.setText(""+panneauAffichage.isVisible());
		  repaint();
		  }
		*/
		//lancer transcription
		if (evt.getSource() == transcrire)    
	    {
			if(ConfigNat.getCurrentConfig().getSaxonAsXsltProcessor())
			{
				gestErreur.AfficheMessage(
						"\n***********************************" +
						"* ATTENTION, utilisation de SAXON *" +
						"\n***********************************", Nat.LOG_DEBUG);
				System.setProperty("javax.xml.transform.TransformerFactory",
				"net.sf.saxon.TransformerFactoryImpl");
				//jcbXsltProc.setEnabled(false);
			}
			else
			{
				System.setProperty("javax.xml.transform.TransformerFactory",
				"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
			}
			
			btEditeur.setEnabled(false);
			this.repaint();
			if ((entreeXML.getText().length()<1)||(filtre.getText().length()<1)||(sortie.getText().length()<1))
		    {
				System.out.println("Entrez un fichier source et un fichier cible");
				panneauLog.setText("Entrez un fichier source et un fichier cible");
		    }
			else
		    {
				panneauLog.setText("");
				panneauLog.paintImmediately(new Rectangle(0,0,panneauLog.getWidth(),panneauLog.getHeight()));
				gestErreur = new GestionnaireErreur(null,panneauLog,ConfigNat.getCurrentConfig().getNiveauLog());
				gestErreur.setModeDebugage(debug.isSelected());
				String source = entreeXML.getText();
				String cible = sortie.getText();
				if (nat.fabriqueTranscription(source, cible, gestErreur))
			    {
					nat.lanceScenario();			
					if (gestErreur.getException() == null )
				    {
						//mettre en place un gestionnaire
						if (ConfigNat.getCurrentConfig().getOuvrirEditeur())
					    {
							afficheFichier(sortie.getText());
					    }
						btEditeur.setEnabled(true);			
				    }
				}
		    }
	    }

		//ouvrir editeur
		else if (evt.getSource() == btEditeur)
	    {
			afficheFichier(sortie.getText());
	    }
		//combo box des configurations
		else if (evt.getSource() == jcbConfig)
	    {
			ConfigNat.charger("configurations/" + jcbConfig.getSelectedItem() + ".cfg");
	    }
		else if(evt.getSource() == btQuitter)
		{
			quitter();
		}
		
    }

	public void focusGained(FocusEvent foc) 
	{} //do nothing

	public void focusLost(FocusEvent foc)
	{
		if (foc.getSource()==sortie)
		{
			sortie.setCaretPosition(sortie.getText().length());
			verifieBtEditeur();
		}
		else if (foc.getSource()==entreeXML)
		{
			entreeXML.setCaretPosition(entreeXML.getText().length());
		}
	}
	
	private void verifieBtEditeur()
	{
		if(new File(sortie.getText()).exists()){btEditeur.setEnabled(true);}
		else{btEditeur.setEnabled(false);}
	}

	public void windowActivated(WindowEvent arg0) {}//do nothing
	public void windowClosed(WindowEvent arg0){quitter();}
	public void windowClosing(WindowEvent arg0) {}//do nothing
	public void windowDeactivated(WindowEvent arg0) {}//do nothing
	public void windowDeiconified(WindowEvent arg0) {}//do nothing
	public void windowIconified(WindowEvent arg0) {}//do nothing
	public void windowOpened(WindowEvent arg0){}//do nothing
	
	private void quitter()
	{
		gestErreur.AfficheMessage("\n** Enregistrement de la configuration avant de quitter...", Nat.LOG_NORMAL);
		ConfigNat.getCurrentConfig().setFcible(sortie.getText());
		ConfigNat.getCurrentConfig().setFsource(entreeXML.getText());
		ConfigNat.getCurrentConfig().sauvegarder();
		gestErreur.AfficheMessage(" ok! \n Au revoir!" , Nat.LOG_NORMAL);
	    System.exit(0);
	}
}
