/*
 * This class is given the responsability to
 * connect web page, open the file
 * or read the stdin and launch the table parser 
 * wich generate a new HTML document
 */

import java.net.*;
import java.io.*;
import java.util.*;
import w3c.wai.parser.html4.*;
import w3c.wai.filter.*;

//import javax.servlet.http.*;


public class Linearize {
    final static public int URL=0;
    final static public int FILE=1;
    final static public int STDIN=2;

    // Network connection for url
    private Socket s=null;

  /*
   * Stream connected to daemon http.
   * This daemon returns the content of the page by
   * the stream
   */
  private InputStream isUrl=null;
    
     /*
      * Stream use to provide the HTTP request to the daemon
      */
  private BufferedWriter bwUrl=null;

    /*
     * Read the file on standard input and 
     * launch the parser
     */
    public Linearize(int tableNumber,int orientation,
		     int repeat,
		     int recurs,
		     int interact,
		     String headerSeparator,String valueSeparator,
		     String cellSeparator,String lineSeparator,
		     String outputFile,
		     String service,
		     int lynx,
		     String base,
		     int embedded) 
       throws IOException {
      
	 /*
	  * the significaton to tableNumber, orientation, recurs, 
	  * headSeparator,valueSeparator, cellSeparator, lineSeparator
	  * are discussed later
	  */
	 
	 
	 isUrl=System.in;
	 
	 if (outputFile==null)
	   new html4(base,isUrl,tableNumber,orientation,repeat,
		     0,interact,
		     headerSeparator,
		     valueSeparator,
		     cellSeparator,lineSeparator,service,lynx,embedded);
	 else {
	   try {
	     FileOutputStream fos=new FileOutputStream(outputFile);
	     new html4(base,isUrl,
		       fos,		
		       tableNumber,orientation,repeat,
		       0,interact,
		       headerSeparator,
		       valueSeparator,
		       cellSeparator,lineSeparator,service,lynx,
		       embedded);
	   }
	   catch(FileNotFoundException e) {
	     System.out.println("Impossible to create the output file.");
	     System.exit(4);
	   }
	 }
    }

  
  /*
   * Connect the web page or the file and 
   * launch the parser
   */
  public Linearize(String url,
		   int tableNumber,int orientation,
		   int repeat,
		   int recurs,
		   int interact,
		   String headerSeparator,String valueSeparator,
		   String cellSeparator,String lineSeparator,
		   int type,
		   String outputFile,
		   String service,
		   int lynx,
		   String base,
		   int embedded) 
       throws IOException {
		     
		     
	 switch (type) {
	   
	 case URL : 
	   filter f=null;
	   try {
	     connectURL(url);
	     f=new filter(isUrl);
	   }
	   catch (MalformedURLException e) {
	     //System.out.print("Content-type: text/html\n\n");
	     System.out.println("Malformed URL.");
	     return;
	   }
	   catch (IOException e) {
	     //System.out.print("Content-type: text/html\n\n");
	     System.out.println("Impossible to connect remote httpd.");
	     try {
	       if (s!=null) 
		 s.close();
	       if (isUrl!=null)
		 isUrl.close();
	       if (bwUrl!=null)
		 bwUrl.close();
	     }
	     catch (IOException e3) {}
	     return;
	   }
	   catch (FilterException e) {
	     //System.out.print("Content-type: text/html\n\n");
	     System.out.println("Problem with input stream.");
	     try {
	       if (s!=null) 
		 s.close();
	       if (isUrl!=null)
		 isUrl.close();
	       if (bwUrl!=null)
		 bwUrl.close();
	     }
	     catch (IOException e3) {}
	     return;
	   }
	   
	   /*if (f.getHtmlText()) 
	     System.out.println("Content-type: text/html\n\n");
	     else 
	     System.out.println("Content-type: text/plain\n\n");*/
	   break;
	   
	 case FILE :
	   try {
	     isUrl=new FileInputStream(url);
	   }
	   catch (FileNotFoundException e) {
	     System.out.println("File not found.");
	     return;
	   }
	   recurs=0;
	   break;
	 }
	 
	 if (outputFile==null)
	   new html4((base.equals("")?url:base),
		     isUrl,tableNumber,orientation,repeat,
		     recurs,interact,headerSeparator,
		     valueSeparator,
		     cellSeparator,lineSeparator,service,lynx,
		     embedded);
	 else {
	   try {
	     FileOutputStream fos=new FileOutputStream(outputFile);
	     new html4((base.equals("")?url:base),
		       isUrl,fos,		
		       tableNumber,orientation,repeat,
		       recurs,interact,headerSeparator,
		       valueSeparator,
		       cellSeparator,lineSeparator,service,lynx,
		       embedded);
	   }
	   catch(FileNotFoundException e) {
	     System.out.println("Impossible to create the output file.");
	     return;
	   }
	 }
  }
  
