/*
<!-- Copyright 2008-2009 Parthian Systems. All Rights Reserved -->
<!-- Editor - Processing Shapes -->
*/

// http://viavirtualearth.com/Wiki/DrawPolygon.ashx
var modpoints = new Array();
var tempmodpoints = null;
var tempLL; 
var num = 0;  
var tempShape = null;
var shapeType;
var sqlBuilder;
var pointCount = 0;
var polylineCount = 0;
var polygonCount = 0;
var pointArray = new Array();
var polylineArray = new Array();
var polygonArray = new Array();
var dragSegAngle;
var dragDistance;
var dragTotalDistance;
var routeText;

function drawShape(type) {
  switch (type) {
  case "points": shapeType = VEShapeType.Pushpin; break; // safe default (probably)
  case "lines": shapeType = VEShapeType.Polyline; break; // safe default (probably)
  case "polygons": shapeType = VEShapeType.Polygon; break; // safe default (probably)
  default: break;
  }
  map.AttachEvent('onclick', mapClick);
  //map.AttachEvent('ondoubleclick', mapContextMenu); // ondoubleclicks not working with IE
  map.AttachEvent('onmousemove', mapMouseMove);
  map.vemapcontrol.EnableGeoCommunity(true);
  dataLayer.Show();
  //origCursor = document.getElementById('Map').childNodes[0].style.cursor; // also use this for starting Explorer
  document.getElementById('Map').childNodes[0].style.cursor = "crosshair";
  routeText = "";
  dragTotalDistance = 0;
  dragSegAngle = 0;
  dragDistance = 0;
  tempLL = new VELatLong(0.000001, 0.0000001); // 1 point to update on creation of Polygon
}        

function mapClick(e) {
  var x = e.mapX;
  var y = e.mapY;
  var pixel = new VEPixel(x, y);
  var LL = map.PixelToLatLong(pixel);
  LL.Latitude = floatTrim (LL.Latitude, 6);  // store with fewer points
  LL.Longitude = floatTrim (LL.Longitude, 6);
  modpoints.push(LL);
  //routeText += "<div>" + dragSegAngle + "&deg; " + "<br />" + dragDistance + "metres</div><br />";
  if (dragDistance > 0) { // but evalJson does not like newlines in value of JSON hash
    routeText += dragSegAngle + "&deg; " + dragDistance + " metres<br />";  } // extra slash to escape the newline - stripslashes on return
  dragTotalDistance += dragDistance;
  if (e.rightMouseButton) {
    mapContextMenu(e); // allow the default action to take place - not this one. In this case allows drag with right button
    return true; // this should prevent the normal VE action
  }
  return true; // prevent default VE create of Pin (normally return false prevents default Event action....)
}        

function mapContextMenu(e) {
  // Code that runs on Right Click - End the Line or Polygon

  // First ensure no new polygon can be created to confuse the GetPin
  map.DetachEvent('onclick', mapClick);
  //map.DetachEvent('ondoubleclick', mapContextMenu);
  // Stop drawing shapes when mouse moves
  map.DetachEvent('onmousemove', mapMouseMove); // Left or Right mouse button normally moves the map
  document.getElementById('Map').childNodes[0].style.cursor = "";  // reset cursor

  if (shapeType == "Polygon") {
    modpoints.push(modpoints[0]); // tag copy of 1st point onto end to close the ring
    var start = modpoints[modpoints.length - 2]; // last 2 points will close the polygon
    var end = modpoints[modpoints.length - 1];
    dragSegAngle = angleOfAttack (start.Latitude, start.Longitude, end.Latitude, end.Longitude);
    dragDistance = floatTrim (segLength (start.Latitude, start.Longitude, end.Latitude, end.Longitude) * 1000, 0); // Not sure this distance is useful
    routeText += dragSegAngle + "&deg; " + dragDistance + " metres<br />"; 
    dragTotalDistance += dragDistance;
  }
  routeText += "Total = " + dragTotalDistance + " metres";
  //var polygon = new VEPolygon('polygon_' + num++, modpoints);
  var shape = new VEShape(shapeType, modpoints);
  shape.SetFillColor(new VEColor(170, 150, 150, 0.65));
  shape.SetLineColor(new VEColor(170, 150, 150, 1.0));
  shape.SetLineWidth(2);
  shape.SetZIndex(null,61); // Point over Poly -- Only update the Poly's not the Pushpins here
  if (shapeType == VEShapeType.Polygon) {
    shape.SetTitle("<b>Area</b>");  }
  if (shapeType == VEShapeType.Polyline) {
    shape.SetTitle("<b>Route</b>");
    }
    
  dataLayer.AddShape(shape); 
  var pinID = shape.GetID();
  var LL = shape.GetPoints()[0];
  LL.Latitude = floatTrim (LL.Latitude, 6);  // store with fewer points
  LL.Longitude = floatTrim (LL.Longitude, 6);

  try {
      map.ClearInfoBoxStyles(); // required due to Styling changes in HTML returned by buildPopupWindow
      shape.SetDescription(buildPopupWindow (pinID, LL, false, routeText ));
      dataLayer.DeleteShape(tempShape); // temporary Polygon
      UpdateSQLQuery(pinID);
  } catch (err) {alert ("Right Click - Delete Error " + err.message); }
  modpoints = new Array();
  map.vemapcontrol.EnableGeoCommunity(false);  
  if (shapeType == VEShapeType.Polyline) {
    toggleCreateLines($('CLines'));  } // Turn off the button indicating mode
  if (shapeType == VEShapeType.Polygon) {
    toggleCreatePolygons($('CPoly'));  }// Turn off the button indicating mode
}        

