/* File: my_gmaps_lib.js
*  Author: Matthew Lawhead, Oregon Dept. of Fish and Wildlife
*  Purpose:Extends the Google Maps API to provide additional 
*            functionality, especially to GPolylines.
*  Dependencies: 1. gmaps API
*                2. prototype.js
*  Note: This library written using gmaps api v2
*
*  Creation Date: 9/28/2006
*  Last Modified: 9/12/2007
*/           

// We define the function first
function Toolbar() {
}

// To "subclass" the GControl, we set the prototype object to
// an instance of the GControl object
Toolbar.prototype = new GControl();

// Creates a one DIV for each of the buttons and places them in a container
// DIV which is returned as our control element. We add the control to
// to the map container and return the element for the map class to
// position properly.
Toolbar.prototype.initialize = function(map) {
  var container = document.createElement("div");
  this.setStyle_(container);
  map.getContainer().appendChild(container);
  return container;
}


// By default, the control will appear in the top left corner of the
// map with 7 pixels of padding.
Toolbar.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0, 0));
}

// Sets the proper CSS for the given button element.
Toolbar.prototype.setStyle_ = function(button) {
  button.style.textDecoration = "underline";
  button.style.color = "#0000cc";
  button.style.backgroundColor = "white";
  button.style.font = "small Arial";
  button.style.border = "1px solid black";
  button.style.padding = "2px";
  button.style.marginBottom = "3px";
  button.style.textAlign = "center";
  button.style.width = "6em";
  button.style.cursor = "pointer";
}



function zoomToShapes(map, rsites){
	var points = [];
	var shapes = [];

	for(i=0, j=rsites.length; i < j; i++){
		var site = rsites[i];
		if(site.type == "polygon"){shapes.push(site.overlay);} 
		if(site.type == "line"){
			if(site.bufferShape){shapes.push(site.bufferShape.overlay);}
			else{shapes.push(site.overlay);}
		};
		if(site.type == "point"){points.push(site.coords[0])};
	}
			
	var bounds_arr = shapes.invoke("getBounds");
	var bounds = new GLatLngBounds();
	
	bounds_arr.each(function(bnds){
		bounds.extend(bnds.getSouthWest());
		bounds.extend(bnds.getNorthEast());
	});
	
	
	points.each(function(pt){
		bounds.extend(pt);
	}); 
	
	if(rsites && rsites.length > 0){
		map.setZoom(map.getBoundsZoomLevel(bounds));
		map.setCenter(bounds.getCenter());
	}

}


function zoomToPoints(map, points){
	// console.dir(points);
	var bounds = new GLatLngBounds();
	for(var i=0, j=points.length; i<j; i++){
		bounds.extend(points[i]);
	};
	map.setZoom(map.getBoundsZoomLevel(bounds));
	map.setCenter(bounds.getCenter());
}

// CUSTOM INFO WINDOW overlay
function RegistryInfoWindow(marker, background_img, tail_img, 
			    html_content, html_header, template){
    this.marker_ = marker;
    this.anchor_ = marker.getLatLng(); // GLatLng
    this.background_ = background_img; // Image object used to store width and height
    this.tail_ = tail_img;             // Image Object
    this.content_ = html_content;
    this.header_ = html_header;
    var temp_name = "IW_" + this.anchor_.lat() + "_" + this.anchor_.lng();
    this.name = temp_name.gsub(/\.|-/, "");
    this.first_time = true;

    // default template
  var temp = '<div id="overlay_tab" class="inside">';
    temp += '<div class="header"></div>';
    temp += ' <div id="info_summary" class="content"></div>';
    temp += '</div>';
    temp += '<div class="bottom"></div>'; 
    this.template_ = template || temp; 
}

RegistryInfoWindow.prototype = new GOverlay();


RegistryInfoWindow.prototype.initialize = function(map) {
    // test to see if an info window already exists. if not, create one.
    if (!$('iw_overlay')){
	var temp_div = document.createElement("div");
	temp_div.id="iw_overlay";
	document.body.appendChild(temp_div);
    }

    var div = $('iw_overlay');
    div.innerHTML = this.template_;
   
    var content_div = div.descendants().find(function(elmt){
	    return elmt.className == "content";});
    var header_div =  div.descendants().find(function(elmt){
	    return elmt.className == "header";});
    
    content_div.innerHTML = this.content_;
    header_div.innerHTML = this.header_;
    
    var close = document.createElement("span");
    close.className = "close";
    //    close.innerHTML = '<a href="#" onClick="document.getElementById(\''+ this.name +'\')._iw.remove();return false;"></a>'
    close.innerHTML = '<a href="#" onClick="document.getElementById(\''+ this.name +'\')._marker.closeRegistryInfoWindow(); return false;"></a>'
    div.appendChild(close);
    
    var close_link = div.getElementsByClassName("close")[0].getElementsByTagName("a")[0];
    close_link.id = this.name;
    //    close_link._iw = this;
    close_link._marker = this.marker_;

    map.getPane(G_MAP_FLOAT_PANE).appendChild(div);       
    
    this.div_ = div;
    this.header_div_ = header_div;
    this.content_div_ = content_div;
    this.map_ = map;
  }