  public Linearize(String url,
		   int tableNumber,int orientation,int repeat,
		   int recurs,int interact,
		   String headerSeparator,String valueSeparator,
		   String cellSeparator,String lineSeparator,
		   OutputStream res,String service,int lynx,
		   String base,int embedded)
       throws IOException {
		     
	 filter f=null;
	 try {
	   connectURL(url);
	   f=new filter(isUrl);
	 }
	 catch (MalformedURLException e) { return;}
	 catch (IOException e) {
	   res.write((new String("Impossible to connect remote httpd.")).getBytes());
	   try {
	     if (s!=null) 
	       s.close();
	     if (isUrl!=null)
	       isUrl.close();
	     if (bwUrl!=null)
	       bwUrl.close();
	   }
	   catch (IOException e3) {}
	   return;
	 }
	 catch (FilterException e) {
	   res.write((new String("Problem with input stream.")).getBytes());
	   try {
	     if (s!=null) 
	       s.close();
	     if (isUrl!=null)
	       isUrl.close();
	     if (bwUrl!=null)
	       bwUrl.close();
	   }
	   catch (IOException e3) {}
	   return;
	 }
	 
	 new html4(url,isUrl,tableNumber,orientation,repeat,
		   recurs,interact,headerSeparator,
		   valueSeparator,
		   cellSeparator,lineSeparator,res,service,lynx,
		   embedded);
  }
  
  /* 
   * Connect the url
   */
  private void connectURL(String urlStr) throws MalformedURLException,
	 IOException {
    URL url=new URL(urlStr);
    s=new Socket(url.getHost(),url.getPort()==-1?80:url.getPort());
    isUrl=s.getInputStream();
    bwUrl=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
    readHTML(url);
  }
  
  /*
   * Send the a GET request to the server
   */
    private void readHTML(URL url) {
      String file=url.getFile();
      String line=null;
      
      line="GET "+file+" HTTP/1.0\n\n";
      
      try {
	bwUrl.write(line);
	bwUrl.flush();
      }
      catch (IOException e) {
	System.out.print("Content-type: text/html\n\n");
	System.out.println("Problem sending request at httpd");
	return;
      }
    }
  
