import java.awt.Panel;
import java.awt.TextField;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Label;
import java.awt.Graphics;
import java.awt.*;
import java.io.File;
import java.net.URL;

/**
 * Class FileZone
 * Date : 26/03/97 20:55
 */
public class FileZone extends Panel {
  public static final byte REMOTE = 0, LOCAL = 1;
  private byte Mode;
  private TextField tf, filtre;
  private MyList l;
  private String filename, title;
  private String [] completion;
  private int ind = -1;
  private Label lab;
  private Frame top;
  private AccessibleDir ad;
  private String URLName = "";

/**
 * Constructeur par defaut.
 */
  public FileZone(String name, byte mode, Frame parent) {
    Mode = mode;
    setLayout(null);
    Initialise();
    setBackground(BackGround);
    title = name;
    add(tf = new TextField("")); tf.setEditable(true);
    add(l = new MyList(true));
    add(filtre = new TextField("*.*")); filtre.setEditable(true);
    Init.println(ClassName, "reading current dir."+mode);
    top = parent;
    if (mode == LOCAL) {
// Si on est dans le mode LOCAL, on browse le repertoire courant
      File tmp = new File(".");
      Init.println(ClassName, "currentDir:"+tmp);
      filename = tmp.getAbsolutePath();
      ad = new LocalDir();
      readUp();
    } else
// Tant qu'on ne sait pas quel est le type de la connection
       ad = new LocalDir();
      
  }

/**
 * recupere les parametres d'initialisation
 */
  private void Initialise() {
    Init.println(ClassName, "Init."+Mode);
    String param = (String)Init.get(ClassName, "Color", "background");
    BackGround = param==null?BackGround:Init.getColor(param);
  }

/**
 * @return URL sur laquelle la connection a ete faite
 */
  public String getURLName() {
    String name = filename;
    if (Mode == REMOTE && filename != null &&  
      (filename.endsWith(".htm") || filename.endsWith(".html")))
        name = getParent(filename);
	
       
    return URLName+" "+name+ad.separator();
  }

/**
 * @param cb si true Le mode est Browse, sinon le mode est par filtre
 * @return list des fichiers selectionnes.
 */
  public String [] getSelectedFile(boolean cb) {
    if (!cb) {
      Init.println(ClassName, cb+":"+filtre.getText());
      String [] tmp = new String[1];  
      tmp[0]=filtre.getText();      // On recupere le filtre
      return tmp;
    }
    return l.getSelectedItems();
  }

/**
 * Demande l'ouverture d'un site distant
 * @param URL site distant
 * @param layout Panel dans lequel on doit afficher l'etat du chargement
 */
  public void Open(String URL, ButtonBar layout) {
    Init.println(ClassName,URL);
    if (URL != null) {
      int ind = URL.lastIndexOf('|');
      URLName = URL.substring(0, ind);
      filename = URL.substring(ind+1);
      ad = new RemoteDir(URLName, this, layout);
      ((Thread)ad).start();
      Init.println(ClassName, "Open:"+URLName+" "+filename);
    }
  }

/**
 * Demande au FileZone de reference une URL
 * Aucune connection n'est effectuee
 * @param URL site distant
 */
  public void ReferURL(String URL) {
    Init.println(ClassName,URL);
    if (URL != null) {
      int ind = URL.lastIndexOf('|');
      URLName = URL.substring(0, ind);
      filename = URL.substring(ind+1);
      Init.println(ClassName, "referURL:"+URLName+" "+filename);
    }
  }

/**
 * Dessine la FileZone
 */
  public void paint(Graphics g) {
    Dimension tmp = size();
    Font normal = g.getFont();
    Font bold = new Font(normal.getName(), Font.BOLD, normal.getSize());
    int height = tmp.height, width = tmp.width;

// Affiche le titre
    g.setFont(bold);
    g.drawString(title, width/2-title.length()*4, 15);

// Met en place la zone utilisee pour le chemin
    tf.move(10, 20);
    tf.resize(width-20, 30);

// Met en place la zone utilisee pour le filtre
    filtre.move(10, height-35);
    filtre.resize(width-20, 30);
    filtre.show();

// Mise en place de la liste contenant le nom des fichiers
    l.move(10, 55);
    l.resize(width-20, height-100);
    l.show();
  }

/**
 * lecture du repertoire dont le nom est contenu dans filename
 * @return true si l'operation se passe bien, false sinon
 */
  public boolean read() {
    Init.println(ClassName, "read:"+filename+"."+Mode);
    try {
      if (ad.isDirectory(filename)||filename.indexOf(ad.separatorChar())==-1) {
	Init.println(ClassName, "Reading :"+filename);
        boolean notroot;
        tf.setText(filename);
        l.clear();
        if (notroot=(filename.indexOf(ad.separatorChar())>-1))
          l.addItem("..");
	((FtpClnt)top).bb.inform(true);  
        String [] Noms = ad.list(filename);
        for (int i = 0; i<Noms.length; i++) {
	  Init.println(ClassName, "Noms:"+i+":"+Noms[i]);
          if (ad.isDirectory(filename+ad.separator()+Noms[i])) {
	    Init.println(ClassName, "dir:"+filename+ad.separator()+Noms[i]);
            l.addItem(Noms[i]+ad.separator(),notroot?1:0);
	  }
          else {
	    Init.println(ClassName, "file:"+filename+ad.separator()+Noms[i]);
            l.addItem(Noms[i]);
	  }
	}
	((FtpClnt)top).bb.inform(false);
        return true;
      }
    } catch (SecurityException se) {
      System.out.println("L'acces a ce repertoire n'est pas autorise");
    }
    return false;
  }

