var theForm;
var acceptForm;

// Set of functions to execute at window.onload
window.onload = function(){
    theForm = window.document.forms["subscription"];
    formCheck();        //defined in subscription.js
    setMapDivLayout();
    loadMap();
    
    if (theForm.geoLat.value == "" || theForm.geoLat.value == "0"
       || theForm.geoLng.value == "" || theForm.geoLng.value == "0"){
//        geoLocateAddress();
    } else {
        point = new GLatLng(parseFloat(theForm.geoLat.value), 
                             parseFloat(theForm.geoLng.value));
        locate(point, ZOOMLEVEL);
        updateNeighbors();
    }
    theForm.address1.onchange = theForm.address2.onchange = theForm.city.onchange = theForm.zip.onchange= theForm.state.onchange = function(){
        geoLocateAddress();
    }
    theForm.maxDistInMi.onchange = function(){
        updateNeighbors();
    }
}

/*
 * Check if the user accepted the agreement
 */
function formCheck(){
    acceptForm = window.document.forms["acceptForm"];
    acceptForm.accept.onclick = function (){
        processCheck();
    }
    processCheck();
}

/* Execute this when use accepts agreemeent
 * 
 */ 
function processCheck(){
    if (optionChecked()){
        enabletheFormFields();
        showForm();
        hideIntro();
        resetBodyHeight();
    }else{
        disabletheFormFields();
        hideForm();
        showIntro();
    }
    theForm.accept.value=acceptForm.accept.checked;
}
function showForm(){
    theForm.style.display = "block";
    if (map && map.isLoaded()) map.checkResize(); //This fixed the partial map display
}
function hideForm(){
    theForm.style.display = "none";
}
function showIntro(){
    MM_showHideLayers2("intro", "", "show");
}
function hideIntro(){
    MM_showHideLayers2("intro", "", "hide");
}
function optionChecked(){
    return acceptForm.accept.checked;
}
function disabletheFormFields(){
    changeDisabled(true);
}
function enabletheFormFields(){
    changeDisabled(false);
}
function changeDisabled(newValue){
    for (var i =0; i < theForm.elements.length; i++){
        theForm.elements[i].disabled = newValue;
    }
}
/*
 * This is executed when user presses the Save Data button
 * 
 */
function sendForm(form){
    if (form.minRainOption[0].checked){
//        form.minRainIn.value = "-1.0";
    } else {
//        form.minRainIn.value = form.minRainInTmp.value;
    }
    form.minRainIn.value = form.minRainInTmp.value;
    
    //Submit form
    form.submit();
}

function resetBodyHeight(){
  changeDivWHStyles(MM_findObj('bodydiv'), "" , "1400px");    
}

/****** CODE FOR MAP *****/
  
  var gLatFound = 0;   //latitude found by google
var gLongFound = 0;    //longitude found by google
var PRECISION = 10;
var ZOOMLEVEL = 18;
var map;
var geocoder;
var marker;
var completeAddress = "";


function validNumberStr(numberAsString){
    if (numberAsString == ""
        || isNaN(parseFloat(numberAsString))
        || parseFloat(numberAsString) == 0)
        return false;
    else
        return true;
}
function setMapDivLayout(){
    obj = MM_findObj("mapLayer");
//    obj.style.width = "53em";
//    obj.style.height = "45em";
}
function loadMap() {
      if (GBrowserIsCompatible()) {
        mapObj = document.getElementById("mapLayer");
        map = new GMap2(mapObj);
        map.setCenter(new GLatLng(34, -112), 9);
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.setMapType(G_HYBRID_MAP);
        map.enableScrollWheelZoom();
        GEvent.addListener(map, "click", function(overlay, point) {
          if (overlay) {
          } else if (point) {
//                map.panTo(point);
                locate(point);
          }
        });
        map.addControl(new TextualZoomControl());
      }
}

/***** GEOLOCATE CODE *****/
/**
 * Google's geo code requires all basic fields of an address: number, street, city, state, and zip
 * So we need to figure if we got all of them
 * In this function we build a text string of the full address to geo-locate
 *
 */
