// $Id: DAMLLayer.java,v 1.5 2003/02/06 18:51:18 mdean Exp $


/**
 * display a layer defined using map-ont.daml using OpenMap (http://openmap.bbn.com)
 */
public class DAMLLayer
    extends com.bbn.openmap.Layer
{
    public com.bbn.openmap.proj.Projection projection;
    public com.bbn.openmap.omGraphics.OMGraphicList omgraphics = null;
    com.hp.hpl.mesa.rdf.jena.model.Model model = new com.hp.hpl.mesa.rdf.jena.mem.ModelMem();

    public void projectionChanged (com.bbn.openmap.event.ProjectionEvent e) {

	com.bbn.openmap.proj.Projection newP = e.getProjection();
	if (newP.equals(projection)) {// projection not really different
	    repaint();
	    return;
	}
	projection = newP.makeClone();

	computeLayer();
    }

    public synchronized void paint (java.awt.Graphics g)
    {
	omgraphics.render(g);
    }

    public void repaintGraphics()
    {
	omgraphics.regenerate(projection);
	repaint();
    }

    protected synchronized void computeLayer ()
    {
	if (projection == null) return;

	// only do work if the layer is visible
	if (! isVisible())
	    return;

	if (omgraphics == null)
	    {
		omgraphics = new com.bbn.openmap.omGraphics.OMGraphicList();
		getDAML();
		omgraphics.generate(projection, false);
	    }
	else 
	    omgraphics.regenerate(projection);

	repaint();
    }

    float getFloat(com.hp.hpl.mesa.rdf.jena.model.Resource resource,
			  com.hp.hpl.mesa.rdf.jena.model.Property property)
			  throws Exception
    {
	com.hp.hpl.mesa.rdf.jena.model.RDFNode node = itinerary2map.getValue(model, resource, property);
	return Float.parseFloat(node.toString());
    }

    /**
     * return the first/single instances of the specified type
     */
    static com.hp.hpl.mesa.rdf.jena.model.Resource getFirst(com.hp.hpl.mesa.rdf.jena.model.Model model,
							    com.hp.hpl.mesa.rdf.jena.model.Resource type)
	throws Exception
    {
	com.hp.hpl.mesa.rdf.jena.model.ResIterator iterator = model.listSubjectsWithProperty(com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type,
											      type);
	return iterator.next();
    }

    void getDAML()
    {
	boolean done = false;
	while (! done)
	    {
		String uri = null;
		try {
		    uri = com.bbn.openmap.Environment.get("daml.uri");
		    if (uri == null) 
			uri = javax.swing.JOptionPane.showInputDialog(this, "Enter DAML Map URI");
		    if (uri == null)
			System.exit(0);
		    model.read(uri);

		    // get our layer
		    com.hp.hpl.mesa.rdf.jena.model.Resource layer = (com.hp.hpl.mesa.rdf.jena.model.Resource) getFirst(model, map_ont.DrawingLayer);
	
		    // display the objects
		    com.hp.hpl.mesa.rdf.jena.model.NodeIterator iterator = model.listObjectsOfProperty(layer, map_ont.object);
		    while (iterator.hasNext())
			{
			    com.hp.hpl.mesa.rdf.jena.model.Resource object = (com.hp.hpl.mesa.rdf.jena.model.Resource) iterator.next();
			    com.hp.hpl.mesa.rdf.jena.model.Resource type = (com.hp.hpl.mesa.rdf.jena.model.Resource) itinerary2map.getValue(model, object,
																	    com.hp.hpl.mesa.rdf.jena.vocabulary.RDF.type);
			    if (type.equals(map_ont.Point))
				{
				    com.hp.hpl.mesa.rdf.jena.model.Resource location = (com.hp.hpl.mesa.rdf.jena.model.Resource) itinerary2map.getValue(model, object, map_ont.location);
				    float lat = getFloat(location, map_ont.latitude);
				    float lon = getFloat(location, map_ont.longitude);
				    String label = itinerary2map.getValue(model, object, map_ont.label).toString();
				    com.bbn.openmap.omGraphics.OMPoint point = new com.bbn.openmap.omGraphics.OMPoint(lat, lon);
				    point.setLineColor(getColor(object));
				    omgraphics.add(point);
				    com.bbn.openmap.omGraphics.OMText text = new com.bbn.openmap.omGraphics.OMText(lat, lon, label, com.bbn.openmap.omGraphics.OMText.JUSTIFY_CENTER);
				    omgraphics.add(text);
				}
			    else if (type.equals(map_ont.Line))
				{
				    com.hp.hpl.mesa.rdf.jena.model.NodeIterator locationIterator = model.listObjectsOfProperty(object, map_ont.location);
				    com.hp.hpl.mesa.rdf.jena.model.Resource point1 = (com.hp.hpl.mesa.rdf.jena.model.Resource) locationIterator.next();
				    com.hp.hpl.mesa.rdf.jena.model.Resource point2 = (com.hp.hpl.mesa.rdf.jena.model.Resource) locationIterator.next();
				    locationIterator.close();
				    float lat1 = getFloat(point1, map_ont.latitude);
				    float lon1 = getFloat(point1, map_ont.longitude);
				    float lat2 = getFloat(point2, map_ont.latitude);
				    float lon2 = getFloat(point2, map_ont.longitude);
				    com.bbn.openmap.omGraphics.OMLine line = new com.bbn.openmap.omGraphics.OMLine(lat1, lon1, lat2, lon2, com.bbn.openmap.omGraphics.OMLine.LINETYPE_GREATCIRCLE);
				    line.setLineColor(getColor(object));
				    omgraphics.add(line);
				}
			    else
				System.err.println("unknown object type " + type + " ignored");
			}
		    done = true;
		} catch (Exception e) {
		    javax.swing.JOptionPane.showMessageDialog(this, e.toString(), "getting " + uri, javax.swing.JOptionPane.ERROR_MESSAGE);
		    e.printStackTrace();
		}
	    }
    }

    static java.util.Hashtable colors = new java.util.Hashtable();

    static java.awt.Color getColor(com.hp.hpl.mesa.rdf.jena.model.Resource mapObject)
	throws com.hp.hpl.mesa.rdf.jena.model.RDFException
    {
	String colorName = null;
	com.hp.hpl.mesa.rdf.jena.model.StmtIterator iterator = mapObject.listProperties(map_ont.color);
	while (iterator.hasNext())
	    {
		colorName = iterator.next().getObject().toString();
		int hash = colorName.indexOf('#');
		if (hash != (-1))
		    colorName = colorName.substring(hash + 1);
		java.awt.Color color = (java.awt.Color) colors.get(colorName);
		if (color == null)
		    System.err.println("unknown color " + colorName);
		else
		    return color;
	    }

	return java.awt.Color.red; // default
    }

    public DAMLLayer()
    {
    }

    static
    {
	colors.put("black", java.awt.Color.black);
	colors.put("blue", java.awt.Color.blue);
	colors.put("cyan", java.awt.Color.cyan);
	colors.put("gray", java.awt.Color.gray);
	colors.put("green", java.awt.Color.green);
	colors.put("magenta", java.awt.Color.magenta);
	colors.put("orange", java.awt.Color.orange);
	colors.put("pink", java.awt.Color.pink);
	colors.put("red", java.awt.Color.red);
	colors.put("white", java.awt.Color.white);
	colors.put("yellow", java.awt.Color.yellow);
    }
}