  public boolean action(Event ev, Object what) {
    if (ev.target == l)
      if (((String)what).equals(".."))
        readUp();
      else {
        String path = (String)what;
        int Long = path.length(), ind = path.lastIndexOf('.');


        Init.println(ClassName, "filname:"+filename);
// Si on est en mode Remote et que c'est un html
        if (Mode == REMOTE && 
	   (filename.endsWith(".htm") || filename.endsWith(".html")))
	  filename = getParent(filename);

// Si c'est un repertoire
        if (path.charAt(Long-1) == ad.separatorChar()) {
          String tmp_name = filename;
          filename += ad.separator()+getParent(path);
          if (read() == false) {
            filename=tmp_name;
            tf.setText(filename);
          }
        }
        String ext = (ind==-1)?"":path.substring(ind, Long).toLowerCase();

// Si c'est un jpg ou un gif
        if (ext.equals(".jpg") || ext.equals(".gif"))
          new ShowFrame(URLName, path, filename);
      }
    return super.action(ev, what);
  }

// Verifie que le chemin entre dans le TextField
// corresponde reellement a un chemin valide.
// si ce n'est pas le cas, on replace un chemin
// valide dans le TextField tf
  private void validTextField() {
    String tmp_name = filename;
    filename = tf.getText();
    if (filename.charAt(filename.length()-1) == ad.separatorChar())
      filename = getParent(filename);
    if (read() == false) {
      filename=tmp_name;
      tf.setText(filename);
    }
  }

// Effectue la completion dans le TextField tf
// @param direct true  : completion dans le sens direct
//               false : completion dans le sens indirect
  private void complete(boolean direct) {
// On recupere l'indice du caractere ou il y a le curseur
    int pos = tf.getSelectionStart();
// On recupere tout le texte avant le curseur
    String baseName = pos>0?tf.getText().substring(0, pos):ad.separator();
    int indSep = baseName.lastIndexOf(ad.separatorChar());
    String debut = (indSep == -1)?"":baseName.substring(indSep+1, pos);
// Enleve tout jusqu'au '/' precedent.
    Init.println(ClassName, "baseName:"+baseName);
    baseName = getParent(baseName);
    try {
      if (ind == -1)
        completion = ad.list(baseName, new DirectoryFilter(debut, ad));
      if (completion != null && completion.length!=0) {
        if (direct) {
          if (++ind>=completion.length)
            ind = 0;
        } else
          if (--ind<0)
            ind = completion.length-1;
        tf.setText(baseName+ad.separator()+completion[ind]);
        tf.select(pos, pos);
      }
    } catch (NullPointerException ex) {
      // le chemin complete n'est pas valide
    }
  }

  public boolean keyDown(Event ev, int k) {
    if (ev.target == tf)
      switch (k) {
      case '\t': // tabulation => completion
        complete((ev.modifiers & Event.SHIFT_MASK)==0);
        return true;
      case '\n': // retour chariot
        validTextField();
      default:
        ind=-1;
        return super.keyDown(ev, k);
      }
    return super.keyDown(ev, k);
  }

// Positionne filename vers le chemin superieur
  private void readUp() {
    Init.println(ClassName, "readUp:"+filename);
    filename = getParent(filename);
    read();
  }

// Renvoie le chemin du repertoire parent a file
  private String getParent(String file) {
    Init.println(ClassName, "getParent:"+file);
    int tmp = file.lastIndexOf(ad.separatorChar());
    return file.substring(0, (tmp==-1)?0:tmp);
  }

  public Dimension preferredSize() {
    Dimension tmp = top.size();
    return new Dimension((tmp.width-130)/2, tmp.height/2);
  }

  private final String ClassName="FileZone";
  private Color BackGround = Color.white;
}

/**
 * Class ShowFrame
 * Affiche un fenetre qui va contenir l'image selectionnee
 */
class ShowFrame extends Dialog {
  private Image im;
  private Button ok;
  private String ClassName = "ShowFrame";

/**
 * Constructeur par defaut
 */
  public ShowFrame(String url, String name, String path) {
    super(new Frame(), name, true);
    Init.println(ClassName, url+":"+path+":"+name);
    setLayout(null);
    add(ok = new Button("Ok")); ok.resize(60, 30);
//Calcul le nom de l'image et la charge
    if (url.length()==0)
      im = Toolkit.getDefaultToolkit().getImage(path+File.separator+name);
    else { 
      String fname = url+path+File.separator+name;
      Init.println(ClassName, "Show:"+fname);
      try {
        im = Toolkit.getDefaultToolkit().getImage(new URL(fname));
      } catch (java.net.MalformedURLException mue) {
        System.err.println("Url malformed:"+fname);
      }
    }
// On l'ajoute au MediaTracker
    MediaTracker tracker = new MediaTracker(this);
    tracker.addImage(im, 0);
    try {
      tracker.waitForID(0);
    } catch (Exception ex) {
      System.out.println("Error opening File");
    }
// Recupere les dimensions de l'image
    int height = im.getHeight(this), width = im.getWidth(this);
// retaille la fenetre
    resize(width=Math.max(width+10, 150), height=Math.max(height+150, 150));
// Affiche le bouton ok
    ok.move(width/2-30, height-40);

    show();
  }

  public void paint(Graphics g) {
    update(g);
  }

  public void update(Graphics g) {
    int height = im.getHeight(this), width = im.getWidth(this);
    g.drawImage(im, 10, 30, this);
    g.drawString(width+"x"+height, 20, height+50);
  }

  public boolean action(Event ev, Object what) {
    if (ev.target instanceof Button)
      dispose();
    return true;
  }
}