function mapMouseMove(e) {
  // For every tiny movement of the mouse another shape is created and currentPinHTML updated.

  var x = e.mapX;
  var y = e.mapY;
  var pixel = new VEPixel(x, y);
  var LL = map.PixelToLatLong(pixel);
  if (modpoints.length == 1 && shapeType == "Polygon") { // add a fake point to make 3 points for a polygon
    tempmodpoints = [];
    tempLL.Latitude = modpoints[0].Latitude; 
    tempLL.Longitude = modpoints[0].Longitude; 
    tempmodpoints.push(tempLL);    // So first Point of all Polygons is fake. 
    tempmodpoints.push(modpoints[0]); // then the first clicked point
  }
  else {
    tempmodpoints = modpoints.slice(0, modpoints.length);
  }

  tempmodpoints.push(LL); // Add the active location    
    
  try { // Before 1st shape created movements raise an error here - catch but ignore...
      dataLayer.DeleteShape(tempShape);
  } catch (err) { }

  tempShape = new VEShape(shapeType, tempmodpoints);
  tempShape.SetFillColor(new VEColor(170, 150, 150, 0.65));
  tempShape.SetLineColor(new VEColor(170, 150, 150, 1.0));
  tempShape.SetLineWidth(2);
  tempShape.SetZIndex(5002, 5001); // Crazy ZIndex values - TODO
  var currentMarkerID = tempShape.GetID() + '_icon';
  var currentPinHTML = pinHTMLDrag.replace('{0}', currentMarkerID); // use currentPinHTML if adding more 
  //var bground = "background: url(icons/userO.png) no-repeat 0 0;";
    //var bground = "width:32px; height:32px; display:inline-block; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icons/" + jsonData[ip].commenttype + ".png');";
  currentPinHTML = currentPinHTML.replace('pinStyle', 'pinStyleDrag'); // change the class to use that style
  if (tempmodpoints.length > 1) {
    var start = tempmodpoints[tempmodpoints.length - 2];
    var end = tempmodpoints[tempmodpoints.length - 1];
    dragSegAngle = angleOfAttack (start.Latitude, start.Longitude, end.Latitude, end.Longitude);
    dragDistance = floatTrim (segLength (start.Latitude, start.Longitude, end.Latitude, end.Longitude) * 1000, 0); // Not sure this distance is useful
    currentPinHTML = currentPinHTML.replace('replaceme', dragSegAngle + "&deg;  <br />" + dragDistance + "m");
  }
  else {
    currentPinHTML = currentPinHTML.replace('replaceme', dragSegAngle + "&deg;  <br />" + dragDistance + "m");  }

  tempShape.SetCustomIcon(currentPinHTML);

  dataLayer.AddShape(tempShape);
}  

/* -------------- Drawing Shapes Code Complete ------------------  */


