/*
 * @(#)MapTest.java	0.1 14/12/1999
 *
 */

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

/**
 * Draws a map based on lat/long data.
 * I dunno what this will evolve into.
 * At the moment it's something for me to learn Java off.
 * Some ideas:
 *   o animated tidal display
 *     (woah james - ridiculous - but was the initial idea)
 *     It would be GREAT fun to watch ripples of tides washing round
 *     the coast but we need lots of algorithms (e.g. from xtide) and
 *     also tidal harmonics data (harder to get hold of for Ireland)
 *   o Display map/gif in background, show routes or places of interest.
 *     Now this is not half a bad idea.  Could be quite nice for Cobh page.
 *     Could also make customised maps/routes easily. ... sounds like killer ap.
 *     Goes well with my wish to ascii-map the world .... or, well, at least Ireland,
 *     ... well, perhaps a bit of Cobh/Dublin would do to start with.
 *
 * Can be run either as a standalone application by
 * typing "java MapTest" or as an applet in Netscrape/whatever.
 */

public class MapTest extends Applet {
    MapControls controls;   // The controls for configuring the map & location display
    MapCanvas canvas;       // The drawing area to display the map (and controls)

    public void init() {
	setLayout(new BorderLayout());
	canvas = new MapCanvas();
	add("Center", canvas);
	add("South", controls = new MapControls(canvas));
    }

    public void destroy() {
        remove(controls);
        remove(canvas);
    }

    public void start() {
	controls.setEnabled(true);
    }

    public void stop() {
	controls.setEnabled(false);
    }

    public void processEvent(AWTEvent e) {
        if (e.getID() == Event.WINDOW_DESTROY) {
            System.exit(0);
        }
    }

    public static void main(String args[]) {
	Frame f = new Frame("MapTest");
	MapTest	MapTest = new MapTest();

	MapTest.init();
	MapTest.start();

	f.add("Center", MapTest);
	f.setSize(300, 300);
	f.show();
    }

    public String getAppletInfo() {
        return "Draws a map based on lat/long data, I dunno what this will evolve into.";
    }
} //class MapTest extends Applet


class MapControls extends Panel
                  implements ActionListener, MouseMotionListener {
    TextField s;
    TextField e;
    MapCanvas canvas;

    public MapControls(MapCanvas canvas) {
	Button b = null;

	this.canvas = canvas;
        this.canvas.addMouseMotionListener(this);

	add(s = new TextField("0", 4));
	add(e = new TextField("45", 4));
	b = new Button("Fill");
	b.addActionListener(this);
	add(b);
	b = new Button("Draw");
	b.addActionListener(this);
	add(b);
	b = new Button("Quit");
	b.addActionListener(this);
	add(b);
    }

    public void actionPerformed(ActionEvent ev) {
	String label = ev.getActionCommand();
        //Object src=ev.getSource();

        if (label.equals("Quit")) {
          System.out.println("Quit - user request");
          System.exit(0);
        }

        if (label.equals("Draw")) {
          System.out.println("Draw");
          //canvas.ldraw();
        }

	canvas.redraw();
	// pass info from controls to canvas.redraw like this:
           //label.equals("Fill"), (boolean)
           //Integer.parseInt(s.getText().trim()),  Integer.parseInt(e.getText().trim()));
    }

    public void mouseMoved(MouseEvent ev) {
        System.out.println("Mouse "+ev.getX()+","+ev.getY());
        s.setText(" "+canvas.getsLat(ev.getX()));
        e.setText(" "+canvas.getsLong(ev.getY()));
        //s.repaint();
        //e.repaint();
    }

    public void mouseDragged(MouseEvent ev) {
    }

} // class MapControls extends Panel


class MapCanvas extends Canvas {

    public int abs (int i) {   //pathetic, in java.lang.math
        if (i>0) return (i);
        else return (-i);
    }

    double minlat,maxlat,minlong,maxlong;
    double latd,longd;
    Rectangle r;
    int rheight, rwidth; // real h/w (less space for controls/...)

    public void init(){
      initLocations();
      r = getBounds();
      // latd, longd used to calculate actual canvas coordinates
      // Canvas: 0, 0, r.height-32, r.width-50
      // Map: minlong, minlat, maxlong, maxlat
      rheight=r.height-32; // less 32 at bottom for controls
      rwidth=r.width-50; // less 50 at right for names
      latd=(double)(rheight)/(maxlat-minlat); // less 50 at right for names
      longd=(double)(rwidth)/(maxlong-minlong); // less 32 at bottom for controls
      // canvas x,y  =  (xory - min(latorlong) ) * (latorlong)d
      System.out.println("Init Win: " + r.height + "," + r.width + ":" + latd + "," + longd);
      System.out.println("Lat: " + 0 + "," + rwidth + ":" + maxlat + "," + minlat);
      System.out.println("Long: " + 0 + "," + rheight + ":" + maxlong + "," + minlong);
    }

    // convert lat/long (double) to screen coordinates (int)
    public int getX(double lat) {
        return (int)((lat-minlat)*latd);
    }