  public static void main(String argv[]) {
    int nbr=argv.length;
    int ind=-1;
    int table=0;
    int orient=1;
    int repeat=4;
    int recurs=0;
    int interact=0;
    String hs=", ";
    String vs="= ";
    String cs=", ";
    String ls="";
    int type=STDIN;
    String url=null;
    String outputFile=null;
    String service=null;
    int lynx=0;
    String base="";
    int embedded=0;
    
    if (nbr==1 && argv[0].equals("-help")) {
      printHelp();
    }
    
    if ((ind=getIndiceOption("-t",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      try {
	table=Integer.parseInt(argv[ind+1]);
      }
      catch(NumberFormatException e) {
	System.out.println("Give a number for table option");
	System.exit(2);
      }
    }
    
    if ((ind=getIndiceOption("-interact",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      try {
	interact=Integer.parseInt(argv[ind+1]);
      }
      catch(NumberFormatException e) {
	System.out.println("Give a number for Interaction mode");
	System.exit(2);
      }
      if (interact<0 || interact>1) {
	System.out.println("Error... values for interact can only be: 0 or 1");
	System.exit(1);
      }
    }

    if ((ind=getIndiceOption("-repeat",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      if (argv[ind+1].equals("deepest4all"))
	repeat=2;
      else 
	  if (argv[ind+1].equals("all4all"))
	      repeat=4;
	  else
	      if (argv[ind+1].equals("deepest"))
		  repeat=1;	    
	      else
		  if (argv[ind+1].equals("all"))
		      repeat=3;	    
	      else {
		System.out.println("Error... values for repeat can only be: all4all or deepest4all");
		System.exit(1);
	    }
    }

    if ((ind=getIndiceOption("-base",argv))!=-1) {
	if (ind+1>=nbr)
	    printHelp();
	base=argv[ind+1];
    }

    if (getIndiceOption("-e",argv)!=-1) {
	if (getIndiceOption("-url",argv)==-1)
	    if (base.equals("")) {
		System.out.println("If you want to change the embedded URL (loading a local file), please give me a base (-base option).");
		System.exit(1);
	    }
	embedded=1;
    }
    else 
       base="";
    
    if ((ind=getIndiceOption("-orient",argv))!=-1) {
	if (ind+1>=nbr)
	    printHelp();
	if (argv[ind+1].equals("row"))
	    orient=1;
	else 
	    if (argv[ind+1].equals("column"))
		orient=2;
	    else
		if (argv[ind+1].equals("markup"))
		    orient=3;
		else {
		    System.out.println("Error... values for orientation can only be: row,column or markup");
		    System.exit(1);
		}
    }
    
    if ((ind=getIndiceOption("-r",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      if (argv[ind+1].equals("true")) {
	  FileReader fr=null;
	  try {
	      fr=new FileReader("config.cfg");
	  }
	  catch (FileNotFoundException e) {
	      System.out.println("Config.cfg doesn't exists\n");
	      System.exit(1);
	  }
	  recurs=1;
	  try {
	      service=readLine(fr);
	      //System.out.println("-"+service+"-");
	  }
	  catch (IOException e) {
	      System.out.println("Problem with the config.cfg");
	      System.exit(1);
	  }
	  
      }
      else 
	  if (argv[ind+1].equals("false"))
	      recurs=0;
	  else {
	      System.out.println("Error... values for recursive can only be: true or false");
	      System.exit(1);
	  }
    }
    
    if ((ind=getIndiceOption("-hs",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      hs=parse(argv[ind+1]);
    }
    
    if ((ind=getIndiceOption("-vs",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      vs=parse(argv[ind+1]);
    }
    
    if ((ind=getIndiceOption("-cs",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      cs=parse(argv[ind+1]);
    }
    
    if ((ind=getIndiceOption("-ls",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      ls=parse(argv[ind+1]);
    }
    
    if ((ind=getIndiceOption("-o",argv))!=-1) {
      if (ind+1>=nbr)
	printHelp();
      outputFile=argv[ind+1];
    }
    
    if (getIndiceOption("-x",argv)!=-1) 
	lynx=1;
    
    if ((ind=getIndiceOption("-url",argv))!=-1)
      type=URL;
    else 
      if ((ind=getIndiceOption("-file",argv))!=-1)
	type=FILE;
    
    if (type!=STDIN) {      
      if (ind+1>=nbr)
	printHelp();
      url=argv[ind+1];
      try {
        new Linearize(url,
		      table,orient,repeat,recurs,
		      interact,
		      hs,vs,cs,ls,type,outputFile,
		      service,lynx,base,embedded);
      }
      catch (IOException e) {
	  System.out.println("Problem with streams.");
      }
    }
    else 
	try {
	    new Linearize(table,orient,repeat,recurs,interact,
			  hs,vs,cs,ls,outputFile,
			  service,lynx,base,embedded);
	}
	catch (IOException e) {
	    System.out.println("Problem with streams.");
	}
  }
    
    private static String readLine(FileReader fr) throws IOException {
	int car;
	StringBuffer sb=new StringBuffer();
	while (true) {
	    car=fr.read();
	    if (car==-1 || car==0 || car=='\n' || car=='\r' ||
		car==32)
		break;
	    sb.append((char)car);
	}
	if ((new String(sb)).indexOf("http://")!=0 || sb.length()<8) {
	    System.out.println("Bad URL in config.cfg");
	    System.exit(1);
	}
	return new String(sb);
    }

  
  private static void printHelp() {
    System.out.println("java Linearize [ (-url <url>) | (-file <string>) ] [-t <number>] [-orient <string>] [-repeat <string>] [-r <boolean>] [-hs <string>] [-vs <string>] [-cs <string>] [-ls <string>] [-interact <number>] [-base <string>] [-o <string>] [-x] [-e]");
    System.exit(0);
  }
  
  private static int getIndiceOption(String option,String[] tab) {
    for (int cpt=0;cpt<tab.length;cpt++) 
      if (tab[cpt].equals(option))
	return cpt;
    return -1;
  }
  
  
  private static String parse(String value) {
    StringBuffer sb=new StringBuffer();
    int begin=0;
    int end=0;
    while (true) {
      end=value.indexOf('\\',end);
      if (end==-1) {
	sb.append(value.substring(begin));
	break;
      }
      sb.append(value.substring(begin,end));
      switch (value.charAt(end+1)) {
      case 'r' : 
	sb.append('\r');
	begin=end+2;
	end=begin;
	break;
      case 't' : 
	sb.append('\t');
	begin=end+2;
	end=begin;
	break;
      case 'n' :
	sb.append('\n');
	begin=end+2;
	end=begin;
	break;
      default : 
	sb.append('\\');
	begin=++end;
      }
    } 
    return new String(sb);
  }
}