function submitGeom(pID) {
  // This is mainly for User created Geometries but is also used for GPX Imports that are saved to individuals accounts
  // Use Ajax to send the data to the database
  var shape = map.GetShapeByID(pID);  // get the pin
  var pinID = shape.GetID();
  
  // In order to add routes with html for newlines etc the start of the editbox content must also be html 
  // so add div to comment. submitPins perhaps needs same but is all of this a security issue???? TODO
  var usersnotes = "<div>" + document.getElementById(pinID + "_notes").value + "</div>";
  if ($(pinID + "_routes")) { // Adding the steps (angle and distance) to the comment - this can take up too much space TODO
    usersnotes += $(pinID + "_routes").value; } // also only do this if a route created manually - perhaps parse GPX to make this TODO
  var commentType = getRadioChecked(pinID + "_pin"); // use Div id to get checked option

  // Flag this pin in Epoch Prime
  //set the attribute values for date1 - if you don't set an attribute value, it will simply default to blank.
  var datetime = new Date(); // use to store time in seconds from 1970 but need to /1000 for PHP
  if (document.getElementById('startdate').value != "today") {
    var sd = document.getElementById('startdate').value.split("-"); // but replace with date set by user
    datetime.setFullYear(sd[2], sd[1]-1, sd[0]);  // watch month starts from 0 - But is this Morning, Noon or Night??? TODO
    }
  // Use the Object to ensure Date is updated with cellHTML etc for Epoch
  var dateCal = new DateCalendar (datetime); // Pass in Specific Date (may not be today)
  var myArray = new Array (dateCal.d); // Add date object updated with Epoch information into the array to send to Calendar
  calendar1.addDates(myArray, true); //add the dates and display them on the calendar! Perhaps delay redraw?
  // Should really add these to dateShapeMap so that little flag is automatically drawn if Pin needs attention
  var buffer = document.getElementById("buffer").value; // Slight worry that these should be pin specific...

  var request = new Ajax.Request(
  "php/login/storecomplexgeom.php",
  {
    method: 'post',
    parameters: {usersnotes: usersnotes, buffer: buffer, sqlgeom: sqlBuilder, commenttype: commentType, datetime:  Math.floor(datetime.getTime()/1000)},
    onSuccess: function (theReturn) {
      var response = theReturn.responseText; 
      alert ("Shape Added to Database. Turn Off/On the - Show/Hide Shapes & Routes button to see the new data");
      },
    onFailure: function (theReturn) {
      // the Header Response is populated with 400 (200 is success) and "Status: some error stuff"
      var response = theReturn.responseText || "No Error Message"; 
      alert ("Submit of Geometries Failed: " + theReturn.getResponseHeader("Status"));
      //If there is a failure - remove everything to ensure all started again
      handleLayer(dataLayer.GetTitle().toLowerCase(), "delete", "geometries"); // won't '
    }
  });
  sqlBuilder = ""; // reset the string and counters and arrays of Geometries - 
  pointCount = 0;
  polylineCount = 0;
  polygonCount = 0; 
  pointArray = new Array();
  polylineArray = new Array();
  polygonArray = new Array();
}


function getRoute () {
try {
  // Simply get the route from the database and store in a file.
  var request = new Ajax.Request(
  "php/login/getroute.php",
  {
    method: 'post',
    parameters: { },
    onSuccess: function (theReturn) {
      var response = theReturn.responseText; 
      //alert (response);
      displayGPXRoute();
    },
    onFailure: function (theReturn) {
      var response = theReturn.responseText || "No Error Message"; 
      alert ("Get of Route Failed: " + theReturn.getResponseHeader("Status")); }
  } );
} catch (e) {alert ("Error - Show Route: " + e.message);}
}

function displayGPXRoute() {
// Get the file of the route - could have been simpler to parse GML on javascript side...
// but this way the file is stored until overwritten so perhaps has value being kept server side.
try {
  var path; 
  if (currentUser) { // if someone logged in - do this to avoid data//route if currentUser empty
    path =  DATAPATH + currentUser + "/route.gpx";
  } else {
    path = DATAPATH + "route.gpx";
  }
    
  // Simply get the route from the database and store in a file.
  //alert ("Displaying Route");
  var request = new Ajax.Request(
  path,
  {
    method: 'get',
    parameters: { },
    onSuccess: function (theReturn) {
      var response = theReturn.responseText; 
      show_popup("xmlsave-box", response);
    },
    onFailure: function (theReturn) {
      var response = theReturn.responseText || "No Error Message"; 
      alert ("Display of Route Failed: " + theReturn.getResponseHeader("Status")); }
  } );
} catch (e) {alert ("Error - Display Route: " + e.message);}

}

function show_popup(sID, response) {
  // fill a popbox with text but 1st close any previous popups
  if(sID!="xmlsave-box") { close_popup("xmlsave-box"); }
  if(sID!="foldout-box") { close_popup("foldout-box"); }
  var obj = document.getElementById(sID);
  obj.style.visibility = "visible";
  obj.style.display = "inline";
  if (response != "") { // must be route display mode
    var txtArea = document.getElementById("xml-textarea");
    txtArea.value = response; // Thought this didn't work for textareas....
    txtArea.focus();
    toggleExportLines($('ExportR')); // Turn off button
  }
}

function showLeaflet(sID, leafletName) {
  var leafletDIV;
  var pageWidth;
  switch (leafletName){
    case "THI": leafletDIV = "<div class='popup-box' id='foldout-box' style='position:absolute; height:670px; width:940px; top:30px; left:70px;'>\n\
<img id='page3' height='663' width='466' src='data/thi_3_80_80.jpg' style='position:absolute; top:10px; left:470px; display:none;' />\n\
<img id='page2' height='663' width='0' src='data/thi_2_80_80.jpg' style='position:absolute; top:10px; left:470px; display:none;' />\n\
<img id='page1' onclick='foldOut();' height='663' width='466' src='data/thi_1_80_80.jpg' style='position:absolute; top:10px; left:470px; display:none;' />\n\
<button type='button' style='position:absolute; z-index:1001' onclick='javascript:close_popup(\"foldout-box\");'>Close</button>\n\\n\
<br /><br /><b>Click the front page -> to open the leaflet</b>\n\
</div>";
    pageWidth = 470;
    break;
    default: break;
  }
  
  if(sID!="leaflet") { close_popup("leaflet"); }
  var obj = document.getElementById(sID);
  if (leafletName != "") {
    obj.innerHTML = leafletDIV; 
    obj.focus();
  }
  obj.style.visibility = "visible";
  obj.style.display = "inline";
  setupFoldOut(pageWidth);
  //foldOut();
}


