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

import gestionnaires.GestionnaireMajTabBraille;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ContainerListener;
import java.awt.event.ContainerEvent;

import nat.ConfigNat;
import nat.Nat;
/**
 * Cette classe de l'interface graphique code la fenêtre permettant l'édition de la table braille
 * @author bruno
 */
public class ConfTableBraille extends JFrame implements ActionListener, ContainerListener 
{
	/** Pour la sérialisation (non utilisé) */
	private static final long serialVersionUID = 1L;
	/** La table d'affichage */
	private JTableNonEditCol1 table;
	/** Nom de la table en cours */
	private JLabel nomTable;
	/** Label pour afficher des messages d'information lors des enregistrements */
	private JLabel message = new JLabel("<html><br></html>");
	/** JScrollPane pour la table  */
	private JScrollPane scrollTable;
	/** JButton pour enregistrer */
	private JButton btEnregistrer = new JButton("Enregistrer",new ImageIcon("ui/icon/document-save.png"));
	/** JButton pour enregistrer sous */
	private JButton btEnregistrerSous = new JButton("Enregistrer sous...",new ImageIcon("ui/icon/document-save-as.png"));
	//private JTextField texteEnregistrerSous;
	/** JButton pour fermer la fenêtre */
	private JButton btQuitter = new JButton("Fermer",new ImageIcon("ui/icon/exit.png"));
	/** adresse de la table braille */
	private String fichierTable;
	/** adresse de la table braille de conversion*/
	private String fichierTableConv;
	/** Nom des colonnes de la table */
	private String[] lesColonnes = new String[]{"Braille", "Caractère", "Code"};
	/** Tableau pour les données de la table */
	private String[][] donnees;
	//private ConfigNat confNat;
	/** nom du fichier de la table */
	private String nomFichierTable;
	/** nom court du fichier de la table*/
	private String nomCourt = "";
	/** gestionnaire pour la mise à jour des listes de tables 
	private GestionnaireMajTabBraille gmtb ;*/
	/** true si il y a eu des modifications depuis le dernier enregistrement */
	private boolean modif = false;
	