function getAddressToUse(){
    //This was initially created to selectively send parts of address but Google does not allow it,
    //thus we ended up sending the whole address if any field is missing this function returns an empty string
    if (theForm.address1.value == ""){
        //Do we have city and state
        if (theForm.city.value == ""
            || theForm.state.selectedIndex ==0){
            //Do we have zip?
            if (theForm.zip.value == ""){
                return "";
            } else {
//                return theForm.zip.value;
                return "";
            }
        } else {
//            return theForm.city.value + ", " + theForm.state.options[theForm.state.selectedIndex].value;
            return "";
        }
    } else {
        //We need city and state and zip
        if (theForm.city.value == "" 
                || theForm.state.selectedIndex == 0
                || theForm.zip.value == ""){
                return "";
        } else {
            return theForm.address1.value 
                + " " + theForm.address2.value 
                + " " + theForm.city.value 
                + ", " + theForm.state.options[theForm.state.selectedIndex].value + " " 
                + theForm.zip.value;
        }
    }
}
/*
 *Gets tha completeAddress to geolocate and sends it to a function that handles it
 *
 */
function geoLocateAddress(){
//    completeAddress += "" + subs["address1"];
//    completeAddress += " " + subs["address2"];
//    completeAddress += " " + subs["city"];
//    completeAddress += ", " + subs["state"];
//    completeAddress += " " + subs["zip"].substr(0,5);
    completeAddress = getAddressToUse();
//    alert(completeAddress);
    if (completeAddress != "") googleGeoCode(completeAddress);
}
function googleGeoCode(params){
//    alert("="+params+"=");
    geocoder = new GClientGeocoder();
    geocoder.getLatLng(completeAddress,
    function(point) {
        processGeocoderResp(point);
    }
    );
}
/*
 *This function is executef upon completion of Google's request
 *if nothing was found then point is null
 */
function processGeocoderResp(point){
    if (!point) {
        alert("Could not locate your address:\n" + completeAddress + "\n\nPlease locate in on the map and click over your property when you find it.");
    } else {
        locate(point, ZOOMLEVEL);
        gLatFound = point.lat();
        gLongFound = point.lng();
        updateNeighbors();
    }
}
//Center, add marker and change form fields
function locate(point, zoomL){
    if (typeof zoomL != "undefined"){
        map.setZoom(zoomL);
    }
    map.panTo(point);
    createMarker(point);
    setCoords(point);
    return point;
}

//Set fields and update labels
function setCoords(point){  
    point = new GLatLng(point.lat().toFixed(PRECISION), point.lng().toFixed(PRECISION));
    theForm.geoLat.value = point.lat();
    theForm.geoLng.value = point.lng();
}

//adds marker at particular point
function createMarker(point){
    //first remove old one
    if (marker) map.removeOverlay(marker);
    
    //add it to map
    marker = new GMarker(point);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(completeAddress);
    });
    

//    GEvent.addListener(marker, "click", function() {});
    map.addOverlay(marker);
//    marker.openInfoWindowHtml(completeAddress);
    
}
var polyline; //this variable is use to figure the extend of the neighboring RainLoggers

/*
*The updateNeighbors function figures how many neighboring RainLoggers there are based on
*- the lat/long of the address (needs to have a value on the according fields)
*- the farthese distance selected by the user
*Upon figuring this, it updates the label showing this information. And shows the markers of the 
*loggers on the map.
*This function uses AJAX to execute a Servlet that returns the total number of neighbors as well
*as an XML identifyng each with: lat, long, date of registration, date of last reading, and count of all entries.
*Hopefully, this info will help the subcriber determine if he/she wants a larger/shorter area to consider
*/
function updateNeighbors(){

  if (theForm.geoLat.value == "" ||
      theForm.geoLng.value == "" ||
      theForm.maxDistInMi.options[theForm.maxDistInMi.selectedIndex].value == "") return;
  if (map)  map.clearOverlays();
  if (marker) createMarker(marker.getPoint());
  
   var url = "/usprn/FindNeighboringRainLoggers?lat=" + theForm.geoLat.value + 
       "&lng=" + theForm.geoLng.value + 
       "&distance=" + theForm.maxDistInMi.options[theForm.maxDistInMi.selectedIndex].value;
GDownloadUrl(url, function(data, responseCode) {
  var xml = GXml.parse(data);
  var neighbors = xml.documentElement.getElementsByTagName("neighbors");
  if (neighbors.length > 0){
      var total = neighbors[0].getAttribute("count");
      MM_setTextOfLayer("totalNeighbors", "", "Found " + total + " active RainLoggers at " + theForm.maxDistInMi.options[theForm.maxDistInMi.selectedIndex].value + " mi.")
  }
  var markers = xml.documentElement.getElementsByTagName("marker");
  var polylineVertex = new Array();
  for (var i = 0; i < markers.length; i++) {
    var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                            parseFloat(markers[i].getAttribute("lng")));
    map.addOverlay(createNMarker(point, markers[i]));
    polylineVertex[i] = point;
  }
  polyline = new GPolyline(polylineVertex, "#ff0000", 10);
//  map.setZoom(map.getBoundsZoomLevel(polyline.getBounds())-1);
  xml=null;
  neighbors = null;
  markers = null;
});  
}

