package org.eclipse.stem.ui.ge.kml;

/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
import java.awt.Polygon;
import java.awt.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;

import org.eclipse.stem.ui.ge.GELog;

/**
 * Obtain the BoundingBox info for GoogleEarth 
 * from the Servlet.  
 * GoogleEarth sends the current Screen viewing area to the servlet 
 * as a BBOX parameter.  The SlideShowServlet saves this BBOX string
 * each time it is sent.  
 * 
 * This class runs as a thread and every N seconds makes a request to the
 *  BBoxServlet to access the latest BBOX string and return it.
 *  We then convert it to a bounding box rectangle and make it available 
 *  for access.  KMLDisplay will access it and use it to filter out 
 *  display of Admin areas that are not within the screen Bounding box.
 * 
 *
 */
public class BBoxInfo implements Runnable {
    
	private static final long SLEEPTIME = 10*1000;
	
	/**
	 * id used to access the session data in servlet
	 */
	private String servletId = null;
	/**
	 * url to access the servlet
	 */
	private String servletUrl = null;
	
	/**
	 * BoundingBox last gotten from servlet
	 */
	private static Rectangle bBox = null;
	
	private String bboxOld = null;
	/**
	 * constructor
	 * @param url  URL for the servlet server
	 * @param id Id to identify the servlet session.
	 */
	public BBoxInfo(String url,String id) {
		servletId = id;
		servletUrl = url;
	}
	
	
	/**
	 * This thread will sit in a loop and every N seconds it 
	 * will send a request to the SlideShowServlet to give it
	 * the latest BBox info that was sent from GoogleEarth
	 */
	public void run() {
		
		while (true) {
			try {
				Rectangle bbox = readBBox();
				if (bbox != null) 
					setBBox(bbox);
				Thread.sleep(SLEEPTIME);
			} catch (InterruptedException e) {
				
			}
		}

	}
	/**
	 * readBBox 
	 *   read the GoogleEarth BBox info from the servlet.
	 *   GoogleEarth sends the viewport bounding box to the 
	 *   servlet which stores it.  This will request the servelet
	 *   to forward it to us.
	 *   
	 *
	 * @return BBox Rectangle 
	 */
	public  Rectangle  readBBox() {
		Rectangle bbox = null;
		
		try {
			URL url = new URL(servletUrl);
			URLConnection connect = url.openConnection();
			connect.setUseCaches(false);
			connect.setDoInput(true);
			connect.setDoOutput(true);
			connect.setRequestProperty("Content-type", "application/octet-stream");
			
			  // use ByteArray output
			ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
			DataOutputStream output =
				new DataOutputStream(byteOutput);
			// tell it what we want and give key to info
			output.writeUTF("BBOX "+servletId);
			
			output.flush();
			byte[] buf = byteOutput.toByteArray();
			
			connect.setRequestProperty("Content-length", ""+buf.length);
			DataOutputStream dataOutput =
				new DataOutputStream(connect.getOutputStream());
			dataOutput.write(buf);
			dataOutput.flush();
			dataOutput.close();
			
			DataInputStream in = 
				new DataInputStream(connect.getInputStream());
			String stringValue = in.readUTF();
			
			in.close();
			
			
			// TODO convert string to rectangle
			String bboxstr = stringValue.substring(5);
			if (! bboxstr.equals(bboxOld)) {
			   GELog.debug(this,"BBOX: "+bboxstr);
			   // convert to Bounding box rectangle
			   bbox = getBBox(bboxstr);
			   GELog.debug(this,"bbox: "+bbox);
			   bboxOld = bboxstr;
			}
			
			
		} catch (MalformedURLException e) {	
			
			GELog.debug(e.getMessage());
		
			//error ="ERROR Invalid URL "+urlstr;
			
		} catch (IOException e) {			
			GELog.debug(e.getMessage());
			
		}
		
		return bbox;
	}
	/**
	 * Given a BBOX string returned from GoogleEarth 
	 * generate the BoundingBox rectangle.
	 * GoogleEarth returns the BBOX in the following format.
	 *  BBOX x1,y1,x2,y2
	 *  where x1,y1 are latitude/longitude of bottom left point 
	 *  and x2,y2 are latitude/longitude of top right point
	 *  Values are doubles like -114.14578934
	 *   
	 * Note that the Rectangle coordinate system uses the origin  
	 * (0,0) as the top left of the screen, 
	 *  with the x and y values increasing as they move to the right 
	 *  and down respectively.
	 *  
	 * @param String containing BBOX info from GE
	 * @return Rectangle
	 */
	private static Rectangle getBBox(String bboxString) {

		Rectangle bBox = null;

		Polygon polygon = new Polygon();
		//GELog.debug(BBoxInfo.class, "BBOX: " + bboxString);

		StringTokenizer st = new StringTokenizer(bboxString, ",");
		if (st.countTokens() == 4) {
			// GE returns the BBox as bottom left, top right coordinates
			// we have to translate to top left + width+height
			double x1 = Double.parseDouble(st.nextToken());
			double y1 = Double.parseDouble(st.nextToken());
			double x2 = Double.parseDouble(st.nextToken());
			double y2 = Double.parseDouble(st.nextToken());
			double[] longitudes = { x1, x1, x2, x2, x1 };
			double[] latitudes = { y1, y2, y2, y2, y1 };
            // ignore if entire globe
			if (x1 == -180 && x2 == 180) {
				//x1 = -180;
				x2 = 0;
				GELog.debug(BBoxInfo.class,"****** modify BBOX to 180,0 ******");
			}
				
			
			for (int p = 0; p < longitudes.length; p++) {
				double x = longitudes[p];
				double y = latitudes[p];
				int xint = (int) ((x + 180) * 1000);
				int yint = (int) ((y + 90) * 1000);

				polygon.addPoint(xint, yint);
			}
		}
	
		
		bBox = polygon.getBounds();
		
		return bBox;
	}

	/**
	 * @return the bBox
	 */
	public synchronized static Rectangle getBBox() {
		return bBox;
	}


	/**
	 * @param box the bBox to set
	 */
	public synchronized static void setBBox(Rectangle box) {
		bBox = box;
	}
	
	/**
	 * Test  containment of bounding box 1 in Bounding box 2
	 * If any corner of BBox 1 is contained in BBox 2 or any corner
	 * of BBox 2 is contained in BBox 1 then they are adjacent.
	 * 
	 * @param r1  bounding box 1
	 * @param r2  bounding box 2
	 * @return true if adjacent or containment true
	 */
	public static boolean testContainment (Rectangle r1, Rectangle r2) {
		
		// coords of corners of first bounding box
		int xMin1 = r1.x;
		int  xMax1 = r1.x+r1.width;
		int  yMin1 = r1.y-r1.height;
		int  yMax1 = r1.y;
		// test overlap
		if (r2.contains(xMin1,yMin1)) return true;
		if (r2.contains(xMin1,yMax1)) return true;
		if (r2.contains(xMax1,yMax1)) return true;
		if (r2.contains(xMax1,yMin1)) return true;
		
        // coords of corners of second bounding box
		int  xMin2 = r2.x;
		int  xMax2 = r2.x+r2.width;
		int  yMin2 = r2.y-r2.height;
		int  yMax2 = r2.y;
        // test overlap
		if (r1.contains(xMin2,yMin2)) return true;
		if (r1.contains(xMin2,yMax2)) return true;
		if (r1.contains(xMax2,yMax2)) return true;
		if (r1.contains(xMax2,yMin2)) return true;
		 
		return false;
	}
}
