package ftp_client;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;

// Fenetre principale
public class MainWindow {

	/* Controls */
	private Shell shell = null;
	public Shell getShell(){ return shell; }
	
	private SashForm sashForm = null;
	private SashForm sashForm1 = null;
	
	private StyledText traceText = null;
	public StyledText getTrace(){ return traceText; }
		
	private Tree localTree = null;
	public Tree getLocalTree(){ return localTree; }
	private Tree remoteTree = null;
	public Tree getRemoteTree(){ return remoteTree; }
	
	private Tree localFilesTree = null;
	public Tree getLocalFilesTree(){ return localFilesTree; }
	private Tree remoteFilesTree = null;
	public Tree getRemoteFilesTree(){ return remoteFilesTree; }
	
	private Composite composite = null;
	private Composite composite2 = null;
	
	private Text TBlocal = null;
	public String getCurrentLocalDirectory(){ return TBlocal.getText(); }
	private Text TBremote = null;
	
	private Table table = null;

	/* About Box */
	AboutBox form_about;
	
	/* Constructor */
	public MainWindow(){
		createShell();
		createListener();
		initControls();
		shell.setSize(new Point(800, 600));
		
		Display.getDefault().asyncExec(new Runnable() {
            public void run() {
            	changeLocalDirectory(null, true);
			}
		});
				
		shell.open();
	}
	public boolean isDisposed(){ return shell.isDisposed(); }
	
	/* Form Init */
	public void initControls(){
		if(remoteTree==null || TBremote==null) return;
		Display.getDefault().asyncExec(new Runnable() {public void run(){ 
			if(!remoteTree.isDisposed()) remoteTree.removeAll();
			if(!TBremote.isDisposed()) TBremote.setText("Aucune connexion");
		}});
	}
	
	private void createShell() {
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 3;
		shell = new Shell(Display.getDefault(), SWT.MAX | SWT.MIN | SWT.RESIZE);
		createMenu();
		shell.setLayout(new FillLayout());
		createMainView();
		shell.setText("Client FTP");
	}
	
	Menu menuBar, connectionMenu, quickMenu, aboutMenu;
	MenuItem connectionMenuHeader, quickMenuHeader, aboutMenuHeader;
	MenuItem connectionManagerItem, disconnectionItem, quickItem, aboutItem;

	private void createMenu(){
		menuBar = new Menu(shell, SWT.BAR);
		
		connectionMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
		connectionMenuHeader.setText("Connexion");
		
		connectionMenu = new Menu(shell, SWT.DROP_DOWN);
		connectionMenuHeader.setMenu(connectionMenu);
		
		quickItem = new MenuItem(connectionMenu, SWT.CASCADE);
		quickItem.setText("Connexion rapide");
		quickMenu = new Menu(shell, SWT.DROP_DOWN);
		quickItem.setMenu(quickMenu);
		
		connectionManagerItem = new MenuItem(connectionMenu, SWT.PUSH);
		connectionManagerItem.setText("Gérer les comptes FTP");
		connectionManagerItem.addSelectionListener(new org.eclipse.swt.events.SelectionListener(){
			public void widgetDefaultSelected(SelectionEvent arg0) {}

			public void widgetSelected(SelectionEvent arg0) {
				fireShowConnectionManagerListener();
			}				
		});	
		
		disconnectionItem = new MenuItem(connectionMenu, SWT.PUSH);
		disconnectionItem.setText("Déconnexion");
		disconnectionItem.addSelectionListener(new org.eclipse.swt.events.SelectionListener(){
			public void widgetDefaultSelected(SelectionEvent arg0) {}

			public void widgetSelected(SelectionEvent arg0) {
				fireDisconnectListener();
			}				
		});		
		
		aboutMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
		aboutMenuHeader.setText("?");
		
		aboutMenu = new Menu(shell, SWT.DROP_DOWN);
		aboutMenuHeader.setMenu(aboutMenu);
		
		aboutItem = new MenuItem(aboutMenu, SWT.PUSH);
		aboutItem.setText("À propos");
		aboutItem.addSelectionListener(new org.eclipse.swt.events.SelectionListener(){
			public void widgetDefaultSelected(SelectionEvent arg0) {}

			public void widgetSelected(SelectionEvent arg0) {
				if(form_about != null && !form_about.isDisposed()) return;
				form_about = new AboutBox();
			}				
		});		
				
		shell.setMenuBar(menuBar);
	}
	