    public int getY(double lon) {
        return (int)((lon-minlong)*longd);
    }

    public double getLat(int x) {
        return (minlat+((double)x)/latd);
    }

    public double getLong(int y) {
        return (minlong+((double)y)/longd);
    }

    public String getsLong(int y) {
        String slong,maybezero;
        double rlong=getLong(y);
        slong=(rlong<0)?"N":"S";
        int longdeg=(int)rlong;
        int longmin=abs((int)((rlong-(double)longdeg)*60));
        maybezero=(longmin<10)?"0":"";
        longdeg=abs(longdeg);
        return (""+longdeg+"° "+maybezero+longmin+"'"+slong);    // &#176 == °
    }

    public String getsLat(int x) {
        String slat,maybezero;
        double rlat=getLat(x);
        slat=(rlat<0)?"W":"E";
        int latdeg=(int)rlat;
        int latmin=abs((int)((rlat-(double)latdeg)*60));
        maybezero=(latmin<10)?"0":"";
        latdeg=abs(latdeg);
        return (""+latdeg+"° "+maybezero+latmin+"'"+slat);
    }

    Font font;

    public void redraw() {
	repaint();
    }

    public void ldraw(Graphics g) {
        int x1=getX(locations[0].lati);
        int y1=getY(locations[0].longi);
	for (int i = 1; i < locations.length; i++) {
            Location l=locations[i];
            int x=getX(l.lati);
            int y=getY(l.longi);
    	    g.setColor(Color.yellow);
	    g.drawLine(x1,y1,x,y);
            x1=x; y1=y;
        }
    }

    public void paint(Graphics g)
    {
        // init canvas coordiante info
        init();

        // Lines of Longitude =====
	for (int l=(int)minlong;l<(int)maxlong;l++) {
	    int sx = 2;
	    int sy = getY(l); //(int)((l-minlong) * longd);
            System.out.println("Long: " + l + " " + sy);
   	    g.setColor(Color.red);
	    g.drawLine(0, sy, rwidth, sy);
	    g.setColor(Color.black);
	    g.setFont(font);
	    g.drawString(" "+abs(l), sx, sy);
	}

        // Lines of Latitude ||||||
	for (int l=(int)minlat;l<(int)maxlat;l++) {
	    int sy = 10;
	    int sx = getX(l);
            System.out.println("Lat: " + l + " " + sx);
   	    g.setColor(Color.red);
	    g.drawLine(sx, 0, sx, rheight);
	    g.setColor(Color.black);
	    g.setFont(font);
	    g.drawString(" "+abs(l), sx, sy);
	}

        // For connecting lines between locations, oldx,oldy init
        Location l=locations[0];
        int oldx=getX(l.lati); //(int)((l.lati-minlat)*latd);
        int oldy=getY(l.longi); //(int)((l.longi-minlong)*longd);
        System.out.println("First Loc: " + l.name + " " + oldx + "," + oldy + " " + l.lati + "," + l.longi);

        //for (Location l in locations) {
	for (int i = 0; i < locations.length; i++) {
            l=locations[i];
            // convert lat/long (double) to screen coordinates (int)
            int x=getX(l.lati); //(int)((l.lati-minlat)*latd);
            int y=getY(l.longi); //(int)((l.longi-minlong)*longd);
            // Mark location with name and little green +
    	    g.setColor(Color.black);
	    g.drawString(locations[i].name,x,y+8);
   	    g.setColor(Color.green);
	    g.drawLine(x-1,y,x+1,y);
	    g.drawLine(x,y-1,x,y+1);
            // debug info
            //System.out.println("Loc: " + l.name + " " + x + "," + y + " " + l.lati + "," + l.longi);
            // Draw green connecting lines between locations (rough country outline)
            g.drawLine(x,y,oldx,oldy);
            oldx=x; oldy=y;
        }

        // Draw lines between locations
        ldraw(g);
    }

    Location locations[]=getLocationInfo();
    final static int nirl=1;
    final static int irl=0;

    public void initLocations(){
      minlat=locations[0].minlati;
      maxlat=locations[0].maxlati;
      minlong=locations[0].minlongi;
      maxlong=locations[0].maxlongi;
    }

/* coordinates appropriated from: http://www.tides.com/bareg1.htm
xtide harmonics http://www.universe.digex.net/~dave/xtide/harmonics.html
Thanks.
*/