function close_popup(sID) {
  var obj = document.getElementById(sID);
  if (obj != null) {
    obj.style.visibility = "hidden";
    obj.style.display = "none";
  }
}
/*
function check_for_escape(e, sPopupID){
    if (e.keyCode==27) {
        close_popup(sPopupID);
        var obj=document.getElementById("gpxButton");
        obj.focus();
    }
}
*/

function removeGeometries () {
  // Remove old Geometries (not pins) to stop them piling up. Don't use blankett VE function as need to control via handler
  for (var count = 0; count < map.GetShapeLayerCount(); count++) {
   handleLayer(map.GetShapeLayerByIndex(count).GetTitle().toLowerCase(), "delete", "geometries"); 
   // code will ignore non Feature Layer Layers e.g. unsaved collection and lots with no Title 
  }
}


function showGeometries () {
  // Use Ajax to get the data from the database
  // Later get a date range and the name of the user to get points for and possibly other criteria
  // as per the radio buttons above
try {
  // Remove old Geometries (not pins) to stop them piling up. Don't use blankett VE function as need to control via handler
  for (var count = 0; count < map.GetShapeLayerCount(); count++) {
   handleLayer(map.GetShapeLayerByIndex(count).GetTitle().toLowerCase(), "delete", "geometries"); 
   // code will ignore non Feature Layer Layers e.g. unsaved collection and lots with no Title 
  }
  if (xmlAttributes == undefined) {  // may have already been called for Explorer...
    xmlAttributes = ajaxGetXML("data/routes.xml");  }

  var request = new Ajax.Request(
  "php/login/getgeometries.php",
  {
    method: 'post',
    parameters: { },
    onSuccess: function (theReturn) {
      var response = theReturn.responseText; 
      // Technique from Google Maps 
      var jscript = theReturn.responseText;
      // returning XML appears to be difficult - probably due to header conflict - so save to file
      //var xmlDoc = theReturn.responseXML;
      //var coords = xmlDoc.documentElement.getElementsByTagName("coordinates");
      //alert (jscript);
      addGMLGeometries (jscript);
      // Reset cursor at end of Import Callback
    },
    onFailure: function (theReturn) {
      var response = theReturn.responseText || "No Error Message";
      document.body.style.cursor = "default";
      alert ("Get of Geometries Failed: " + theReturn.getResponseHeader("Status")); }
  } );
}
catch (e)
  {
  document.body.style.cursor = "default";
  alert ("Error - Show Geometries: " + e.message);
  }
}

function uploadGPSTrack (filename) {
  var request = new Ajax.Request("php/login/upload.php",
  {
    method: 'post',
    parameters: { },
    onSuccess: function (theReturn) {
      var response = theReturn.responseText; 
      // Technique from Google Maps 
      var jscript = theReturn.responseText;
      // returning XML appears to be difficult - probably due to header conflict - so save to file
      //var xmlDoc = theReturn.responseXML;
      //var coords = xmlDoc.documentElement.getElementsByTagName("coordinates");
      addGMLGeometries (jscript);
    },
    onFailure: function (theReturn) {
      var response = theReturn.responseText || "No Error Message"; 
      alert ("Upload Track Failed: " + theReturn.getResponseHeader("Status"));
      }
  } );
}


function getGeometryColours (geometryInfo) {
 // ignoring the routes tag - possibly gElByTName cannot cope if only one tag - just use route
 var geometries = xmlAttributes.documentElement.getElementsByTagName("geometry");
 // Build up a Hash Table [route:lineColour Object;] 
 //===========Loop through the array to pull out each of the markers
  for (var i = 0; i < geometries.length; i++) {
    // obtain the attributes of each relation
    var geometry = geometries[i];
    var namer = geometry.getAttribute("namer"); // name is probably a reserved word - caused problems as name
    var transparent = geometry.getAttribute("trans"); // this is "1" or "0.5" etc perhaps should turn into float
    var colour = geometry.getAttribute("linecolor");
    var red = (colour & 0xFF0000) >> 16;
    var green = (colour & 0x00FF00) >> 8;
    var blue = colour & 0x0000FF;
    var lineColor = new VEColor(red, green, blue, 1); // VEColor appears to accept string transparent
    colour = geometry.getAttribute("fillcolor");
    red = (colour & 0xFF0000) >> 16;
    green = (colour & 0x00FF00) >> 8;
    blue = colour & 0x0000FF;
    var fillColor = new VEColor(red, green, blue, transparent); // VEColor appears to accept string transparent
    //var hull = geometry.getAttribute("hull");
    geometryInfo[namer + "_lc"] = lineColor; // Auto create entry and assign value in one operation - no push
    geometryInfo[namer + "_fc"] = fillColor; 
    //var hullswitch = namer + "hull";
    //geometryInfo[hullswitch] = hull; // now add e.g. househull: 1
    var notes = geometry.getAttribute("notes"); 
    var geometrynotes = namer + "notes"; // e.g. Hash = westnotes = unique key
    geometryInfo[geometrynotes] = notes;   
  }
  return geometryInfo;
}