	// Rafraichir le menu de connexion rapide
	public void refreshQuickMenu(final ArrayList<FTPInfo> ftps){
		Display.getDefault().asyncExec(new Runnable() {
            public void run() {
				
            	// On supprime tous les anciennes connexions rapides du menu
				MenuItem[] mis = quickMenu.getItems();
				for(MenuItem mi : mis)
					mi.dispose();
				
				if(ftps.size() == 0){ // Si aucun compte, ajouter une fausse connexion rapide indiquant qu'il n'y a aucun compte
					MenuItem mi = new MenuItem(quickMenu, SWT.PUSH);
					mi.setText("Aucune connexion enregistrée");
				}else{ // Sinon ajouter les comptes
					MenuItem mi;
					for(FTPInfo fi : ftps){
						mi = new MenuItem(quickMenu, SWT.PUSH);
						mi.setText(fi.user+"@"+fi.address+":"+fi.port);
						final FTPInfo ffi = fi;
						mi.addSelectionListener(new org.eclipse.swt.events.SelectionListener(){
							public void widgetDefaultSelected(SelectionEvent arg0) {}
			
							public void widgetSelected(SelectionEvent arg0) {
								fireConnectListener(ffi); // Lorsqu'on clique dessus, demander la connexion
							}				
						});
					}
				}
            }
        });
	}