	/**
	 * Constructeur
	 * @param btli l'item représentant la table braille
	 * @param gmtb le gestionanire de mise à jour des listes de tables
	 */
	public ConfTableBraille(BrailleTableListItem btli, GestionnaireMajTabBraille gmtb)//, ConfigNat confNat)
	{
		super("Edition de la table braille");
		
		String pathEmb;
		
		if(btli.getIsSystem())
		{
			pathEmb = ConfigNat.getInstallFolder()+"/xsl/tablesEmbosseuse/";
		}
		else
		{
			pathEmb = ConfigNat.getUserEmbossTableFolder()+"/";
		}

		fichierTable = btli.getFilename();
		fichierTableConv = pathEmb + btli.getName()+".ent";
		
		nomCourt = btli.getName();
		nomFichierTable = nomCourt+".ent";
		
		//this.gmtb = gmtb ;
		addWindowListener(gmtb) ;
		/*texteEnregistrerSous = new JTextField("nouvelle table", 10);
		texteEnregistrerSous.getAccessibleContext().setAccessibleName("Champ de saisie nom table");
		texteEnregistrerSous.getAccessibleContext().setAccessibleDescription("Entrer le nom de la nouvelle table puis activer le bouton enregistrer sous");
		texteEnregistrerSous.setToolTipText("Entrer le nom de la nouvelle table");*/
		
		nomTable = new JLabel("<html><center><h2>Table " + nomCourt + "</h2></center></html>");
		//on ouvre le fichier et on remplit la table
		afficheTable();
		table = new JTableNonEditCol1(donnees,lesColonnes);
		// permettre le tri sur les colonnes
		table.setAutoCreateRowSorter(true);
		//bug de sun pour la maj de la table
		table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
		
		scrollTable = new JScrollPane (table);
		scrollTable.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scrollTable.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scrollTable.setPreferredSize(new Dimension(300,350));
		
		table.addContainerListener(this);
		
		JPanel pTable = new JPanel();
		pTable.add(scrollTable);
		pTable.setPreferredSize(new Dimension(350,400));
		
		JPanel lesBoutons = new JPanel();
		btEnregistrer.addActionListener(this);
		btEnregistrer.getAccessibleContext().setAccessibleName("Bouton Enregistrer la table");
		btEnregistrer.getAccessibleContext().setAccessibleDescription("Valider pour enregistrer les modifications apportées à la table");
		btEnregistrer.setToolTipText("Enregistrer les modifications (Alt+s)");
		btEnregistrer.setMnemonic('s');
		btEnregistrer.setEnabled(!(ConfigNat.getCurrentConfig().getIsSysTable()));
		
		btQuitter.addActionListener(this);
		btQuitter.getAccessibleContext().setAccessibleName("Bouton fermer la fenêtre");
		btQuitter.getAccessibleContext().setAccessibleDescription("Valider pour fermer la fenêtre");
		btQuitter.setToolTipText("Fermer la fenêtre (Alt+f) ou (Alt+F4)");
		btQuitter.setMnemonic('f');
		
		btEnregistrerSous.addActionListener(this);
		btEnregistrerSous.getAccessibleContext().setAccessibleName("Bouton enregistrer sous");
		btEnregistrerSous.getAccessibleContext().setAccessibleDescription("Valider pour enregistrer la table  sous un nouveau nom");
		btEnregistrerSous.setToolTipText("Enregistrer la table  sous un nouveau nom (Alt+n)");
		btEnregistrerSous.setMnemonic('n');
		
		
		lesBoutons.add(btEnregistrer);
		lesBoutons.add(btEnregistrerSous);
		// lesBoutons.add(texteEnregistrerSous);
		lesBoutons.add(btQuitter);
		JPanel entete = new JPanel();
		entete.add(nomTable);
		entete.add(message);
		
		//setLayout(new BorderLayout(5,5));
		add(BorderLayout.NORTH, entete);
		add(BorderLayout.CENTER,pTable);
		add(BorderLayout.SOUTH,lesBoutons);
		setSize(500,500);
	}
	/**
	 * Méthode implémentée d'ActionListener
	 * Gère les évènements des boutons
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent evt)
	{
		if (evt.getSource()==btQuitter)
		{
			if(modif&&table.isValide())
			{
				//JOptionPane jopErreur = new JOptionPane();
				if(JOptionPane.showConfirmDialog( this,"Enregistrer les modifications?","Enregistrement", JOptionPane.YES_NO_OPTION)==JOptionPane.OK_OPTION)
				{
					enregistrer();
				}
			}
			this.dispose();
		}
		else
		{
			if(table.getCellEditor()!=null)
			{
				table.dispatchEvent(new ContainerEvent(table,ContainerEvent.COMPONENT_REMOVED,table.getComponentAt(table.getEditingRow(), table.getEditingColumn())));
			}
			boolean saisieOk=table.isValide();
			if (evt.getSource()==btEnregistrer&&saisieOk)
			{
				//JOptionPane jopErreur = new JOptionPane();
				if(JOptionPane.showConfirmDialog( this,"Voulez-vous écraser la table " + nomFichierTable,"Enregistrement", JOptionPane.YES_NO_OPTION)==JOptionPane.OK_OPTION)
				{
					enregistrer();
				}
			}
			else if(evt.getSource()==btEnregistrerSous&&saisieOk)
			{
				enregistrerSous();
			}
			else
			{
				JOptionPane.showMessageDialog( this,"Enregistrement annulé: il y a des erreurs de saisie dans la table","Erreur de saisie", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	/**
	 * ne fait rien de plus
	 * @see java.awt.event.ContainerListener#componentAdded(java.awt.event.ContainerEvent)
	 */
	public void componentAdded(ContainerEvent e){/*do nothing*/}
	/**
	 * Implémentation, vérifie la saisie effectuée dans une cellule
	 * @see java.awt.event.ContainerListener#componentRemoved(java.awt.event.ContainerEvent)
	 */
	public void componentRemoved(ContainerEvent e)
	{
		//déclenché quand on a rentré une nouvelle valeur
		message.setText("");
		modif = true;
		//On cherche quel composant a été modifié:
		int x = table.getEditingRow();
		int y = table.getEditingColumn();

		String valeur = ((JTextField) table.getEditorComponent()).getText();
		boolean saisieOk=majTable(valeur,x,y);
		if(!saisieOk){table.setValide(x, y, false);}
		else{table.setValide(x,y,true);}
	}
	
	/**
	 * Met à jour les données à partir de la cellule x, y
	 * @param valeur valeur de la cellule
	 * @param x ligne
	 * @param y colonne
	 * @return true si valeur est valide
	 */
	private boolean majTable(String valeur, int x, int y)
	{
		boolean retour=  false;
		
		switch (y)
		{
			case 1:
				//colonne 2
				if (valeur.length()==1)
				{
					//c'est un caractère
					donnees[x][1] = valeur;
					char c = valeur.charAt(0);
					donnees[x][2] = Short.toString((short) c);
					retour = true;
				}
				else
				{
					//JOptionPane jopErreur = new JOptionPane();
					JOptionPane.showMessageDialog( this,"Vous devez saisir un seul caractère","Erreur de saisie", JOptionPane.ERROR_MESSAGE);
				}
				break;
				
			case 2:
				//colonne 3
				try
				{
					donnees[x][1]=Character.toString( ((char) Integer.parseInt(valeur)));
					donnees[x][2]=valeur;
					retour = true;
				}
				catch(NumberFormatException nfe)
				{
					JOptionPane.showMessageDialog( this,"Vous devez saisir uniquement un entier","Erreur de saisie", JOptionPane.ERROR_MESSAGE);
					table.setEditingColumn(y);
					table.setEditingRow(x);
				}
				break;
		}
		table.repaint();
		return retour;
	}
	