function importKMLCallback ( jscript, kml ) {
  // FF doesn't call this when the data is valid - Catch22
try {
  //alert ("Callback " + jscript);
  //alert ("ShapeLayer " + kml.GetTitle());
  var dateArray = new Array();
  var jsonData = jscript.evalJSON(false);
  var geometryInfo = new Array();
  geometryInfo = getGeometryColours(geometryInfo);
  var count = kml.GetShapeCount(); 
  var pin = count - 1; // Every Delete shifts the array of shapes to the left so start from end and count down 
  for(var ip=0; ip < count; ip++) { 
    var kmlShape = kml.GetShapeByIndex(pin);
    // Cannot move a shape from layer to layer (I think) so create a new one and copy stuff over
    var shape = new VEShape(kmlShape.GetType(), kmlShape.GetPoints()  );
    shape.SetZIndex(null, 61); // Suspect mapcruncher is at 59 - need Line Start/End at 1 less than line 
    // Set Styling here and all the stuff from processGeometries
    var shapeTitle = kmlShape.GetTitle();
    var shapeLayer = handleLayer(shapeTitle, "return", ""); // getShapeLayer
    
    // If the shape is a Line add the start/end styling
    if (kmlShape.GetType() == VEShapeType.Polyline) {
      var zIndex = kmlShape.GetZIndexPolyShape(); // What is this
      var points = shape.GetPoints();
      // Create a Start Point
      var startShape = new VEShape(VEShapeType.Pushpin, points[0]);
      startShape.SetCustomIcon("<div style='color:Lime;'><img style='position:relative; top:6px; left:6px' src='icons/flaggreen.png' width='24px' height='24px' /></div>");
      startShape.SetZIndex(62, null);
      shapeLayer.AddShape(startShape);
      // Create an End Point
      var endShape = new VEShape(VEShapeType.Pushpin, points[points.length-1]);
      endShape.SetCustomIcon("<div style='color:Red;'><img style='position:relative; top:6px; left:6px' src='icons/flagchequered.png'width='24px' height='24px' /></div>");
      endShape.SetZIndex(62, null);    // #960014
      shapeLayer.AddShape(endShape);
    }    
    //shape.SetCustomIcon("<img src='icons/default.png'/>"); 
    shape.SetLineColor(geometryInfo[shapeTitle + "_lc"]);
    shape.SetFillColor(geometryInfo[shapeTitle + "_fc"]); // hopefully setting fillcolor for lines wont matter
    shape.SetLineWidth (2); // could get this from xml too
    //shape.SetDescription(geometryInfo[shape.GetTitle() + "notes"]);
    //alert ("sLayerT " + shapeLayer.GetTitle() );
    shapeLayer.AddShape(shape); // Copy the shape into the appropriate layer (and gets ID)
    var pinID = shape.GetID();
    var deleteBtn;
    var showpoint = shape.GetPoints()[0];
    var jp;
    for (jp=0; jp < jsonData.length; jp++) { // match the json to the kml using Description as join
      if (jsonData[jp].serialpk == kmlShape.GetDescription() ) { break; } // set the jp at the match
    }
    var currentMarkerID = pinID + '_icon';
    var currentPinHTML = pinHTML.replace('{0}', currentMarkerID); // use currentPinHTML if adding more 
    // Now using Image Mapping
    //var bground = "background-image: url(icons/" + jsonData[jp].commenttype + ".png) "; // TODO - Different Size Pins will need changes here
    //var bground = "width:32px; height:32px; display:inline-block; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icons/" + jsonData[ip].commenttype + ".png');";
    currentPinHTML = currentPinHTML.replace('dummy', "pinStyle " + "icon" + jsonData[jp].commenttype);
    shape.SetCustomIcon(currentPinHTML);
     
    var dateCal = new DateCalendar (jsonData[jp].datetime * 1000); // PHP uses seconds from 1970 - JS needs milliseconds 
    dateUsage (dateCal, pinID, dateArray); // update the calendar

    shape.SetTitle(shapeTitle + ' #' + jsonData[jp].serialpk);
    if (currentUser.match(jsonData[jp].username) != null ) {
       if (kmlShape.GetType() == VEShapeType.Polyline) { // strip off the Start/End Pins
         deleteBtn = '<input type="button" value="Delete Shape" id="clearPin" onclick="deletePin(\'' + pinID + '\',\'' + dateCal.day + '\',\'' +  dateCal.month + '\',\'' +  dateCal.year1 + '\'); clearPin (\'' + startShape.GetID() + '\'); clearPin (\'' + endShape.GetID() + '\');" />';
       } else {
         deleteBtn = '<input type="button" value="Delete Shape" id="clearPin" onclick="deletePin(\'' + pinID + '\',\'' + dateCal.day + '\',\'' +  dateCal.month + '\',\'' +  dateCal.year1 + '\');" />';
       }
  } else {
       deleteBtn = ""; }
     
    // if a polygon strip off the Directions 
    if (kmlShape.GetType() == VEShapeType.Polygon) {
      jsonData[jp].comment = jsonData[jp].comment.slice(0, jsonData[jp].comment.indexOf("<div>Directions<br", 0));      
    }
     
    var feedBack = '<div id="' + pinID + '_pin" >' + jsonData[jp].comment + '<br />Posted by ' + jsonData[jp].username  + dateCal.theDate + ' <br />\n\
      <input readonly="readonly" size="11" type="text" value=' + showpoint.Latitude + ' autocomplete="off" />\n\
      <input readonly="readonly" size="11" type="text" value=' + showpoint.Longitude + ' autocomplete="off" />' + deleteBtn + ' </div>';
    shape.SetDescription(feedBack);  
    kml.DeleteShape(kmlShape); // remove the kml version of the data now that it has been copied to a FeatureLayer
    pin = pin - 1;
} 
 // Now Add to the Calendar - do not reset all dates (even if it worked)
 calendar1.addDates(dateArray);  
 calendar1.reDraw(); // can send int of index to redraw that cell - could be good for clear
  // Now delete contents of Imported KML Layer - DeleteAllShapes() fails for some unknown reason
  //alert ("Delete after delay");
  //setTimeout (function(){removeKML(kml);}, 2000);
  document.body.style.cursor="default";
} catch (e) {document.body.style.cursor="default"; alert ("Error - importKML: " + e.message); }
  // map.EnableShapeDisplayThreshold(false);  to turn off generalization
}