  private Location[] getLocationInfo()
  {
  Location[] info =
    {
      new Location(nirl, "Warrenpoint", 54, 6, "N", 6, 15, "W"),
      new Location(nirl, "Kilkeel", 54, 3, "N", 5, 59, "W"),
      new Location(nirl, "Ardglass", 54, 16, "N", 5, 36, "W"),
      new Location(nirl, "Quoile Barrier", 54, 22, "N", 5, 41, "W"),
      new Location(nirl, "Portavogie", 54, 28, "N", 5, 26, "W"),
      new Location(nirl, "Belfast", 54, 36, "N", 5, 55, "W"),
      new Location(nirl, "Carrickfergus", 54, 43, "N", 5, 48, "W"),
      new Location(nirl, "Larne", 54, 51, "N", 5, 47, "W"),
      new Location(nirl, "Cushendun", 55, 8, "N", 6, 2, "W"),
      new Location(nirl, "Ballycastle Bay", 55, 12, "N", 6, 14, "W"),
      new Location(nirl, "Portrush", 55, 12, "N", 6, 40, "W"),
      new Location(nirl, "River Foyle (Lisahally)", 55, 3, "N", 7, 16, "W"),
      new Location(nirl, "Londonderry", 55, 0, "N", 7, 19, "W"),

      new Location(irl, "Inishtrahull", 55, 26, "N", 7, 14, "W"),
      new Location(irl, "Portmore", 55, 22, "N", 7, 20, "W"),
      new Location(irl, "Fanad Head", 55, 16, "N", 7, 38, "W"),
      new Location(irl, "Burtonport", 54, 59, "N", 8, 26, "W"),
      new Location(irl, "Killybegs", 54, 38, "N", 8, 26, "W"),
      new Location(irl, "Killala Bay (Inishcrone)", 54, 13, "N", 9, 6, "W"),
      new Location(irl, "Broadhaven", 54, 16, "N", 9, 53, "W"),
      new Location(irl, "Blacksod Quay", 54, 6, "N", 10, 3, "W"),
      new Location(irl, "Galway", 53, 16, "N", 9, 3, "W"),
      new Location(irl, "Carrigaholt", 52, 36, "N", 9, 42, "W"),
      new Location(irl, "Kilrush", 52, 38, "N", 9, 30, "W"),
      new Location(irl, "Tarbert", 52, 35, "N", 9, 22, "W"),
      new Location(irl, "Knights Town", 51, 56, "N", 10, 18, "W"),
      new Location(irl, "Castletown Bearhaven", 51, 39, "N", 9, 54, "W"),
      new Location(irl, "Bantry", 51, 41, "N", 9, 28, "W"),
      new Location(irl, "Skull", 51, 31, "N", 9, 32, "W"),
      new Location(irl, "Baltimore", 51, 29, "N", 9, 23, "W"),
      new Location(irl, "Castletownshend", 51, 32, "N", 9, 10, "W"),
      new Location(irl, "Kinsale", 51, 42, "N", 8, 31, "W"),
      new Location(irl, "Roberts Cove", 51, 45, "N", 8, 19, "W"),
      new Location(irl, "Cobh", 51, 51, "N", 8, 18, "W"),
      new Location(irl, "Ringaskiddy", 51, 50, "N", 8, 19, "W"),
      new Location(irl, "Youghal", 51, 57, "N", 7, 51, "W"),
      new Location(irl, "Dunmore East", 52, 9, "N", 6, 59, "W"),
      new Location(irl, "Cheekpoint", 52, 16, "N", 7, 0, "W"),
      new Location(irl, "Kilmokea Point", 52, 17, "N", 7, 0, "W"),
      new Location(irl, "New Ross", 52, 24, "N", 6, 57, "W"),
      new Location(irl, "Baginbun Head", 52, 10, "N", 6, 50, "W"),
      new Location(irl, "Rosslare Harbour", 52, 15, "N", 6, 21, "W"),
      new Location(irl, "Wexford Harbour", 52, 20, "N", 6, 27, "W"),

      new Location(irl, "Courtown", 52, 39, "N", 6, 13, "W"),
      new Location(irl, "Arklow", 52, 47, "N", 6, 8, "W"),
      new Location(irl, "Wicklow", 52, 59, "N", 6, 2, "W"),
      new Location(irl, "Dublin (North Wall)", 53, 21, "N", 6, 13, "W"),
      new Location(irl, "Howth", 53, 23, "N", 6, 4, "W"),
      new Location(irl, "Malahide", 53, 27, "N", 6, 9, "W"),
      new Location(irl, "River Boyne Bar", 53, 43, "N", 6, 14, "W"),

      new Location(nirl, "Warrenpoint", 54, 6, "N", 6, 15, "W"),
    };
  return info;
  }

} // class MapCanvas extends Canvas


class Location {
  public int country;
  public String name;
  public double lati;
  public double longi;
  // longi and lati (units: degrees)

  static int init=0;
  public static double maxlati, minlati, maxlongi, minlongi;

  Location(int where, String lname, int longdeg, int longmin, String olong, int latdeg, int latmin, String olat)
  {
    country=where;
    name=lname;
    lati=(double)latdeg+((double)latmin)/60.0;
    longi=(double)longdeg+((double)longmin)/60.0;
    if (olat=="W") lati=-lati;
    if (olong=="N") longi=-longi;    // this way to agree with canvas origin at 0,0 on top left

    if (init==0) {
      maxlati=minlati=lati;
      maxlongi=minlongi=longi;
      init=1;
    } else {
      if (lati>maxlati) maxlati=lati;
      if (lati<minlati) minlati=lati;
      if (longi>maxlongi) maxlongi=longi;
      if (longi<minlongi) minlongi=longi;
    }

  }

} // class Location
