	/**
	 * Enregistre la table braille dans les fichiers fichierTable et fichierTableConv
	 */
	private void enregistrer()
	{
		try
		{
			int i;
			FileWriter raf = new FileWriter(fichierTable);
			FileWriter rac = new FileWriter(fichierTableConv);
			raf.write(Nat.getLicence("<!--\n","-->\n"));
			rac.write(Nat.getLicence("<!--\n","-->\n"));
			for (i=0; i<donnees.length; i++)//length - 1 car il y a une ligne en plus je sais pas pq
			{
				if (donnees[i][1].equals("\""))
				{
					raf.write("<!ENTITY " + donnees[i][0] + " \"&quot;\">\n");
					rac.write("<!ENTITY " + donnees[i][0].replaceFirst("pt", "pte") + " \"&quot;\">\n");
				}
				else if(donnees[i][1].equals("'"))
				{
					raf.write("<!ENTITY " + donnees[i][0] + " \"&apos;\">\n");
					rac.write("<!ENTITY " + donnees[i][0].replaceFirst("pt", "pte") + " \"&apos;\">\n");
				}
				else if(donnees[i][1].equals("<"))
				{
					raf.write("<!ENTITY " + donnees[i][0] + " \"&lt;\">\n");
					rac.write("<!ENTITY " + donnees[i][0].replaceFirst("pt", "pte") + " \"&lt;\">\n");
				}
				else if(donnees[i][1].equals(">"))
				{
					raf.write("<!ENTITY " + donnees[i][0] + " \"&gt;\">\n");
					rac.write("<!ENTITY " + donnees[i][0].replaceFirst("pt", "pte") + " \"&gt;\">\n");
				}
				else if(donnees[i][1].equals("&"))
				{
					raf.write("<!ENTITY " + donnees[i][0] + " \"&amp;\">\n");
					rac.write("<!ENTITY " + donnees[i][0].replaceFirst("pt", "pte") + " \"&amp;\">\n");
				}
				else
				{
					raf.write("<!ENTITY " + donnees[i][0] + " \"&#" + donnees[i][2] + ";\">\n");
					rac.write("<!ENTITY " + donnees[i][0].replaceFirst("pt", "pte") + " \"&#" + donnees[i][2] + ";\">\n");
				}
			}
			raf.close();
			rac.close();
			message.setText("<html><br><p>Table enregistrée</p></html>");
			nomTable.setText("<html><h2>Table " + nomCourt + "</h2></html>");
			modif=false;
		}
		catch (IOException e)
		{
			System.err.println("erreur dans: " + e);
			message.setText("<html><br><p color=\"red\">Erreur lors de l'enregistrement</p></html>");
		}
	}
	
	/**
	 * Enregistre une nouvelle table braille et vérifie qu'elle n'existe pas déjà.
	 *
	 */
	private void enregistrerSous()
	{
		//String nomTable = ConfigNat.getCurrentConfig().getTableBraille();
		
		//on demande le nom de la nouvelle table
		String nomNewTable = (String)JOptionPane.showInputDialog(
									this,
									"Nom de la nouvelle table :",
									"Table actuelle : "+nomCourt,
									JOptionPane.PLAIN_MESSAGE,null,null,
									nomCourt);
 		if (!nomNewTable.equals(""))
        {    
 			String nomNewTableComplet =ConfigNat.getUserBrailleTableFolder()+"/"+nomNewTable+".ent";
		    //on vérifie qu'elle n'existe pas déjà
			int reponse = JOptionPane.YES_OPTION ;
			if (new File(nomNewTableComplet).exists())
			{
				reponse = JOptionPane.showConfirmDialog(
				    this,
				    "La table braille\n"+nomNewTable+"\nexiste déjà,\nvoulez-vous l'écraser ?",
				    "Confirmation",
				    JOptionPane.YES_NO_OPTION);
			}
	
			
		    if (reponse == JOptionPane.YES_OPTION)
		    {
				nomFichierTable = nomNewTableComplet;
				this.fichierTable = nomNewTableComplet;
				File f = new File(nomNewTableComplet);				
				this.fichierTableConv = new File(f.getParent()).getParent()+"/tablesEmbosseuse/" + f.getName();
				nomCourt = nomNewTable;
				btEnregistrer.setEnabled(true);
				enregistrer();
		    }
        }
	}
	
