// $Id: virtuallythere.java,v 1.8 2001/10/26 20:48:12 mdean Exp $


class virtuallythere
{
    static final java.text.DateFormat dateFormat = new java.text.SimpleDateFormat("EEE, MMM d");
    static final java.text.DateFormat timeFormat = new java.text.SimpleDateFormat("HH:mm");
    static final java.text.DateFormat isoDateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    static final java.util.Date currentDate = new java.util.Date();
    static final java.util.Calendar calendar = java.util.Calendar.getInstance();
    static final int year = calendar.get(java.util.Calendar.YEAR);
    
    /**
     * return a specific node in the flight data
     */
    static String getRC(org.daml.html.Tree tree,
			String path,
			int row,
			int column,
			String suffix)
	throws Exception
    {
	return tree.getString(path + "tr/td/table[1]/tr/td/table/tr[" + row + "]/td[" + column + "]/" + suffix);
    }

    /**
     * add 2 dates
     */
    static java.util.Date addDates(java.util.Date date,
				   java.util.Date time)
    {
	return new java.util.Date(date.getTime() + time.getTime());
    }

    /**
     * reuturn the speecified airport object
     */
    static com.hp.hpl.mesa.rdf.jena.model.Resource parseAirport(com.hp.hpl.mesa.rdf.jena.model.Model model,
								String airport)
	throws Exception
    {
	int paren = airport.lastIndexOf('(');
	return model.createResource("http://www.daml.ri.cmu.edu/ont/AirportCodes.daml#" + airport.substring(paren + 1,
													     paren + 4));
    }

    static final char nbsp = 160;

    /**
     * trim whitespace, including nbsp's
     */
    static String trim(String string)
    {
	return string.replace(nbsp, ' ').trim();
    }

    static com.hp.hpl.mesa.rdf.jena.model.Model virtuallythere(String pnr,
							       String surname)
	throws Exception
    {
	org.daml.html.Tree tree = new org.daml.html.Tree("https://www.virtuallythere.com/cgi-bin/nph-itinerary?pnr=" + pnr + "&name=" + surname + "&language=0&host=1W&clocktype=24");
	// org.daml.html.Tree tree = new org.daml.html.Tree("file:/mdean/airfax/2001-10-15.html");

	com.hp.hpl.mesa.rdf.jena.model.Model model = new com.hp.hpl.mesa.rdf.jena.mem.ModelMem();
	com.hp.hpl.mesa.rdf.jena.model.Resource itineraryResource = model.createResource("#" + pnr.toUpperCase());
	model.add(itineraryResource,
		  com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
		  itinerary_ont.Itinerary);

	String passenger = tree.getString("html/body/table[1]/tr/td/div/table[8]/tr/td/table/tr/td/table/tr/td[2]/b/text()");
	model.add(itineraryResource,
		  itinerary_ont.passenger,
		  trim(passenger));

	String flights = "html/body/table[2]/tr/td/";
	for (int flight = 2; ; flight++)
	    {
		String path = flights + "table[" + flight + "]/";
		String dateAirlineFlight = tree.getString(path + "tr/td/div/b/text()");
		if (dateAirlineFlight == null)
		    break;
		java.util.Date date = dateFormat.parse(dateAirlineFlight.substring(0, dateAirlineFlight.indexOf(nbsp)));
		dateAirlineFlight = trim(dateAirlineFlight);
		int comma = dateAirlineFlight.lastIndexOf(',');
		int space = dateAirlineFlight.indexOf(' ', comma + 2);
		String airline = dateAirlineFlight.substring(comma + 2,
							     space);
		int flightNumber = Integer.parseInt(dateAirlineFlight.substring(space + 1));
		
		// year heuristic
		calendar.setTime(date);
		calendar.set(java.util.Calendar.YEAR, year);
		date = calendar.getTime();
		if (date.before(currentDate))
		    {
			calendar.set(java.util.Calendar.YEAR, year + 1);
			date = calendar.getTime();
		    }

		com.hp.hpl.mesa.rdf.jena.model.Resource flightResource = model.createResource();
		model.add(flightResource,
			  com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
			  itinerary_ont.Flight);
		model.add(itineraryResource,
			  itinerary_ont.flight,
			  flightResource);
		model.add(flightResource,
			  itinerary_ont.airline,
			  airline); // XXX - URI
		model.add(flightResource,
			  itinerary_ont.flight,
			  "" + flightNumber);

		// collect attributes
		java.util.HashMap values = new java.util.HashMap();
		for (int row = 0; row < 9; row++)
		    {
			for (int col = 0; col < 2; col++)
			    {
				String key = getRC(tree, path, row + 1, col * 2 + 1, "b/text()");
				if (key == null)
				    continue;
				key = key.trim();
				String value = getRC(tree, path, row + 1, col * 2 + 2, "text()");
				values.put(key, value);
			    }
		    }

		java.util.Date depart = timeFormat.parse((String) values.get("Departs:"));
		java.util.Date arrive = timeFormat.parse((String) values.get("Arrives:")); // XXX - wrap day if necessary
		model.add(flightResource,
			  itinerary_ont.origin,
			  parseAirport(model,
				       (String) values.get("From:")));
		model.add(flightResource,
			  itinerary_ont.destination,
			  parseAirport(model,
				       (String) values.get("To:")));
		model.add(flightResource,
			  itinerary_ont.depart,
			  isoDateFormat.format(addDates(date, depart)));
		model.add(flightResource,
			  itinerary_ont.arrive,
			  isoDateFormat.format(addDates(date, arrive)));
		model.add(flightResource,
			  itinerary_ont.miles,
			  values.get("Mileage:"));
		model.add(flightResource,
			  itinerary_ont.seat,
			  values.get("Seat:"));
		// XXX - duration
		// XXX - class
		// XXX - meal
		// XXX - aircraft
	    }

	// XXX - hotels 

	// XXX - rental cars

	// XXX - rln(s)

	return model;
    }

    static void usage()
    {
	System.err.println("Usage:  rln surname");
	System.exit(1);
    }

    public static void main(String args[])
	throws Exception
    {
	if (args.length != 2)
	    usage();

	com.hp.hpl.mesa.rdf.jena.model.Model model = virtuallythere(args[0],
								    args[1]);
	java.io.PrintWriter writer = new java.io.PrintWriter(System.out);
	model.write(writer);
	writer.close();
    }
}
