/*
 * Samira & Aymeric
 * RTM1
 * 16/11/2004
 * Java - M1 - TP2 - WinZip
 * fichier : SamAymZip.java
 *
 * Ce fichier contient le noyau de notre WinZip : l'interface, le main et
 * les différents listeners associés à notre interface
 */

import java.awt.*;
import javax.swing.table.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.util.zip.*;
import java.util.*;

public class SamAymZip extends JFrame
{ 
    JButton newButton, addfileButton, openButton, adddirButton, zipButton, unzipButton;
    String lastAction="";
    SAZFile notreFichier;
    SAZFile []nosFichiers;
	DefaultTableModel model;
	JTable statusbar;

	public SamAymZip()
	{
		super("SamAymZip 2004 - Powered by Java");
		setSize(450, 250);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		/*
		 * zipContent contient nos divers éléments
		 */
		Container zipContent = this.getContentPane();
		
		/*
		 * Les boutons sont mis dans une ToolBar
		 */
		JToolBar jtb = new JToolBar();
		
		/*
		 * On affiche le Nom, la Taille, la Date de dernier accès et le taux
		 * de compression des fichiers dans une table
		 */
		Object[] columnNames = {"Nom","Taille","Date","Taux compression"};
		
		/*
		 * model va définir notre model pour la table
		 */
		model=new DefaultTableModel(columnNames,0);
		statusbar = new JTable(model);
		
		statusbar.setPreferredScrollableViewportSize(new Dimension(350,150));
        
        /*
         * On définit une scroll bar dans laquelle on va insérer notre table
         * La scrollbar apparaitra automatique lorsque le tableau devient trop
         * grand
         */
        JScrollPane zipScroll = new JScrollPane(statusbar);


		zipContent.setLayout(new FlowLayout());

		/*
		 * La variable notreFichier va contenir des informations utiles sur
		 * le fichier à décompresser
		 */
		notreFichier=new SAZFile();
		
		/*
		 * Création des boutons
		 */	
		newButton = new JButton("NEW");
		addfileButton = new JButton("ADD FILE");
		openButton = new JButton("OPEN");
		adddirButton = new JButton("ADD DIR");
		zipButton = new JButton("ZIP");
		unzipButton = new JButton("UNZIP");

		/* 
		 * Exemple tiré du poly du cours page 221 
		 */
		/*
		 * Le listener associé à openButton s'enclenche lorsqu'on clique sur
		 * le bouton open dans le but de décompresser le fichier.
		 * Lorsque on open un fichier zippé, on voit le contenu dans la table.
		 */
		openButton.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent ae)
				{
					JFileChooser chooser = new JFileChooser();
					
					/*
					 * On utilise le FileFilter pour afficher seulement les
					 * fichiers qui ont une extension .zip dans notre dialog
					 *
					 * ExampleFileFilter est fourni par Sun 
					 * http://www-uxsup.csx.cam.ac.uk/java/jdk-1.2.2/demo/jfc/FileChooserDemo/
					 */
				    ExampleFileFilter filter = new ExampleFileFilter();
					filter.addExtension("zip");
				    filter.setDescription("ZIP files");
					chooser.setFileFilter(filter);

					/*
					 * On interdit la sélection de plusieurs fichiers
					 */
					chooser.setMultiSelectionEnabled(false);
					
					int option = chooser.showOpenDialog(SamAymZip.this);
				
					if (option == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile() != null)
					{
						/*
						 * lastAction va être utile pour savoir ce qui vient d'être fait
						 */
						lastAction="open";
						
						/*
						 * On disable/enable les bons boutons
						 */
						unzipButton.setEnabled(true);
						zipButton.setEnabled(false);
						
						/*
						 * On vide la table
						 */
						vide();
						
						/*
						 * sf contient le fichier sélectionné
						 */
						File sf = chooser.getSelectedFile();
						
						/*
						 * Grâce à myViewZip on affiche dans la table le contenu
						 * de l'archive choisie
						 */
						ourZip oz = new ourZip();
          				oz.myViewZip(sf,SamAymZip.this);
          				
          				/*
          				 * On utilise notreFichier pour enregistrer certaines
          				 * infos sur notre archive.
          				 */
          				notreFichier=new SAZFile();
          				
          				notreFichier.setAbsolutePath(sf.getAbsolutePath());
          				notreFichier.setFileName(sf.getName());
          				
          				setTitle("SamAymZip 2004 - Contenu de " + notreFichier.getFileName());
        			}
				}
			}
		);

		
		/*
		 * Lorsqu'on clique sur ADD FILE
		 * Ce bouton permet d'ajouter seulement des fichiers à notre archive
		 */
		addfileButton.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent ae)
				{
					JFileChooser chooser = new JFileChooser();
					
					/*
					 * La multisélection est possible
					 */
					chooser.setMultiSelectionEnabled(true);
					
					
					int option = chooser.showDialog(SamAymZip.this,"Ajouter");
				
					if (option == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile() != null)
					{
						/*
						 * Si la derniere action a été d'ouvrir une archive, on vide la table
						 */
						if (lastAction == "open") vide();
						
						lastAction = "add";
						
						setTitle("SamAymZip 2004 - Powered by Java");
						
						zipButton.setEnabled(true);
						unzipButton.setEnabled(false);
						
						File[] sf = chooser.getSelectedFiles();

          				if (sf.length > 0)
          				{  
          					/*
          					 * Pour chaque fichier on va enregistrer certaines
          					 * infos grâce à la classe SAZFile
          					 */
          					
          					int debut=0;
          					
          					if (nosFichiers != null)
          					{
          						debut=nosFichiers.length;
          					
          						if (debut > 0) nosFichiers=RedimEtCopie(nosFichiers,sf.length);
          					}
          					else nosFichiers = new SAZFile[sf.length];
          					
	          				for (int i = debut,j=0; i < sf.length+debut; i++,j++)
	          				{
	          					Date lm = new Date(sf[j].lastModified());
	          					
								/*
								 * La fonction ajoute(), ajoute une ligne à la table
								 */
	          					ajoute(sf[j].getName(),sf[j].length(),lm.toString(),"-");
	          					
	          					nosFichiers[i] = new SAZFile();
	          					nosFichiers[i].setFileName(sf[j].getName());
	          					nosFichiers[i].setAbsolutePath(sf[j].getAbsolutePath());
	          				}
	          			}
        			}
				}
			}
		);

		
		/*
		 * Bouton ADD DIR qui permet l'ajout de répertoire seulement
		 */
		adddirButton.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent ae)
				{
					JFileChooser chooser = new JFileChooser();
					chooser.setMultiSelectionEnabled(true);
					
					chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					
					int option = chooser.showDialog(SamAymZip.this,"Ajouter");
				
					if (option == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile() != null)
					{
						if (lastAction == "open") vide();
						
						lastAction = "add";
						
						setTitle("SamAymZip 2004 - Powered by Java");
						
						zipButton.setEnabled(true);
						unzipButton.setEnabled(false);
						
						File[] sf = chooser.getSelectedFiles();

          				if (sf.length > 0)
          				{
          					int debut=0;
          					
          					if (nosFichiers != null)
          					{
          						debut=nosFichiers.length;
          					
          						if (debut > 0) nosFichiers=RedimEtCopie(nosFichiers,sf.length);
          					}
          					else nosFichiers = new SAZFile[sf.length];
          					
	          				for (int i = debut,j=0; i < sf.length+debut; i++,j++)
	          				{
	          					Date lm = new Date(sf[j].lastModified());
	          					
	          					ajoute(sf[j].getName(),sf[j].length(),lm.toString(),"-");
	          					
	          					nosFichiers[i] = new SAZFile();
	          					nosFichiers[i].setFileName(sf[j].getName());
	          					nosFichiers[i].setAbsolutePath(sf[j].getAbsolutePath());
	          				}
	          			}
        			}
				}
			}
		);
		
		
		/*
		 * Le bouton ZIP est enable lorsqu'on est autorisé à zipper
		 */
		zipButton.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent ae)
				{
					int taille=nosFichiers.length;
					File[] filelist = new File[taille];
					for (int i=0; i < taille; i++)
						filelist[i] = new File(nosFichiers[i].getAbsolutePath());

					JFileChooser chooser = new JFileChooser();
					
					// fourni par Sun http://www-uxsup.csx.cam.ac.uk/java/jdk-1.2.2/demo/jfc/FileChooserDemo/
				    ExampleFileFilter filter = new ExampleFileFilter();
					filter.addExtension("zip");
				    filter.setDescription("ZIP files");
					chooser.setFileFilter(filter);
					
					int option;
					do
					{
						option = chooser.showSaveDialog(SamAymZip.this);
					} while (chooser.getSelectedFile() == null);
					
					if (option == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile() != null)
					{
						
						setTitle("SamAymZip 2004 - Powered by Java");

						boolean ok=true;
						
						/*
						 * On teste si le fichier selectionné existe
						 */
						if (chooser.getSelectedFile().exists() == true)
						{
							/*
							 * Si oui on demande à l'utilisateur une confirmation 
							 * de son choix de vouloir le remplacer
							 */
							int reponse = JOptionPane.showConfirmDialog(SamAymZip.this,
									       "Ce fichier existe déjà. Voulez-vous le remplacer ?",
									       "Warning", 
									        JOptionPane.YES_NO_OPTION);
									        
							if (reponse == JOptionPane.YES_OPTION)
								ok=true;
							else
								ok=false;
						}
						
						if (ok == true)
						{
							/*
							 * On donne le choix entre 4 types de compression
							 */
							Object[] possibleValues = { "Meilleure Compression", "Compression normale", "Meilleure rapidité", "Pas de compression" };
							
							Object selectedValue = JOptionPane.showInputDialog(SamAymZip.this, 
							"Choississez un taux de compression", "Options de compression",
							JOptionPane.INFORMATION_MESSAGE, null,
							possibleValues, possibleValues[0]);
							
							int method = ZipOutputStream.DEFLATED;
							int taux;
							
							if (selectedValue.toString() == "Meilleure Compression") taux=Deflater.BEST_COMPRESSION;
							else if (selectedValue.toString() == "Compression normale") taux=Deflater.DEFAULT_COMPRESSION;
							else if (selectedValue.toString() == "Meilleure rapidité") taux=Deflater.BEST_SPEED;
							else if (selectedValue.toString() == "Pas de compression") taux=Deflater.NO_COMPRESSION;
							else taux=Deflater.DEFAULT_COMPRESSION;
							
							/*
							 * On lance la compression
							 */
							ourZip zf = new ourZip();

							zf.myZip(filelist, chooser.getSelectedFile().getAbsolutePath(), taux, method);
							
							/*
							 * Message qui indique la fin de l'opération
							 */
							JOptionPane d = new JOptionPane();
							d.showMessageDialog(SamAymZip.this,"Fichier compressé !","Information",JOptionPane.INFORMATION_MESSAGE);
						}
					}
				}
			}
		);


		
		/*
		 * Bouton UNZIP enable que lorsqu'on a le droit de l'utiliser
		 */
		unzipButton.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent ae)
				{
					/*
					 * On choisit le répertoire où doit être décompressé le fichier
					 */
					JFileChooser chooser = new JFileChooser();
					chooser.setDialogTitle("Extraire vers ...");
					chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					
					int option = chooser.showDialog(SamAymZip.this,"Extraire vers...");
					
					if (option == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile() != null)
					{
						/*
						 * On effectue la décompression
						 */
						ourZip zf = new ourZip();
						zf.myUnZip(notreFichier.getAbsolutePath(),chooser.getSelectedFile().getAbsolutePath());
						
						/*
						 * Message qui indique la fin de l'opération
						 */
						JOptionPane d = new JOptionPane();
						d.showMessageDialog(SamAymZip.this,"Fichier décompressé !","Information",JOptionPane.INFORMATION_MESSAGE);
					}
				}
			}
		);

		
		/*
		 * Bouton NEW qui vide le tableau et remet tout en l'état d'origine
		 */
		newButton.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent ae)
				{
					vide();
					setTitle("SamAymZip 2004 - Powered by Java");
					zipButton.setEnabled(false);
					unzipButton.setEnabled(false);
					nosFichiers=null;
					notreFichier=null;
				}
			}
		);
		

   		/*
   		 * Placement des boutons dans notre ToolBar
   		 */
		jtb.add(newButton);
		jtb.add(addfileButton);
		jtb.add(adddirButton);
		jtb.add(openButton);
		jtb.add(zipButton);
		zipButton.setEnabled(false);
		jtb.add(unzipButton);
		unzipButton.setEnabled(false);
		
		/*
		 * Placement de nos éléments dans le content
		 */
		zipContent.add(jtb,BorderLayout.NORTH);
		zipContent.add(zipScroll,BorderLayout.CENTER);
		
		/*
		 * Placement de notre fenêtre au centre de l'écran
		 */
		setLocationRelativeTo(this.getParent());
	}
	
	

	/*
	 * Fonction main() de notre programme
	 */
	public static void main(String args[])
	{
		SamAymZip SAZ = new SamAymZip();
		SAZ.setVisible(true);
		
	}
	
	
	/*
	 * Fonction vide() permettant de vider notre table 
	 */
	public void vide()
	{
		int i;
		while ((i = model.getRowCount()) != 0)
			model.removeRow(i-1);
	}
	
	/*
	 * Fonction ajoute() permettant d'ajouter une ligne dans notre table
	 */
	public void ajoute(String filename, long taille, String date, String taux)
	{
		Object []tmp = {filename,Long.toString(taille),date,taux};
		model.addRow(tmp);
	}
	
	/*
	 * Fonction RedimEtCopie() qui permet de redimensionner un tableau de
	 * type SAZFile
	 */
	public SAZFile[] RedimEtCopie(SAZFile[] tab1, int length)
	{
		SAZFile[] tab2 = new SAZFile[tab1.length+length];

		/*
		 * On recopie l'ancien tableau dans le nouveau tableau redimensionné
		 */
		for (int i=0; i < tab1.length; i++)
		{
			tab2[i] = new SAZFile();
			tab2[i].setFileName(tab1[i].getFileName());
			tab2[i].setAbsolutePath(tab1[i].getAbsolutePath());
		}
		
		return tab2;
		
	}
		
}