function addGMLGeometries (jscript) {
      
// 2004hurricaneivan.xml
// 
// NOTES. Cannot import GML nor files named *.gml (even if correct GEORSS format). hurricane is an example of a working GEORSS file
// but seems an odd format 
// <?xml version="1.0" ?> 
//<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
//<channel>
//<title>Hurricane Ivan 2004</title>
//<item><title>Ivan 09/02/04 18:00</title><description>Tropical Depression, 25 mph, 1009 mb</description>
//<geo:lat>9.70</geo:lat><geo:long>-27.60</geo:long></item>
  try {
   //var geometries = xmlAttributes.documentElement.getElementsByTagName("geometry");
  
  var kmlLoader = new VEShapeLayer(); // A weird timing issue? need this line or code won't work TODO  
  //   2. Create a shape source specification with type VEDataType.ImportXML, the url to the XML file, and a reference to the shape layer:
  var filename = DATAPATH + "geometries.kml";
  var shapeSpec = new VEShapeSourceSpecification(VEDataType.ImportXML, filename, kmlLoader);
  // This function doesn't work for local files - only shows data if found over the web - also fails for FF
  // Localhost failure is due to XML(KML) being parsed through maps.live.com
  // Failure in FF could be due to function passing extra variable instaed of simple call - NO Tested, simple callback makes no difference
  map.ImportShapeLayerData(shapeSpec, function(kmlLoader2){importKMLCallback(jscript, kmlLoader2); }, false);

  // using this technique to pass in parameters to Callback but for some reason the kml.DeleteAllShapes
  // in the callback doesn't work. Doesn't work here either without a delay. Not sure whether null of 2 parameters is appropriate
  // This worked but risk of not getting delay correct setTimeout (function(){removeKML(kmlLoader);}, 1000);
  // so now Delete each shape in turn.
    } catch(e) {                                              // parameter = null - but both params or none
      alert ("AddKML Error: " + e.message);
    }
}

function removeKML (kml) {
kml.DeleteAllShapes();
}

