/*
 * 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.GestionnaireErreur;
import gestionnaires.GestionnaireMajTabBraille;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.KeyStroke;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.ArrayList;
import java.io.IOException;
//import javax.swing.ImageIcon;

import nat.ConfigNat;
import nat.Nat;
/**
 * Fenêtre graphique de configuration des options de NAT
 * @author bruno
 *
 */
public class Configuration extends JFrame implements ActionListener, WindowListener, ComponentListener
{
    /** Pour la sérialisation (non utilisé) */
    private static final long serialVersionUID = 1L;
    /** titre onglet 4 (indice 3) en cas de MEP activée */
    private static final String TAB3_TITLE_MEP = "Niveaux de Titres  ";
    /** titre onglet 4 (indice 3) en cas de MEP désactivée */
    private static final String TAB3_TITLE_NOMEP = "Chaînes à rajouter";
    /** JTabbedPane contenant les onglets de configuration */
    private JTabbedPane onglets = new JTabbedPane();
    /** Onglet de configuration générale */
    private ConfGeneral panGen;
    /** Onglet MEP Avancée (Niveaux de titres OU chaînes à rajouter */
    private ConfMiseEnPageAvancee panMepAvancee;
    /** liste de tous les onglets de configuration */
    private ArrayList<OngletConf> listOnglets = new ArrayList<OngletConf>();
    /** JLabel indiquant la configuration éditée */
    private JLabel lTitreConfig = new JLabel ("<html><h3>Edition de la configuration "
					      + ((ConfigNat.getCurrentConfig().getIsSysConfig())?"(système)":"") 
					      + " : "
					      + ConfigNat.getCurrentConfig().getName() 										
					      + "</h3></html>");
    //private JLabel lInfosConfig  = new JLabel ("<b>"+ConfigNat.getCurrentConfig().getInfos() +"</b>");											
    /** JPanel du titre */
    private JPanel panelTitre = new JPanel();
    /** JPanel conteannt les boutons d'enregistrement */
    private JPanel lesBoutons = new JPanel();
    /** Annule les modifications */
    private JButton btAnnuler = new JButton("Annuler",new ImageIcon("ui/icon/edit-undo.png"));
    /** Enregistre les modifications dans la configuration courante */
    private JButton btEnregistrer = new JButton("Enregistrer",new ImageIcon("ui/icon/document-save.png"));
    /** Enregistre les options dans une nouvelle configuration */
    private JButton btEnregistrerSous = new JButton("Enregistrer sous...",new ImageIcon("ui/icon/document-save-as.png"));
    /** Instance de la fenêtre principale de NAT qui a construit l'instance de Configuration */
    private FenetrePrinc fPrinc;
    /** une instance de {@link gestionnaires.GestionnaireMajTabBraille}*/
    private GestionnaireMajTabBraille gmtb;
    /**
     * Constructeur
     * @param fp la fenêtre principale appelant le constructeur
     */
    public Configuration(FenetrePrinc fp)
    {
		super("Configuration de NAT");
		fPrinc = fp;
		addWindowListener(this);
		addComponentListener(this);
		//Ajout d'une action pour quitter la fenêtre avec echap
		Action annuleAction = new AbstractAction() {
			private static final long serialVersionUID = 1L;
			public void actionPerformed(ActionEvent e) {dispose();}};
			
		Action selectOnglet0 = new OngletAction(0);
		Action selectOnglet1 = new OngletAction(1);
		Action selectOnglet2 = new OngletAction(2);
		Action selectOnglet3 = new OngletAction(3);
		Action selectOnglet4 = new OngletAction(4);
		Action selectOnglet5 = new OngletAction(5);
		Action selectOnglet6 = new OngletAction(6);
		

		//input map de l'onglet quand il a le focus
		InputMap im = onglets.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		//ajout des actions à cette inputmap
		im.put(KeyStroke.getKeyStroke("ESCAPE"), "annuleAction");
		im.put(KeyStroke.getKeyStroke('1'), "ong0");
		//im.put(KeyStroke.getKeyStroke('g'), "ong0");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.ALT_DOWN_MASK), "ong0");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_DOWN_MASK), "ong0");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.CTRL_DOWN_MASK), "ong0");
		im.put(KeyStroke.getKeyStroke('2'), "ong1");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.ALT_DOWN_MASK), "ong1");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.CTRL_DOWN_MASK), "ong1");
		im.put(KeyStroke.getKeyStroke('3'), "ong2");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.ALT_DOWN_MASK), "ong2");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.CTRL_DOWN_MASK), "ong2");
		im.put(KeyStroke.getKeyStroke('4'), "ong3");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_4, InputEvent.ALT_DOWN_MASK), "ong3");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_4, InputEvent.CTRL_DOWN_MASK), "ong3");
		im.put(KeyStroke.getKeyStroke('5'), "ong4");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_5, InputEvent.ALT_DOWN_MASK), "ong4");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_5, InputEvent.CTRL_DOWN_MASK), "ong4");
		im.put(KeyStroke.getKeyStroke('6'), "ong5");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_6, InputEvent.ALT_DOWN_MASK), "ong5");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_6, InputEvent.CTRL_DOWN_MASK), "ong5");
		im.put(KeyStroke.getKeyStroke('7'), "ong6");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_7, InputEvent.ALT_DOWN_MASK), "ong6");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_7, InputEvent.CTRL_DOWN_MASK), "ong6");
		//ajout de l'action à la liste des ActionMap de 'onglet
		ActionMap am = onglets.getActionMap();
		am.put("annuleAction", annuleAction);
		am.put("ong0", selectOnglet0);
		am.put("ong1", selectOnglet1);
		am.put("ong2", selectOnglet2);
		am.put("ong3", selectOnglet3);
		am.put("ong4", selectOnglet4);
		am.put("ong5", selectOnglet5);
		am.put("ong6", selectOnglet6);
			
		ConfEmbossage panConfEmbossage = new ConfEmbossage();
		panGen = new ConfGeneral(this);
		panMepAvancee = new ConfMiseEnPageAvancee();
			
		listOnglets.add(panConfEmbossage);
		listOnglets.add(new ConfConversion());
		listOnglets.add(new ConfTranscription());
		listOnglets.add(new ConfMiseEnPage());
		listOnglets.add(panMepAvancee);
		listOnglets.add(new ConfPostTraitement());//,this);
		listOnglets.add(new ConfInterface());
		listOnglets.add(new ConfAvance());
		listOnglets.add(panGen);
			
		gmtb = new GestionnaireMajTabBraille (panGen.getComboTables(), panConfEmbossage.getComboTables());
		onglets.addTab("Général",new ImageIcon("ui/icon/document-properties.png"),panGen,"Regroupe les options de configuration les plus génériques (1)");
		onglets.setMnemonicAt(0, 'g');
		onglets.addTab("Transcription",new ImageIcon("ui/icon/stock_script.png"),listOnglets.get(2),"Regroupe les options pour un paramétrage fin de la transcription (2)");
		//onglets.setMnemonicAt(1, '2');
		onglets.addTab("Mise en page", new ImageIcon("ui/icon/document-page-setup.png"),listOnglets.get(3),"Regroupe les options de mise en page (3)");
		//onglets.setMnemonicAt(2, '3');
		String titreOnglet4;
		if (ConfigNat.getCurrentConfig().getMep()) {titreOnglet4 = TAB3_TITLE_MEP;}
		else {titreOnglet4 = TAB3_TITLE_NOMEP;}
		onglets.addTab(titreOnglet4, new ImageIcon("ui/icon/document-page-setup-advanced.png"),listOnglets.get(4),"Regroupe les options de mise en page avancée (4)");
		//onglets.setMnemonicAt(3, '4');
		onglets.addTab("Embossage",new ImageIcon("ui/icon/stock_print-setup.png"),panConfEmbossage,"Regroupe les options pour l'embossage (5)");
		//onglets.setMnemonicAt(4, '5');
		onglets.addTab("Interface",new ImageIcon("ui/icon/gnome-settings-ui-behavior.png"),listOnglets.get(6),"Regroupe les options de configuration de l'interface graphique (6)");
		//onglets.setMnemonicAt(5, '6');
		/*if(!(ConfigNat.getCurrentConfig().getNiveauLog() < Nat.LOG_DEBUG))
		    {*/
		onglets.addTab("Avancé",new ImageIcon("ui/icon/stock_form-properties.png"),listOnglets.get(7),"Regroupe les réglages techniques avancés de NAT (7)");
			//onglets.setMnemonicAt(6, '7');
		    //}
		//onglets.addTab("Conversion",new ImageIcon("ui/icon/stock_filter-data-by-criteria.png"),listOnglets.get(1),"Regroupe les options des convertisseurs");
	
		btAnnuler.addActionListener(this);
		btAnnuler.getAccessibleContext().setAccessibleName("Bouton annuler");
		btAnnuler.getAccessibleContext().setAccessibleDescription("Valider pour annuler les modifications et fermer la fenêtre");
		btAnnuler.setToolTipText("Annuler et fermer la fenêtre (Alt+z) ou (Alt+F4)");
		//btAnnuler.setMnemonic(KeyEvent.VK_ESCAPE);
		btAnnuler.setMnemonic('z');
			
		if ((!(ConfigNat.getCurrentConfig().getIsSysConfig())) && (ConfigNat.getCurrentConfig().getFichierConf() != null))
		    {
		        btEnregistrer.addActionListener(this);
		    } 
		else {btEnregistrer.setEnabled(false);}
	
		btEnregistrer.getAccessibleContext().setAccessibleName("Bouton enregistrer");
		btEnregistrer.getAccessibleContext().setAccessibleDescription("Valider pour enregister les modifications et fermer la fenêtre");
		btEnregistrer.setToolTipText("Enregistrer et fermer la fenêtre (Alt+s)");
		btEnregistrer.setMnemonic('s');
			
		btEnregistrerSous.addActionListener(this);
		btEnregistrerSous.getAccessibleContext().setAccessibleName("Bouton enregistrer sous");
		btEnregistrerSous.getAccessibleContext().setAccessibleDescription("Valider pour enregistrer la configuration sous un nouveau nom");
		btEnregistrerSous.setToolTipText("Enregistrer la configuration sous un nouveau nom (Alt+n)");
		btEnregistrerSous.setMnemonic('n');
	
		lesBoutons.add(btEnregistrer);
		lesBoutons.add(btEnregistrerSous);
		lesBoutons.add(btAnnuler);
		
		//ajout d'un scrollpane aux onglets pour éviter les pb de résolution sur petites résolutions d'écran
		JScrollPane scrollRes = new JScrollPane (onglets);
		scrollRes.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scrollRes.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		
		//mise en page générale
		panelTitre.add(lTitreConfig);
		add("North", panelTitre);
		add("Center",scrollRes);
		add("South",lesBoutons);
		if(ConfigNat.getCurrentConfig().getMemoriserFenetre())
	    {
	    	int x= ConfigNat.getCurrentConfig().getWidthOptions();
	    	int y=ConfigNat.getCurrentConfig().getHeightOptions();
	    	if(x+y != 0){setPreferredSize(new Dimension(x,y));}
	    }
		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);
	    }
	
    }
    /** Méthode d'accès en lecture à {@link #gmtb}
     * @return {@link #gmtb} 
     **/
    public GestionnaireMajTabBraille getGmtb (){return gmtb ;}
    /**
     * ferme la fenêtre et indique à {@link #fPrinc} que la fenêtre est fermée
     * @see java.awt.Window#dispose()
     */
    @Override
	public void dispose()
    {
		super.dispose();
		fPrinc.setOptionsOuvertes(false);
    }
    /**
     * Gère les actions sur les boutons d'enregistrement
     * @see #btAnnuler
     * @see #btEnregistrer
     * @see #btEnregistrerSous
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent evt)
    {
		if (evt.getSource() == btAnnuler)
	    {
			this.dispose();
			try{this.finalize();}
			catch (Throwable e){e.printStackTrace();}
	    }
		else if (evt.getSource() == btEnregistrer)
		{
			if (saveAll())
		    {
				//String nomConf = ConfigNat.getCurrentConfig().getShortFichierConf();
				ConfigNat.getCurrentConfig().setConfVersion(Nat.CONFS_VERSION);
				ConfigNat.getCurrentConfig().saveFilterConf(ConfigNat.getCurrentConfig().getFichierConf());
				fPrinc.chargeConfigurations();
				if (ConfigNat.getCurrentConfig().getSortieAuto())
					{fPrinc.setSortieAuto(ConfigNat.getCurrentConfig().isReverseTrans());}
				this.dispose();
				try {this.finalize();}
				catch (Throwable e){e.printStackTrace();}
		    }
	    }
		else if(evt.getSource()==btEnregistrerSous)
	    {	
			String nomConf;
			if (ConfigNat.getCurrentConfig().getFichierConf() != null ){nomConf = ConfigNat.getCurrentConfig().getShortFichierConf();}
			else {nomConf = "defaut";}

			//System.out.println("Enregistrere sous / ancienne : "+nomConf);
			//on demande le nom de la nouvelle config
			String nomNewConf = (String)JOptionPane.showInputDialog(this,"Nom de la nouvelle configuration :",
					"Conf. actuelle : "+nomConf, JOptionPane.PLAIN_MESSAGE,null,null,nomConf);
			
			//on vérifie qu'elle n'existe pas déjà
			int reponse = JOptionPane.YES_OPTION ;
			if ((new File(ConfigNat.getUserConfigFolder()+nomNewConf).exists()) && (nomNewConf != null))
		    {
				reponse = JOptionPane.showConfirmDialog(this, "La configuration\n"+nomNewConf+"\nexiste déjà,\nvoulez-vous l'écraser ?",
								"Confirmation",	JOptionPane.YES_NO_OPTION);
		    }

			if ((nomNewConf != null) && (nomNewConf.length() > 0) && (reponse == JOptionPane.YES_OPTION))
		    {    
				try
			    {
					String cpn = (new File(ConfigNat.getUserConfigFilterFolder() + nomNewConf).getCanonicalPath());				
					ConfigNat.getCurrentConfig().setFichierConf(cpn);
	    			    
					if (saveAll())
				    {
						ConfigNat.getCurrentConfig().setIsSysConfig(false);
						ConfigNat.getCurrentConfig().setName(nomNewConf);
						ConfigNat.getCurrentConfig().setConfVersion(Nat.CONFS_VERSION);
						ConfigNat.getCurrentConfig().saveFilterConf(ConfigNat.getCurrentConfig().getFichierConf());
						//				ConfigNat.getCurrentConfig().sauvegarder();
	
						fPrinc.chargeConfigurations();//ajout de la nouvelle conf
						if (ConfigNat.getCurrentConfig().getSortieAuto())
						{fPrinc.setSortieAuto(ConfigNat.getCurrentConfig().isReverseTrans());}
						this.dispose();
						try{this.finalize();}
						catch (Throwable e){e.printStackTrace();}
				    }
			    }
				catch (IOException ioe)
			    {
					JOptionPane.showMessageDialog(this,
					      "Erreur lors de l'enregistrement\n La configuration na pas pu être sauvegardée",
					      "Erreur",JOptionPane.ERROR_MESSAGE);
			    }
		    }
	    }
		else if (evt.getSource()==panGen.getMepBox())
		{
			/*if (panGen.getMepBox().isSelected())
				{getOnglets().setTitleAt(3, TAB3_TITLE_MEP);}
			else
				{getOnglets().setTitleAt(3, TAB3_TITLE_NOMEP);}*/
			//écriture équivalente
			getOnglets().setTitleAt(3,panGen.getMepBox().isSelected()?TAB3_TITLE_MEP:TAB3_TITLE_NOMEP);
			panMepAvancee.enableTabComponents(panGen.getMepBox().isSelected());
	    }
    }
	/** Méthode redéfinie de ComponentListener
	 * Ne fait rien
	 * @param arg0 Le ComponentEvent
	 */
	public void componentHidden(ComponentEvent arg0){/*do nothing*/}
	/** Méthode redéfinie de ComponentListener
	 * Ne fait rien
	 * @param arg0 Le ComponentEvent
	 */
	public void componentMoved(ComponentEvent arg0){/*do nothing*/}
	/** Méthode redéfinie de ComponentListener
	 * Ne fait rien
	 * @param arg0 Le ComponentEvent
	 */
	public void componentShown(ComponentEvent arg0){/*do nothing*/}
	/** Méthode redéfinie de ComponentListener
	 * Mis à jour de l'affichage lors du redimensionement
	 * @param arg0 Le ComponentEvent
	 */
	public void componentResized(ComponentEvent arg0)
	{
		if (getExtendedState()==Frame.MAXIMIZED_BOTH)
		{
		ConfigNat.getCurrentConfig().setMaximizedOptions(true);
		}
		else
		{
		ConfigNat.getCurrentConfig().setWidthOptions(getWidth());
		ConfigNat.getCurrentConfig().setHeightOptions(getHeight());
		ConfigNat.getCurrentConfig().setMaximizedOptions(false);
		}
		repaint();
	}

    /** ne fait rien
     * @see java.awt.event.WindowListener#windowActivated(java.awt.event.WindowEvent)
     */
    public void windowActivated(WindowEvent arg0) {/*do nothing*/}
    /** ne fait rien
     * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent)
     */
    public void windowClosed(WindowEvent arg0) {/*do nothing*/}
    /** 
     * Indique à {@link #fPrinc} que la fenêtre des options est fermée
     * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent)
     */
    public void windowClosing(WindowEvent arg0) {fPrinc.setOptionsOuvertes(false);}
    /** ne fait rien
     * @see java.awt.event.WindowListener#windowDeactivated(java.awt.event.WindowEvent)
     */
    public void windowDeactivated(WindowEvent arg0) {/*do nothing*/}
    /** ne fait rien
     * @see java.awt.event.WindowListener#windowDeiconified(java.awt.event.WindowEvent)
     */
    public void windowDeiconified(WindowEvent arg0) {/*do nothing*/}
    /** ne fait rien
     * @see java.awt.event.WindowListener#windowIconified(java.awt.event.WindowEvent)
     */
    public void windowIconified(WindowEvent arg0) {/*do nothing*/}
    /** ne fait rien
     * @see java.awt.event.WindowListener#windowOpened(java.awt.event.WindowEvent)
     */
    public void windowOpened(WindowEvent arg0) {/*do nothing*/}
    /**
     * Sauvegarde tous les onglets de configuration contenus dans {@link #listOnglets}
     * @return true si les sauvegardes se sont bien déroulées, false sinon
     */
    private boolean saveAll()
    {
		boolean retour = true;
		int i= 0;
		while(i<listOnglets.size()&&retour)
	   	{
			retour = listOnglets.get(i).enregistrer();
			i++;
	    }
		return retour;
    }
    /** 
     * Renvoie le gestionnaire d'erreur utilisé dans la fenêtre principale 
     * @return le gestionnaire d'erreur utilisé dans la fenêtre principale
     * */
	public GestionnaireErreur getGestErreur() {return fPrinc.getGestErreur();}
	
	/**
	 * Accès aux onglets
	 * @return les onglets
	 */
	protected JTabbedPane getOnglets() {return onglets;}

	/**
	 * classe interne pour les actions de positionnement sur onglet
	 * @author bruno
	 *
	 */
	private class OngletAction extends AbstractAction
	{
		/**pour la sérialisation (non utilisé)*/
		private static final long serialVersionUID = 1L;
		/** numéro de l'onglet*/
		private int numOnglet = 0;
		/**
		 * Constructeur
		 * @param i le numéro de l'onglet associé à l'action
		 */
		public OngletAction(int i)
		{
			numOnglet = i;
		}
		/**
		 * Sélectionne l'onglet n° {@link #numOnglet}
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e)
		{
			if(numOnglet<getOnglets().getComponentCount()){
				getOnglets().setSelectedIndex(numOnglet);
				//JPanel selectedTab = (JPanel) getOnglets().getSelectedComponent();
				//selectedTab.getComponent(7).requestFocus();
				}
		}
	}
}