//Creates a marker for a Neighboring RainLogger.... adds information about in on an InfoWindowHtml
function createNMarker(point, markerTag){
    var markerInfo = "Date registered: " + markerTag.getAttribute("registered") + "<br/>" +
        "Total readings: " + markerTag.getAttribute("totalReadings") + "<br/>" +
        "Last reading: " + markerTag.getAttribute("lastReading") + "<br/>";
    var nmarker = new GMarker(point, R_BASE_ICON);
    GEvent.addListener(nmarker, "click", function() {
      nmarker.openInfoWindowHtml(markerInfo);
    });

    return nmarker;
}
var R_BASE_ICON;
R_BASE_ICON = new GIcon();
//    R_BASE_ICON.shadow = "http://cierzo.sahra.arizona.edu/usprn/usermapimages/mm_20_shadow.png";
R_BASE_ICON.iconSize = new GSize(12, 20);
R_BASE_ICON.shadowSize = new GSize(22, 20);
R_BASE_ICON.iconAnchor = new GPoint(6, 20);
R_BASE_ICON.infoWindowAnchor = new GPoint(5, 1);
R_BASE_ICON.image = "http://cierzo.sahra.arizona.edu/usprn/usermapimages/mm_20_green.png";


/*** Elements for showing user-friendly zoom options **/
  
// A TextualZoomControl is a GControl that displays textual "Zoom In To Address"
// and "Zoom Out - to see all neighboring Loggers" buttons (in addition to the iconic buttons used in
// Google Maps).
//Credits: Google Maps API website

// We define the function first
function TextualZoomControl() {
}

// To "subclass" the GControl, we set the prototype object to
// an instance of the GControl object
TextualZoomControl.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.
TextualZoomControl.prototype.initialize = function(map) {
  var container = document.createElement("div");

  var zoomInDiv = document.createElement("div");
  this.setButtonStyle_(zoomInDiv);
  container.appendChild(zoomInDiv);
  zoomInDiv.appendChild(document.createTextNode("Zoom to address"));
  GEvent.addDomListener(zoomInDiv, "click", function() {
    locate(marker.getPoint(), ZOOMLEVEL);
  });

  var zoomOutDiv = document.createElement("div");
  this.setButtonStyle_(zoomOutDiv);
  container.appendChild(zoomOutDiv);
  zoomOutDiv.appendChild(document.createTextNode("See all loggers at selected distance"));
  GEvent.addDomListener(zoomOutDiv, "click", function() {
    map.setZoom(map.getBoundsZoomLevel(polyline.getBounds())-1);
  });

  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.
TextualZoomControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(67, 7));
}

// Sets the proper CSS for the given button element.
TextualZoomControl.prototype.setButtonStyle_ = function(button) {
  button.style.textDecoration = "underline";
  button.style.color = "#000000";
  button.style.backgroundColor = "white";
  button.style.font = "0.8em Arial";
  button.style.border = "1px solid black";
  button.style.padding = "2px";
  button.style.marginBottom = "3px";
  button.style.textAlign = "center";
  button.style.width = "8em";
  button.style.cursor = "pointer";
}


