import java.net.URL;
import java.net.URLConnection;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import com.sun.java.swing.JTextArea;

class Engine implements Runnable
{
  // toString= http://www.toto/titi/tutu#tata
  // getFile=/titi/tutu
  // getHost=www.toto
  // getRef=tata

  EngineCallBack callBackClass; // doit contenir la fonction foundURL(URL)
  Hashtable tableURL;           // tous les URLs trouves
  URL mainURL;                  // l'URL de depart de la recherche
  String mainHost;              // l'hote de depart de la recherche
  String mainDir;               // le repertoire de depart de la recherche
  JTextArea log;                // la zone de sortie de log

  public Engine(EngineCallBack cb, String nom, JTextArea log) throws java.io.IOException,java.net.MalformedURLException
    {
      String s;

      mainURL= new URL(isTildeName(nom)?(nom+'/'):nom);
      if ((s= mainURL.openConnection().getHeaderField(0))==null || s.startsWith("HTTP/1.0 4"))
	  throw new java.io.IOException();
      mainHost= mainURL.getHost();
      mainDir= getBaseName(mainURL.getFile());
      callBackClass= cb;
      this.log= log;
      tableURL= new Hashtable();
    }

  public void run()
    {
      log.append("Launched "+mainURL.toString()+"...\n");
      liste(mainURL);
      log.append("Finished "+mainURL.toString()+"!!!\n");
    }

  boolean isTildeName(String id)
    {
      int i;

      return ((i= id.lastIndexOf('/')+1)<id.length() && id.charAt(i)=='~');
    }

  String getBaseName(String id)
    {
      int i;
      return ((i= id.indexOf('/',1))==-1)?null:id.substring(1,i);
    }

  void liste(URL url)
    {
      StringBuffer sb= null;

      try
	{
	    InputStream is= url.openStream();
	    Parser parser= new Parser(is,log);
	    Vector v= new Vector();
	    Enumeration e;
	    String s,t;
	    boolean b;

	    while ((sb= parser.findTag())!=null)
		{
		    URL u= new URL(url,sb.toString()); // l'URL absolu trouve

		    if (!tableURL.containsKey(s= u.getFile()) && u.getHost().equals(mainHost) && // le chemin trouve est nouveau et il provient du meme hote original
			(mainDir==null || mainDir.equals(getBaseName(s)))) // et soit le chemin est a la racine, soit c'est le meme que celui original
			{
			    tableURL.put(s,u);
			    if ((t= u.openConnection().getHeaderField(0))!=null && !t.startsWith("HTTP/1.0 4")) // le chemin est lisible
				{
				    if (!(b= s.endsWith("/"))) // ce n'est pas un repertoire
					callBackClass.foundURL(u);
				    if (s.substring(s.lastIndexOf('.')+1).equalsIgnoreCase("HTML") || // c'est un fichier HTML ou
					b) // c'est un repertoire
					v.addElement(u); // alors on peut l'explorer
				}
			    else
				log.append("Unreadable address "+u.toString()+"\n");
			}
		}
	    is.close(); // ne pas oublier de fermer le le flux avant l'appel recursif
	    e= v.elements();
	    while (e.hasMoreElements()) // appel recursif sur les nouveaux chemins
		liste((URL)e.nextElement());
	}
      catch (java.net.MalformedURLException x) { log.append("Found unknown protocol "+sb+"\n"); }
      catch (java.io.IOException x) { log.append("Unreachable address "+url.toString()+"\n"); }
    }
}