function processGeometries (jscript) { // IS THIS STILL USED??????
  // Close copy of processPoints - but enough differences to warrant new function
  var myArray = new Array();
  var showpoint;
  var shape;
  var deleteBtn;
  var jsonData = jscript.evalJSON(false); // if true the process fails. Due to Badly formed JSON
  
  // Empty the Calendar
  dateShapeMap = null; // attempt to restart the mapping for what should be highlighted on each date.
  calendar1.resetSelections(); // Clear out everything and goto initial month. TODO Appears to FAIL!!!!!!!
  calendar1.reDraw(); // can send int of index to redraw that cell - could be good for clear

  for (var ip = 0;  ip < jsonData.length; ip++) {
    showpoint = new VELatLong(jsonData[ip].latitude, jsonData[ip].longitude);
    shape = new VEShape(VEShapeType.Pushpin, showpoint);

    shape.SetTitle('Loaded Pushpin');
    // Add the point
    var shapeLayer = handleLayer(jsonData[ip].commenttype, "return", ""); // getShapeLayer
    shapeLayer.AddShape(shape); 
    var pinID = shape.GetID();
    
    // Set the Point Icon using DIV + CSS styling for greater control
    // Perhaps changing the className could be useful for this task (especially highlighting)
    //     http://www.howtocreate.co.uk/alpha.html -- ImageLoader needs the src as parameter
    //style="width:400px;height:32px;display:inline-block;
    /* the height and width should match those of the image */
    //filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='varyAlpha.png');
    var currentMarkerID = pinID + '_icon';
    var currentPinHTML = pinHTML.replace('{0}', currentMarkerID); // use currentPinHTML if adding more 
    //var bground = "background-image: url(icons/" + jsonData[ip].commenttype + ".png) ";
    //var bground = "width:32px; height:32px; display:inline-block; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='icons/" + jsonData[ip].commenttype + ".png');";
    currentPinHTML = currentPinHTML.replace('dummy', "pinStyle " + "icon" + jsonData[jp].commenttype);
    shape.SetCustomIcon(currentPinHTML);

    // Add a button to delete the shape if the username matches who is logged in
    // but watch for "\r\nuser". This makes == fail - however this approach could confuse
    // if "bob" and "bob 1"  are used or similar... TODO
    if (currentUser.match(jsonData[ip].username) != null ) {
       deleteBtn = '<input type="button" value="Clear Pin" id="clearPin" onclick="deletePin(\'' + pinID + '\');" />';
    } else {
       deleteBtn = ""; }
     
    var d = new Date();  // need a new Date object each time otherwise all entries in array share same object
    d.setTime(jsonData[ip].datetime * 1000);  // PHP uses seconds from 1970 - JS needs milliseconds
    var dateCal = new DateCalendar (d);     
    myArray.push(dateCal.d); // Add date object updated with Epoch information into the array to send to Calendar
    
    // To Filter by Date create a structure which stores all pins on a specific day - used by Calendar
    createDateShapeMapping(pinID, dateCal.day, dateCal.month, dateCal.year1);
    // Less than a day to go (may be sometime yesterday as deltaTime is exactly when pin was submitted) - used for Emergency Highlight
    if (Math.abs (dateCal.deltaTime) < dateCal.oneDay) {
      highlightPin(pinID, dateCal.deltaTime); } // so show the warning if Pin is set for on or around today -/+ 24 hours

    // When the shape is added the GetID will be populated
    shape.SetDescription('<div id="' + pinID + '_pin" >' + jsonData[ip].comment + '<br />Posted by ' + jsonData[ip].username + dateCal.theDate + ' <br />\n\
      <input readonly="readonly" size="11" type="text" value=' + showpoint.Latitude + ' autocomplete="off" />\n\
      <input readonly="readonly" size="11" type="text" value=' + showpoint.Longitude + ' autocomplete="off" />' + deleteBtn + ' </div>');
   }
 calendar1.resetSelections(); // Clear out everything and goto initial month. TODO Appears to FAIL!!!!!!!
 calendar1.addDates(myArray);  
 calendar1.reDraw(); // can send int of index to redraw that cell - could be good for clear
}