	private void createMainView() {
		sashForm = new SashForm(shell, SWT.VERTICAL);
		traceText = new StyledText(sashForm, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		traceText.setEditable(false);
		traceText.addMouseListener(new org.eclipse.swt.events.MouseAdapter() {
			public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
				if(e.button != 3) return;
				Menu mn = new Menu(traceText);
				MenuItem mi;
				mi = new MenuItem(mn, SWT.PUSH);		
				mi.setText("Effacer le texte");					
				mi.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
					public void widgetSelected(SelectionEvent event) {
						traceText.setText("");
					}
				});
				Point pt = new Point (e.x, e.y);
				pt = traceText.toDisplay (pt);
				mn.setLocation (pt.x, pt.y);
				mn.setVisible (true);
			}
		});
		createLocalRemoteView();
		table = new Table(sashForm, SWT.SINGLE | SWT.FULL_SELECTION);
		table.setHeaderVisible(true);
		table.setLinesVisible(false);
	    for (int i = 0; i < 6; i++)
	      new TableColumn(table, SWT.NONE);
	    table.getColumn(0).setText("Fichier");
	    table.getColumn(1).setText("<>");
	    table.getColumn(2).setText("Destination");
	    table.getColumn(3).setText("Vitesse");
	    table.getColumn(4).setText("Progression");
	    table.getColumn(5).setText("Transfert");
	    for (int i = 0; i < 6; i++)
	    	table.getColumn(i).setWidth(175);
	    table.getColumn(1).setWidth(40);
	    table.getColumn(3).setWidth(100);
	    table.getColumn(4).setWidth(150);
	    table.addKeyListener(new org.eclipse.swt.events.KeyAdapter() {
			public void keyPressed(org.eclipse.swt.events.KeyEvent e) {
				if(table.getSelectionCount() == 0) return;
				
				((TransfertItem)table.getSelection()[0]).keyDown(e);
			}
		});	    
	}

	/* Create both view */
	private void createLocalRemoteView() {
		sashForm1 = new SashForm(sashForm, SWT.HORIZONTAL);
		createLocalView();
		createRemoteView();
	}
	
	/* FTP Files View */
	private void createRemoteView(){
		composite2 = new Composite(sashForm1, SWT.NONE);
		composite2.setLayout(null);
		TBremote = new Text(composite2, SWT.NONE);
		TBremote.setEditable(false);
		TBremote.setBounds(new Rectangle(19, 50, 367, 79));
		TBremote.setLocation(2,2);
		TBremote.setSize(composite2.getSize().x, 20);
		remoteTree = new Tree(composite2, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
		remoteTree.setLocation(TBremote.getLocation().x, TBremote.getLocation().y + TBremote.getSize().y + 1);
		remoteTree.setHeaderVisible(true);
		
		
		TreeColumn column1 = new TreeColumn(remoteTree, SWT.LEFT);
		column1.setText("Nom");
		column1.setWidth(200);
		TreeColumn column2 = new TreeColumn(remoteTree, SWT.LEFT);
		column2.setText("Taille");
		column2.setWidth(70);
		TreeColumn column3 = new TreeColumn(remoteTree, SWT.LEFT);
		column3.setText("Date de modification");
		column3.setWidth(100);
		TreeColumn column4 = new TreeColumn(remoteTree, SWT.LEFT);
		column4.setText("Utilisateur (groupe)");
		column4.setWidth(100);
	}
	
	/* Local Files View */
	private void createLocalView() {
		composite = new Composite(sashForm1, SWT.NONE);
		composite.setLayout(null);
		TBlocal = new Text(composite, SWT.NONE);
		TBlocal.setEditable(false);
		TBlocal.setBounds(new Rectangle(19, 50, 367, 79));
		TBlocal.setLocation(2,2);
		TBlocal.setSize(composite.getSize().x, 20);
		localTree = new Tree(composite, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
		localTree.setLocation(TBlocal.getLocation().x, TBlocal.getLocation().y + TBlocal.getSize().y + 1);
		localTree.setHeaderVisible(true);
		
		
		TreeColumn column1 = new TreeColumn(localTree, SWT.LEFT);
		column1.setText("Nom");
		column1.setWidth(200);
		TreeColumn column2 = new TreeColumn(localTree, SWT.LEFT);
		column2.setText("Taille");
		column2.setWidth(70);
		TreeColumn column3 = new TreeColumn(localTree, SWT.LEFT);
		column3.setText("Date de modification");
		column3.setWidth(100);
	
	}
	
	FileTreeItem lastRmtCurrent = null; // Dernier repertoire distant courant
	FileTreeItem lastLclCurrent = null; // Dernier repertoire local courant
	void createListener(){
		
		/* Table */
		table.addMouseListener(new org.eclipse.swt.events.MouseAdapter() {
			public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
				TransfertItem ee = (TransfertItem) ((Table)e.getSource()).getItem(new Point(e.x, e.y));
				if(ee==null) return;
				
				if(e.button == 3) ee.rightClick(e);
			}
		});
		
		/* Remote */
		remoteTree.addTreeListener(new org.eclipse.swt.events.TreeAdapter() {   
			public void treeExpanded(org.eclipse.swt.events.TreeEvent e) {    
				final FileTreeItem ee = (FileTreeItem) e.item;
				changeRemoteDirectory(ee, true);
			}
			public void treeCollapsed(org.eclipse.swt.events.TreeEvent e) {
				FileTreeItem ee = (FileTreeItem) e.item;
				ee.removeAll();
				new FileTreeItem(shell, ee, new String[] { "Chargement..." });
				
				if(lastRmtCurrent!=null && (lastRmtCurrent==ee || lastRmtCurrent.isDisposed())){
					if(ee.getParentItem()!=null) changeRemoteDirectory((FileTreeItem)ee.getParentItem(), false);
					else changeRemoteDirectory(null, false);
				}
			}
		});
		remoteTree.addMouseListener(new org.eclipse.swt.events.MouseAdapter() {
			public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
				if(!connected) return; 

				FileTreeItem ee = (FileTreeItem)((Tree)e.getSource()).getItem(new Point(e.x, e.y));
				
				if(ee==null){
					if(e.button != 3) return;

					Menu mn = new Menu((Tree)e.getSource());
					MenuItem mi = new MenuItem(mn, SWT.PUSH);				
					mi.setText("Rafraîchir");
					mi.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
						public void widgetSelected(SelectionEvent event) {
							changeRemoteDirectory(null, true);
						}
					});

					mi = new MenuItem(mn, SWT.PUSH);		
					mi.setText("Nouveau dossier");
					mi.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
						public void widgetSelected(SelectionEvent event) {
							new Thread(){
								public void run(){
									AskWindow aw = new AskWindow("Nouveau dossier", "Veuillez indiquer le nom du nouveau dossier :", "Nouveau Dossier");
									String name = aw.Ask();
									if(name == null) return;
									final boolean isOk = fireMakeDirListener(name);
									Display.getDefault().asyncExec(new Runnable() {
							            public void run() {
							            	if(isOk) changeRemoteDirectory(null, true);
							            }
									});
								}
							}.start();
						}
					});

					Point pt = new Point (e.x, e.y);
					pt = remoteTree.toDisplay (pt);
					mn.setLocation (pt.x, pt.y);
					mn.setVisible (true);

				}else{
					if(e.button == 1 && e.count == 2) ee.dbleClick();
					else if(e.button == 3)	ee.rightClick(MainWindow.this, e);
				}
			}
		});
		remoteTree.addKeyListener(new org.eclipse.swt.events.KeyAdapter() {
			public void keyPressed(org.eclipse.swt.events.KeyEvent e) {
				if(!connected) return;
				
				if(e.keyCode == SWT.F5 && TBremote.getText().equals("/")){ changeRemoteDirectory(null, true); return; }
				
				if(remoteTree.getSelectionCount() == 0) return;
				
				((FileTreeItem)remoteTree.getSelection()[0]).keyDown(MainWindow.this, e);
			}
		});
		
		/* Local */
		localTree.addTreeListener(new org.eclipse.swt.events.TreeAdapter() {   
			public void treeCollapsed(org.eclipse.swt.events.TreeEvent e) {    
				FileTreeItem ee = (FileTreeItem) e.item;
				ee.removeAll();
				new FileTreeItem(shell, ee, new String[] { "Chargement..." });
				if(lastLclCurrent==ee || lastLclCurrent == null || lastLclCurrent.isDisposed()){
					if(ee.getParentItem()!=null) changeLocalDirectory((FileTreeItem)ee.getParentItem(), false);
					else changeLocalDirectory(null, false);
				}
			}
			public void treeExpanded(org.eclipse.swt.events.TreeEvent e) {
				FileTreeItem ee = (FileTreeItem) e.item;
				changeLocalDirectory(ee, true);
			}
		});
		localTree.addMouseListener(new org.eclipse.swt.events.MouseAdapter() {
			public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
				FileTreeItem ee = (FileTreeItem)((Tree)e.getSource()).getItem(new Point(e.x, e.y));
				
				if(ee==null){
					if(e.button != 3) return;
					
					Menu mn = new Menu((Tree)e.getSource());
					MenuItem mi = new MenuItem(mn, SWT.PUSH);				
					mi.setText("Rafraichir");
					mi.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
						public void widgetSelected(SelectionEvent event) {
									Display.getDefault().asyncExec(new Runnable() {
							            public void run() {
							            	changeLocalDirectory(null, true);
										}
									});
						}
					});
					mi = new MenuItem(mn, SWT.PUSH);		
					mi.setText("Nouveau dossier");
					mi.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
						public void widgetSelected(final SelectionEvent event) {
							new Thread(){
								public void run(){
									AskWindow aw = new AskWindow("Nouveau dossier", "Veuillez indiquer le nom du nouveau dossier :", "Nouveau Dossier");
									String name = aw.Ask();
									if(name == null) return;
									final boolean isOk = Misc.makeDir(null, name);
									Display.getDefault().asyncExec(new Runnable() {
							            public void run() {
							            	if(isOk) changeLocalDirectory(null, true);
							            }
									});
								}
							}.start();
						}
					});
					
					Point pt = new Point(e.x, e.y);
					pt = localTree.toDisplay (pt);
					mn.setLocation (pt.x, pt.y);
					mn.setVisible (true);

				}else{
					if(e.button == 1 && e.count == 2) ee.dbleClick();
					else if(e.button == 3)	ee.rightClick(MainWindow.this, e);
				}
			}
		});
		localTree.addKeyListener(new org.eclipse.swt.events.KeyAdapter() {
			public void keyPressed(org.eclipse.swt.events.KeyEvent e) {
				if(e.character == SWT.F5 && TBlocal.getText().equals("/")){ changeLocalDirectory(null, true); return; }
				
				if(localTree.getSelectionCount() == 0) return;
				
				((FileTreeItem)localTree.getSelection()[0]).keyDown(MainWindow.this, e);
			}
		});
		
		/* Resize */
		composite.addControlListener(new org.eclipse.swt.events.ControlAdapter() {
			public void controlResized(org.eclipse.swt.events.ControlEvent e) {
				try{
					TBlocal.setSize(composite.getSize().x, TBlocal.getSize().y);
					localTree.setSize(composite.getSize().x, composite.getSize().y - localTree.getLocation().y);
				}catch(Exception ex){ex.printStackTrace();}
			}
		});
		composite2.addControlListener(new org.eclipse.swt.events.ControlAdapter() {
			public void controlResized(org.eclipse.swt.events.ControlEvent e) {
				try{
					TBremote.setSize(composite2.getSize().x, TBremote.getSize().y);
					remoteTree.setSize(composite2.getSize().x, composite2.getSize().y - remoteTree.getLocation().y);
				}catch(Exception ex){ex.printStackTrace();}
			}
		});
	}
	
	
	/* Change Directory */
	// Changer le repertoire local courant, et le rafraichir ou non
	public void changeLocalDirectory(FileTreeItem ee, boolean refresh) {
		// De base on recupere les fichiers de la racine, sauf si on precise un FileTreeItem
		String fullpath = "";
		if(ee!=null) fullpath = ee.getPath(true);
		TBlocal.setText(fullpath); // On affiche le repertoire courant dans un label
		if(refresh){ // Si on rafraichi, on ajoute les fichiers a l'element de l'arbre
			if(ee!=null && !ee.isDisposed()) FormFuncs.addFilesToTree(shell, ee, fullpath);
			if(ee==null) FormFuncs.addFilesToTree(shell, localTree, fullpath);
		}
    	// On remet la couleur par defaut a l'ancien repertoire courant
		if(lastLclCurrent != null && !lastLclCurrent.isDisposed()) lastLclCurrent.setGlobalBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
		// Et on met une couleur particuliere au nouveau repertoire courant
		if(ee!=null && !ee.isDisposed()) ee.setGlobalBackground(new org.eclipse.swt.graphics.Color(Display.getDefault(), 220, 220, 255));
		// On stock le FileTreeItem courant
		lastLclCurrent = ee;
		
		// Avec GTK, le removeAll() du rafraichissement ferme l'element, il faut le reouvrir
		if(refresh && ee!=null && !ee.isDisposed()) ee.setExpanded(true);
	}
	
	public void changeRemoteDirectory(final FileTreeItem ee, final boolean refresh) {
		// De base on recupere les fichiers de la racine, sauf si on precise un FileTreeItem
		String fullpath = "/";
		if(ee!=null) fullpath = ee.getPath(true);

		final String ffullpath = fullpath;
		new Thread(){
			public void run(){
				try {
					// On demande a changer de repertoire
					if(!fireChangeDirListener(ffullpath)) throw new Exception("Impossible de changer de dossier");
					
					// On recupere les fichiers du repertoire
					ArrayList<FTPFile> fes = null;
					if(refresh) fes = fireGetFilesListener(null);
					final ArrayList<FTPFile> ffes = fes;
					
					Display.getDefault().asyncExec(new Runnable() {
			            public void run() {
			            	TBremote.setText(ffullpath); // On affiche le repertoire courant dans un label
			            	
			            	if(refresh){ // Si on rafraichi, on ajoute les fichiers a l'element de l'arbre
			            		if(ee!=null && !ee.isDisposed()) FormFuncs.addFTPFilesToTree(shell, ee, ffes); 		
			            		if(ee==null) FormFuncs.addFTPFilesToTree(shell, remoteTree, ffes);
			            	}
			            	// On remet la couleur par defaut a l'ancien repertoire courant
			            	if(lastRmtCurrent != null && !lastRmtCurrent.isDisposed()) lastRmtCurrent.setGlobalBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
			        		// Et on met une couleur particuliere au nouveau repertoire courant
			            	if(ee!=null && !ee.isDisposed()) ee.setGlobalBackground(new org.eclipse.swt.graphics.Color(Display.getDefault(), 220, 220, 255));
			        		// On stock le FileTreeItem courant
			            	lastRmtCurrent = ee;
			        		
			            	// Avec GTK, le removeAll() du rafraichissement ferme l'element, il faut le reouvrir
			        		if(refresh && ee!=null && !ee.isDisposed()) ee.setExpanded(true); // removeAll may collapse TreeItem
			            }
			        });
					
				} catch (Exception ex) { // Si on a pas pu acceder au dossier, alors on dit qu'il n'y a aucun fichier dedans
					Display.getDefault().asyncExec(new Runnable() {
			            public void run() {
			            	if(ee!=null && !ee.isDisposed()){
			            		FormFuncs.addFTPFilesToTree(shell, ee, null);
			            		ee.setExpanded(true);
			            	}
			            	if(ee==null) FormFuncs.addFTPFilesToTree(shell, remoteTree, null);
			            }
					});
				}
			}
		}.start();
	}
	
	/* Add Transfert */
	// Ajout d'un transfert (creation d'un TransfertItem a partir d'une Task)
	void addTransfert(Task tsk){
		final TransfertItem ti = new TransfertItem(table, tsk);
		// On ecoute si le TransfertItem veut etre rafraichi
		ti.addUpdateTransfertItemListener(updateTransfertListener);
		// Lorsque la tache se detruit, il ne faut plus la rafraichir
		ti.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				FormFuncs.TItoUpdate.remove(ti);
			}
		});
		// De base une tache est automatique
		tsk.setAuto(true);
	}
	// Appele lorsque un TransfertItem demande a etre rafraichi
	TransfertItem.UpdateTransfertItemListener updateTransfertListener = new TransfertItem.UpdateTransfertItemListener() {
		public void wantToBeUpdated(TransfertItem sender, boolean yes) {
			if(yes){ // Si il veut l'etre...
				if(!FormFuncs.TItoUpdate.contains(sender)){ // ...et qu'il n'est pas deja dans la liste des TransfertItem a rafraichir, alors
					FormFuncs.TItoUpdate.add(sender); // L'ajouter a la liste
					FormFuncs.updateAllTransferts(shell, table); // Et lancer le rafraichissement
				}
			}else	FormFuncs.TItoUpdate.remove(sender); // Sinon le retirer
		}
	};

	/* Change some things if FTP connect or disconnect */
	// Quand le FTP se connecte, on change quelques elements
	boolean connected;
	public void Connected(){
		connected = true;
		Display.getDefault().asyncExec(new Runnable() {
            public void run() {
		TBremote.setText("/");
            }
		});
	}
	// Quand le FTP se deconnecte, on reinitialise tout
	public void Disconnected(){
		connected = false;
		initControls();
	}
	
	/* Directory Renamed -> refresh view */
	// Un dossier a ete renommer, il faut rafraichir l'arbre
	public void directoryRenamed(final FileTreeItem me) {
		Display.getDefault().asyncExec(new Runnable() {
            public void run() {
            	if(me.file instanceof FTPFile) changeRemoteDirectory(me, me.getExpanded());
            	else if(me.file instanceof File ) changeLocalDirectory (me, me.getExpanded());
            }
		});
	}
	
	/* Communicate with the FTP connection */
	// Ecouteur pour les communications FTP
	public interface FTPCommandsListener {
		void showConnectionManager();	
		void connect(FTPInfo fi);
		void disconnect();
		ArrayList<FTPFile> getFiles(String path);
		boolean changeDir(String path);
		boolean makeDir(String path);
	}
	
	private final Collection<FTPCommandsListener> ftpCommandsListeners = new ArrayList<FTPCommandsListener>();
	
	public void addFTPCommandsListener(FTPCommandsListener listener) {
	  ftpCommandsListeners.add(listener);
	}	
	public void removeFTPCommandsListener(FTPCommandsListener listener) {
	  ftpCommandsListeners.remove(listener);
	}

	protected boolean fireChangeDirListener(String path) {
	  boolean allOk = true;
	  for(FTPCommandsListener listener : ftpCommandsListeners)
		   if(!listener.changeDir(path)) allOk = false;
	  return allOk;
	}

	protected boolean fireMakeDirListener(String path) {
	  boolean allOk = true;
	  for(FTPCommandsListener listener : ftpCommandsListeners)
		   if(!listener.makeDir(path)) allOk = false;
	  return allOk;
	}

	protected void fireShowConnectionManagerListener() {
	  for(FTPCommandsListener listener : ftpCommandsListeners)
		   listener.showConnectionManager();
	}

	protected void fireConnectListener(FTPInfo fi) {
	  for(FTPCommandsListener listener : ftpCommandsListeners)
		   listener.connect(fi);
	}
	protected void fireDisconnectListener() {
	  for(FTPCommandsListener listener : ftpCommandsListeners)
		   listener.disconnect();
	}
	  
	protected ArrayList<FTPFile> fireGetFilesListener(String path) {
	  ArrayList<FTPFile> files = new ArrayList<FTPFile>(); 
	  for(FTPCommandsListener listener : ftpCommandsListeners)
		   files.addAll(listener.getFiles(path));
	  return files;
	}
	  
}