// Remove the main DIV from the map pane
RegistryInfoWindow.prototype.remove = function() {
  this.div_.parentNode.removeChild(this.div_);
}


RegistryInfoWindow.prototype.copy = function() {
    return new RegistryInfoWindow(this.anchor_, this.background_, this.tail_, 
				  this.content_, this.header_, this.template_);
}

// Redraw the on the current projection and zoom level
RegistryInfoWindow.prototype.redraw = function(force) {
  // Only need to redraw if the zoom level has changed
    if (!force) return;
    if ($('iw_overlay')){
		var x_offset = 176; // 168 for default icon
		var y_offset = 10; // 30 for default icon
	
		var map_pt = this.map_.fromLatLngToDivPixel(this.anchor_);
  
		var y_loc = parseInt(map_pt.y) - this.div_.offsetHeight - y_offset;
		var x_loc = parseInt(map_pt.x) - x_offset;

		//	var map_controls = this.map_.getElementsByClassName("gmnoprint");


		this.div_.style.top = y_loc  + "px";
		this.div_.style.left = x_loc + "px";
	

		if (this.first_time){
		    // this.map_.panTo(this.anchor_);
			var new_pt = new GPoint(parseInt(map_pt.x), parseInt(map_pt.y) - 15);
			this.map_.panTo(this.map_.fromDivPixelToLatLng(new_pt));
			
		    this.first_time = false;
		}
	// center on infowindow
	//var pixel = new GPoint(x_loc + 194, y_loc + 108.5);
	//this.map_.panTo(this.map_.fromDivPixelToLatLng(pixel));
	// else map.setCenter(map.fromDivPixelToLatLng(pixel));
    }
}



    // CUSTOM OVERLAY (OverlaySwitch)
    function OverlaySwitch(overlays){
	this.overlays = overlays;
    }
    
    OverlaySwitch.prototype = new GControl(true, true);
    OverlaySwitch.prototype.getDefaultPosition = function(){
	return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 7));
    }
    OverlaySwitch.prototype.initialize = function(map){
	var overlayDiv = document.createElement("div");
	overlayDiv.id = "overlays";
	
	var overlaysHeader = "<span id=\"overlays_button\" onclick=\"slide('overlays_selection'); return false;\">Registry Overlays</span>";
	overlayDiv.innerHTML = overlaysHeader;
	
	var overlaySelection = document.createElement("span");
	overlaySelection.id = "overlays_selection";
	overlaySelection.style.display = "none";
	
	var ulist = document.createElement("ul");
	
	this.overlays.each(function(overlay){
		var listItem = document.createElement("li");
		
		// name property is a custom attribute set in wms-gs.js -> createWMSTileLayer method
		var name = overlay.getTileLayer().name;
		var selector = document.createElement("input");
		selector.type = "checkbox";
		//		selector.class = "overlay";
//		selector.setAttribute("class", "overlay");
		selector.className = "overlay";
		selector.name = name;
		selector.value = name;
		selector.id = name;
		selector.onclick = function(){
		    if(this.checked){
			map.addOverlay(overlay);
		    }
		    else{
			map.removeOverlay(overlay);
		    }
		}
		
		// Sam's doing...
		var selectorKey = document.createElement("img");
		var name_class = name.replace(/[^a-zA-Z 0-9 _]+/g,'').toLowerCase().split(" ").join("_");
  	selectorKey.setAttribute("src", "/images/keys/overlay-" + name_class + ".gif");
		
		// END Sam's doing
		
		
		var selectorLabel = document.createElement("label");
		selectorLabel.setAttribute("for", name);
		var name_class = name.replace(/[^a-zA-Z 0-9 _]+/g,'').toLowerCase().split(" ").join("_");
		// selectorLabel.setAttribute("class", name_class);
		selectorLabel.className = name_class;
		selectorLabel.appendChild(document.createTextNode(name));	    
		
		listItem.appendChild(selector);
		listItem.appendChild(selectorKey);
		listItem.appendChild(selectorLabel);
		ulist.appendChild(listItem);
		
	    });
	
	overlaySelection.appendChild(ulist);
	overlayDiv.appendChild(overlaySelection);
	
	map.getContainer().appendChild(overlayDiv);
	return overlayDiv;//container;
    }



// CUSTOM OVERLAY (COAs)

function MapOverlayControl(mLayer) {
    this.globals = {mapLayer: mLayer,
                    toggle: true};
}
MapOverlayControl.prototype = new GControl();

// Creates a one DIV for each of the buttons and places them in a container
// DIV which is returned as our control element. We add the control to
// to the map container and return the element for the map class to
// position properly.
MapOverlayControl.prototype.initialize = function(map) {
  var G = this.globals;
  var container = document.createElement("div");

  var toggleDiv = document.createElement("div");
  this.setButtonStyle_(toggleDiv);
  container.appendChild(toggleDiv);
  toggleDiv.appendChild(document.createTextNode("Priority Areas"));
  
  GEvent.addDomListener(toggleDiv, "click", function() {
    if(G.toggle){  
        map.addOverlay(G.mapLayer);
        G.toggle = false;      
    } 
    else{
        map.removeOverlay(G.mapLayer);
        G.toggle = true;
    }
    
  });

  map.getContainer().appendChild(container);
  return container;
}