// http://johanneskebeck.spaces.live.com/blog/cns!42E1F70205EC8A96!3704.entry
// http://www.youtube.com/watch?v=QzS_shIzfcM
function UpdateSQLQuery(id)
{
    var currentShape = dataLayer.GetShapeByID(id); // id.id
    switch (currentShape.GetType())
    {
        case "Point":
            pointCount++;
            var tempArray = currentShape.GetPoints();
            for(var j = 0; j < (tempArray.length); j++)
            {  
                pointArray.push(tempArray[j].Longitude + " " + tempArray[j].Latitude);
            }
            break;
        case "Polyline":
            polylineCount++;
            var tempArray = currentShape.GetPoints();
            var dummy = "";
            for(var j = 0; j < (tempArray.length); j++)
            {  
                dummy = dummy + tempArray[j].Longitude + " " + tempArray[j].Latitude + ", ";
            }            
            dummy = dummy.substr(0, dummy.lastIndexOf(",")); // strip off last comma - not required
            polylineArray.push(dummy);
            break;
        case "Polygon":
            polygonCount++;
            var tempArray = currentShape.GetPoints();
            var dummy = "";
            for(var j = 0; j < (tempArray.length); j++)
            {  
                dummy = dummy + tempArray[j].Longitude + " " + tempArray[j].Latitude + ", ";
            }
            dummy = dummy.substr(0, dummy.lastIndexOf(",") ); // strip off last comma - not required
            polygonArray.push(dummy);
            break;
    } //Now we determine which type of geography in SQL Server 2008 matches our selection.

    if (pointCount == 1 && polylineCount == 0 && polygonCount == 0) 
      { geomType = "POINT";
     } else { if (pointCount > 1 && polylineCount == 0 && polygonCount == 0) { geomType = "MULTIPOINT";
       } else { if (pointCount == 0 && polylineCount == 1 && polygonCount == 0) { geomType = "LINESTRING";
        } else { if (pointCount == 0 && polylineCount > 1 && polygonCount == 0) {geomType = "MULTILINESTRING";
          } else { if (pointCount == 0 && polylineCount == 0 && polygonCount == 1) {geomType = "POLYGON";
            } else { if (pointCount == 0 && polylineCount == 0 && polygonCount > 1) { geomType = "MULTIPOLYGON";
              } else { geomType = "GEOMETRYCOLLECTION"; }
            }
          }
        }
       }
     }


      // Finally we create our SQL-statement.

    switch (geomType)
    {
        case "POINT": // geography::ST
            sqlBuilder = "POINT (" + pointArray[0] + ")";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('POINT (" + pointArray[0] + ")', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
        case "MULTIPOINT":
            var dummy = "";
            for(var j = 0; j < (pointArray.length); j++)
            {  
                dummy = dummy + pointArray[j] + ", ";
            }            
            dummy = dummy.substr(0, dummy.lastIndexOf(","));
            sqlBuilder = "MULTIPOINT (" + dummy + ")";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('MULTIPOINT (" + dummy + ")', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
        case "LINESTRING":
            sqlBuilder = "LINESTRING (" + polylineArray[0] + ")";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('LINESTRING (" + polylineArray[0] + ")', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
        case "MULTILINESTRING":
            var dummy = "";
            for(var j = 0; j < (polylineArray.length); j++)
            {  
                dummy = dummy + "(" + polylineArray[j] + "), ";
            }            
            dummy = dummy.substr(0, dummy.lastIndexOf(","));
            sqlBuilder = "MULTILINESTRING (" + dummy + ")";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('MULTILINESTRING (" + dummy + ")', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
        case "POLYGON": 
            sqlBuilder = "POLYGON ((" + polygonArray[0] + "))";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('POLYGON ((" + polygonArray[0] + "))', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
        case "MULTIPOLYGON":
            var dummy = "";
            for(var j = 0; j < (polygonArray.length); j++)
            {  
                dummy = dummy + "((" + polygonArray[j] + ")), ";
            }            
            dummy = dummy.substr(0, dummy.lastIndexOf(","));
            sqlBuilder = "MULTIPOLYGON (" + dummy + ")";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('MULTIPOLYGON (" + dummy + ")', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
        case "GEOMETRYCOLLECTION":
            var dummy = "";
            if (pointArray.length > 0)
            {
                for(var j = 0; j < (pointArray.length); j++)
                {  
                    dummy = dummy + "POINT(" + pointArray[j] + "), ";
                }            
            }
            if (polylineArray.length > 0)
            {
                for(var j = 0; j < (polylineArray.length); j++)
                {  
                    dummy = dummy + "LINESTRING(" + polylineArray[j] + "), ";
                }            
            }
            if (polygonArray.length > 0)
            {
                for(var j = 0; j < (polygonArray.length); j++)
                {  
                    dummy = dummy + "POLYGON((" + polygonArray[j] + ")), ";
                }            
            }
            dummy = dummy.substr(0, dummy.lastIndexOf(","));
            sqlBuilder = "GEOMETRYCOLLECTION (" + dummy + ")";
            //sqlBuilder = "INSERT INTO FeatureDemo (Geom) VALUES (GeomFromText('GEOMETRYCOLLECTION (" + dummy + ")', 4326))";
            //document.getElementById("txtSQL").value = sqlBuilder;
            break;
    }
}


var pwidth;
var c1;
var c2;
var c3;
var pos;
var posCONST;
var p1; 
var p2; 
var p3;

function setupFoldOut(pageWidth) {
pwidth = pageWidth;
pos = pageWidth;
posCONST = pageWidth;
p1 = document.getElementById ("page1");
p1.style.display = "block";
p2 = document.getElementById ("page2");
p2.style.cssText = "position:absolute; top:10px; left:" + pos + "px; display:block;"; // ensures reset for next time
p2.setAttribute ('width', 0);
p3 = document.getElementById ("page3");
p3.style.display = "block";
show_popup("foldout-box", "");
}

function foldOut() {
  if (pwidth > 0) {
    pwidth = pwidth - 5;
    p1.setAttribute ('width', pwidth);
    foldertimer = setTimeout ("foldOut()", 10);
  }
 else {
   clearTimeout(foldertimer);
   openPage();
  }
}

function openPage() {
  if (pwidth <= posCONST) { // POS
    pwidth = pwidth + 5;
    pos = pos - 5;
    p2.style.cssText = "position:absolute; top:10px; left:" + pos + "px";
    p2.setAttribute ('width', pwidth);
    opentimer = setTimeout ("openPage()", 10);
    }
  else {
    clearTimeout(opentimer);  }
}