	/**
	 * Charge les données du fichier fichierTable dans le tableau des données pour la table.
	 * @return true si fichier valide, false sinon
	 */
	private boolean afficheTable()
	{
	    boolean retour = true;
		try
	      {
		      RandomAccessFile raf = new RandomAccessFile(fichierTable, "r");
		      String ligne;
		      String[] enregistrement;
		      int i=1;
		      
		      ligne = raf.readLine();
		      //on cherche le début des entitées
		      while(ligne!=null && !ligne.startsWith("<!ENTITY"))
		      {
		    	  ligne = raf.readLine();
		      }
		      if (ligne==null)
		      {
		    	  System.err.println("Le fichier" + fichierTable + "n'est pas un fichier valide");
		    	  message.setText("<html><br><p color=\"red\">Le fichier" + fichierTable + "n'est pas un fichier valide</p></html>");
		    	  retour =false;
		      }
		      else
		      {
		    	  donnees = new String[64][3];
		    	  enregistrement = ligne.split(" ");
		    	  donnees[0][0] = enregistrement[1];

		    	  if(!enregistrement[2].startsWith("\"&#"))
		    	  {
		    		  if (enregistrement[2].startsWith("\"&apos;"))
		    		  {
		    			  donnees[0][1] = "'";
		    			  donnees[0][2] = "39";
		    		  }
		    		  else if (enregistrement[2].startsWith("\"&quot;"))
		    		  {
		    			  donnees[0][1] = "\"";
		    			  donnees[0][2] = "34";
		    		  }
		    		  else if (enregistrement[2].startsWith("\"&lt;"))
		    		  {
		    			  donnees[0][1] = "<";
		    			  donnees[0][2] = "60";
		    		  }
		    		  else if (enregistrement[2].startsWith("\"&gt;"))
		    		  {
		    			  donnees[0][1] = ">";
		    			  donnees[0][2] = "62";
		    		  }
		    		  else
		    		  {
		    			  donnees[0][1] = "&";
		    			  donnees[0][2] = "38";
		    		  }
		    	  }
		    	  else
		    	  {
			    	  donnees[0][1] = Character.toString((char)(Integer.parseInt(enregistrement[2].substring(3, enregistrement[2].length()-3))));
			    	  donnees[0][2] = enregistrement[2].substring(3, enregistrement[2].length()-3);
		    	  }

			      while ( (ligne = raf.readLine()) != null && i<donnees.length)
				  	{
			    	  enregistrement = ligne.split(" ");
			    	  donnees[i][0] = enregistrement[1];
			    	  if(!enregistrement[2].startsWith("\"&#"))
			    	  {
			    		  if (enregistrement[2].startsWith("\"&apos;"))
			    		  {
			    			  donnees[i][1] = "'";
			    			  donnees[i][2] = "39";
			    		  }
			    		  else if (enregistrement[2].startsWith("\"&quot;"))
			    		  {
			    			  donnees[i][1] = "\"";
			    			  donnees[i][2] = "34";
			    		  }
			    		  else if (enregistrement[2].startsWith("\"&lt;"))
			    		  {
			    			  donnees[i][1] = "<";
			    			  donnees[i][2] = "60";
			    		  }
			    		  else if (enregistrement[2].startsWith("\"&gt;"))
			    		  {
			    			  donnees[i][1] = ">";
			    			  donnees[i][2] = "62";
			    		  }
			    		  else
			    		  {
			    			  donnees[i][1] = "&";
			    			  donnees[i][2] = "38";
			    		  }
			    	  }
			    	  else
			    	  {
				    	  donnees[i][1] = Character.toString((char)(Integer.parseInt(enregistrement[2].substring(3, enregistrement[2].length()-3))));
				    	  donnees[i][2] = enregistrement[2].substring(3, enregistrement[2].length()-3);
			    	  }
			    	  i++;
			  	    }
		      }
		      raf.close();
	       }
		   catch (IOException e)
		   {
			   System.err.println("erreur dans: " + e);
			   message.setText(":Erreur d'entrée/sortie lors du chargement");
		   }
		   catch (NumberFormatException e)
		   {
			   System.err.println("La table Braille n'est pas valide: " + e);
			   message.setText("<html><br> <p color=\"red\">La table Braille n'est pas valide</p></html>");
		   }
		   return retour;
	}
}