// By default, the control will appear in the top left corner of the
// map with 7 pixels of padding.
MapOverlayControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(7, 7));
}

// Sets the proper CSS for the given button element.
MapOverlayControl.prototype.setButtonStyle_ = function(button) {
  button.style.color = "#0000cc";
  button.style.backgroundColor = "white";
  button.style.font = "small Arial";
  button.style.border = "1px solid black";
  button.style.padding = "2px";
  button.style.marginBottom = "3px";
  button.style.textAlign = "center";
  button.style.width = "6em";
  button.style.cursor = "pointer";
}


// code to detect overlap with other elements
/* function get_bounds(top left width height){ */
/*     var pt = new Object(); */
/*     var bounds = new Object(); */
/*     bounds.top_left = {x: left, y:top}; */
/*     bounds.bottom_right = {x: (left + width), y: (top + height)};  */
/*     return bounds; */
/* } */

/* function between(x lower upper){ */
/*     return (x > lower) && (x < upper); */
/* } */

/* function point_in_bounds_p(point, bounds){ */
/*     var cond1 = between(point.x,  */
/* 			bounds.top_left.x,  */
/* 			bounds.bottom_right.x); */
/*     var cond2 = between(point.y, */
/* 			bounds.top_left.y, */
/* 			bounds.bottom_right.y); */
/*     return cond1 && cond2; */
/* } */

/* function intersect_p(bounds1, bounds2){ */
/*     return point_in_bounds_p(bounds1.top_left, bounds2) ||  */
/* 	point_in_bounds_p(bounds1.bottom_right, bounds2) || */
/* 	point_in_bounds_p(bounds2.top_left, bounds1) ||  */
/* 	point_in_bounds_p(bounds2.bottom_right, bounds1);   */
/* } */

/* function elements_intersect(elt1, elt2){ */
/*     var bounds1 = get_bounds(elt1.style.top, elt1.style.left, */
/* 			     elt1.style.width, elt1.style.height); */
/*     var bounds2 = get_bounds(elt2.style.top, elt2.style.left, */
/* 			     elt2.style.width, elt2.style.height); */
/*     return intersect_p(bounds1, bounds2); */
/* } */

// Functions for creating an encoded GPolyline; 
// Adapted from http://www.google.com/apis/maps/documentation/polylineutility.html


function getVertices(){
  //Returns an array of vertices (GPoint objects) for a GPolyline
    var n = this.getVertexCount();
    var arr = new Array();

  //  if (this.isPolygon()) n = n - 1; //CHANGED 2/13/07
    for(i=0; i < n; i++){
        arr.push(this.getVertex(i));
    }
    return arr;
}

GPolyline.prototype.getVertices = getVertices;
GPolygon.prototype.getVertices = getVertices;


function lastVertex(){
    var n = this.getVertexCount();
    return this.getVertex(n - 1);
}

GPolyline.prototype.lastVertex = lastVertex;
GPolygon.prototype.lastVertex = lastVertex;

GPolyline.prototype.isPolygon = function(){
  // Tests to see whether a line is a polygon;
  // A line is considered a polygon when its first and last vertices are equal
    var arr = this.getVertices();
    if(arr.length > 1 &&
       arr[0].equals(arr[arr.length - 1])){
       return true;
    }
    else{return false;}
}

/** 
//polygon function: assumes arr is the vertices of a polygon
function getNextIndex(arr, i){
    if(i == (arr.length - 2)) return 0; //last visible element of polygon
    else return i+1; //default behavior
}

//polygon function: assumes arr is the vertices of a polygon
function getPreviousIndex(arr, i){
    if(i == 0) return arr.length - 2;
    else return i - 1;
}

**/

// Function takes a click point (GLatLng), finds the nearest line,
// and inserts the point between the two verts which comprise the line.
GPolyline.prototype.insertVertex = function(point){
    var verts = this.getVertices();
    var height, index, temp, a, b, c; 
    var firstValid = true;
    
    //go through all elements except for last
    for(i=0; i< verts.length - 1; i++){
        // find the sides of a triangle
        a = verts[i].distanceFrom(verts[i+1]); //distance from this vertex to the next
        b = verts[i].distanceFrom(point); //distance from vert to click point
        c = verts[i+1].distanceFrom(point); //distance from next vert to click point
          
        if(a > b && a > c){ //if triangle base is not the longest side, do nothing
            temp = triangleHeight(a, b, c); 
            
            //initialize the lowest triangle height to first valid triangle
            if (firstValid) {height = temp; firstValid = false;} 
            //track whichever height distance is lowest
            if (temp <= height){
                height = temp;
                index = i + 1;
            }
        }
    }
    if(index != null) verts.splice(index, 0, point); 
    return verts;
}
