import java.net.*;
import java.io.*;
import java.util.*;
import java.lang.*;


/** UrlDir 
  * Implemente la gestion des fichiers (AccessibleDir) 
  * @param Url l'url ou se connecter 
  * @version        0.1 Feb 1997
  * @author         Ebele Nicolas, Mallet Frederic
  */

public class UrlDir implements AccessibleDir {
/** le nom de la classe (Pour debugger) */
  static final public String ClassName = "UrlDir";
/** le cache (commun a toutes les instances de la classe) */
  static private DirCache dc = null;
/** l'url courante */
  private String Url;
/** la connection a l'url */
  private MonUrl Connect = null;

/** Renvoie la derniere erreur produite
  * @param pas de parametres
  * @retrun renvoie la derniere erreur si il y en a eu une, null sinon
  */
public String erreurText()
  {
    if (Connect != null)
      return Connect.erreurText();
    return null;
  } 

/** Renvoie la chaine de separation
  * @param pas de parametres
  * @retrun renvoie le separateur de fichier utilise (ici toujours "/") sous forme de string
  */
public String separator()
  {
    return "/";
  }

/** Renvoie le caractere de separation
  * @param pas de parametres
  * @retrun renvoie le separateur de fichier utilise (ici toujours "/") sous forme d'un caractere
  */
public char separatorChar()
  {
    return '/';
  }

/** Initialise le cache
  * @param Url l'url a ajouter en 1er dans le cache
  * @return pas de valeur retournee
  */
private void InitCache(String Url)
  {
    if (dc == null) {
      String param = (String)Init.get(ClassName, "config", "SizeCache");
      int taille = param==null?20:Integer.parseInt(param);
      if (taille == 0)
	taille = 20;
      dc = new DirCache(taille);
    }
    Init.println(ClassName, "Ajout de " + Url);
    if (!dc.isIn(Url)) {
      Init.println(ClassName, "----------------> ok");
      Connect = new MonUrl(Url);
      dc.addElement(Url, Connect.GetList(),false);
    }
    else {
      // ici ca ne coute rien de recreer un 'MonUrl'  car la connection ne se fait pas maintenant ....
      Connect = new MonUrl(Url);
      Init.println(ClassName, "-------------> existe deja ...");
    }
  }



/** Constructeur
  * @param Url l'url a construire
  * note : on a un cache (static a la classe) on ne se connecte a l'url que si elle ne se trouve pas
  *        dans le cache
  */
  UrlDir(String Url)
  {
    if (Url.endsWith("/"))
      Url = Url.substring(0,Url.length()-1);

    this.Url = Url;
    InitCache(Url);
  }
/** Constructeur
  * @param Url l'url a construire
  * @param Cache si = vrai on met dans le cache le repertoire
  * note : on a un cache (static a la classe) on ne se connecte a l'url que si elle ne se trouve pas
  *        dans le cache
  */
  UrlDir(String Url, boolean Cache)
  {

    if (Url.endsWith("/"))
      Url = Url.substring(0,Url.length()-1);
    this.Url = Url;

    if (Cache) 
      InitCache(Url);
    else {
      Connect = new MonUrl(Url);
      Init.println(ClassName, "Constuction d'urldir sans cache");
    }
  }
/** 
  * @param path le path a comparer
  * @return renvoie vrai si path est un repertoire, faux sinon
  */  
public boolean isDirectory(String path)
  { 

    if (path != null && path.startsWith("/"))
      path = path.substring(1);

    if (dc.isIn(Url+(path.length()>0? ("/"+path):"")))
      return true;

    String s,t;
    Hashtable ft;
    int i = path.lastIndexOf("/");

    s = path.substring(0,i==-1?0:i);
    if (s.equals("/"))
      s = "";
    
    t = path.substring(i+1);
    if (t.endsWith(".html") || t.endsWith(".htm")){ // on renvoie vrai si c'est une page html
                                                    // pour pouvoir la parser comme un repertoire ...
      Init.println(ClassName, t + " est une page html -> directory ...");
      return true;
    }

    if (s.length() > 0)
      ft = dc.Element(Url+"/"+s);
    else
       ft = dc.Element(Url);
    if (ft == null) return false;
    return (((FileType)ft.get(t)).isDirectory());
    /*
    Init.println(ClassName,"test="+Url+"  s=="+s+" t==" + t);
    for (int j=0;j<ft.length;j++)
      {
	Init.println(ClassName,"cmp de " + t + " avec " +  ft[j].getName());
	if (t.equals(ft[j].getName()))
	  return ft[j].isDirectory();
      }
    
    return false;
    */
  }
  


/** Renvoie le contenu d'un repertoire
  * @param path le path ou aller chercher la liste
  * @return renvoie un tableau de string representant le repertoire (on se connecte si on a pas le path
  *         dans le cache)
  */
public String[] list(String path)
  { 
    String s;
    
    if (path == null || path.length() == 0)
      s = Url;
    else {
      if (path.startsWith("/"))
	path = path.substring(1);
      if (Url.endsWith("/."))
	s = Url.substring(0,Url.length()-1) + path;
      else
	s = Url + "/" +path;
    }

    Init.println(ClassName,"List: Ici ajout de " + s + " avec Url=" + Url);
    if (!dc.isIn(s)) { 
      Connect = new MonUrl(s);
      Init.println(ClassName,"----------> ok ");
      if (path != null)
	dc.addElement(s, Connect.GetList(),false);
      else
	dc.addElement(Url, Connect.GetList(),false);
    }
    else
      Init.println(ClassName,"-----------> existe deja ...");
    
    return dc.list(s);
  }

/** Renvoie le contenu d'un repertoire
  * @param path le path ou aller chercher la liste
  * @param filter le filenamefilter 
  * @return renvoie un tableau de string representant le repertoire (on se connecte si on a pas le path
  *         dans le cache)
  *         la liste est renvoyee par rapport au FileNameFilter
  */  
 public String[] list(String path,FilenameFilter filter)
  { 
    Init.println(ClassName, "+++++list(filter):"+path);
    String [] tmp = list(path);
    Vector vtmp = new Vector();
         
    for (int i = 0; i<tmp.length; i++) {
      Init.println(ClassName, "Possible choice:"+tmp[i]);
      if (filter.accept(null, path+"/"+tmp[i])) {
        Init.println(ClassName, "Element added:"+tmp[i]);
        vtmp.addElement(tmp[i]);
      }
    }   

    tmp = new String [vtmp.size()];
    for (int i =0; i<vtmp.size(); i++)
      tmp[i] = vtmp.elementAt(i).toString(); 
    
    return tmp;
    
  }
 
/** Charge le fichier source vers le fichier dest 
  * @param Source le fichier source
  * @param Dest le fichier dest
  * @return renvoie vrai si tout c'est bien passe
  */
 public boolean GetFile(String Source, String Dest)
  {
    Init.println(ClassName, "getfile de " + Source + " vers " + Dest + "(connect=" + Connect + ")");
    if (Dest != null)
      return Connect.GetFile(Source,Dest);
    
    return Connect.GetFile(Source);
  }

/** (PAS IMPLEMENTE PAR JAVA !!!!)
  * Met le fichier source vers le fichier dest 
  * @param Source le fichier source
  * @param Dest le fichier dest
  * @return renvoie vrai si tout c'est bien passe
  */
public boolean PutFile(String Source, String Dest)
  {
    return false;  // not implemented
  }

}


