/* ========================================================================= */
/* = Lifemapper utilities                                                  = */
/* = @author: CJ Grady                                                     = */
/* = @email: cjgrady@ku.edu                                                = */
/* = @date: February 17, 2009                                              = */
/* =                                                                       = */
/* = @summary: Lifemapper on-demand javascript functions                   = */
/* ========================================================================= */

/* ========================================================================= */
/* =      Global variables used for validation http://www.jslint.com/      = */
/* ========================================================================= */
/*global ActiveXObject                                                       */
/* ========================================================================= */

/* ......................................................................... */
var algoParams = [];
var projectionScenarios = [];
var kmlUrl = "";
var occPoints = [];
var global_valfield;

/* ......................................................................... */
function removeChildrenFromNode(node)
{
   if (node.hasChildNodes())
   {
      while (node.hasChildNodes())
      {
         node.removeChild(node.firstChild);
      }
   }
}

/* ......................................................................... */
function XMLDoc(sync, sendReq)
{
   var me = this;
   var req = null;
   
   if (window.XMLHttpRequest)
   {
      try
      {
         req = new XMLHttpRequest();
      }
      catch (err1)
      {
         req = null;
      }
   }
   else if (window.ActiveXObject)
   {
      try
      {
         req = new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch (err2)
      {
         try
         {
            req = new ActiveXObject("Microsoft.XMLHTTP");
         }
         catch (err3)
         {
            req = null;
         }
      }
   }
   else
   {
      alert(["This page requires a browser with XML support, such as IE5",
             " Windows, Mozilla, Safari 1.2, or Opera 8."].join(""));
   }
   
   this.request = req;
   this.loadXMLDoc = function(url, method, contentType, loadHandler)
   {
      if (this.request)
      {
         try
         {
            this.request.open(method, url, sync);
            this.request.onreadystatechange = function () 
                                              {
                                                 loadHandler(me);
                                              };
            this.request.setRequestHeader("Content-Type", contentType);
            this.request.send(sendReq);
         }
         catch (err1)
         {
            //alert(url, err1);
         }
      }
   };
}

/* ......................................................................... */
function openPopUp(name)
{
   var overlay = document.getElementById('popUpOverlay');
   overlay.className = 'popUpOverlay showMeBlock';
   var showDiv = document.getElementById(name);
   showDiv.className = 'popUp showMeBlock';
}

/* ......................................................................... */
function hidePopUp(name)
{
   var overlay = document.getElementById('popUpOverlay');
   overlay.className = 'popUpOverlay hideMe';
   var hideDiv = document.getElementById(name);
   hideDiv.className = 'popUp hideMe';
}

/* ......................................................................... */
function clearOccurrenceSet()
{
   var occSetInput = document.getElementById("spInputText");
   var occSetSpeciesText = document.getElementById("spInput");
   var occSetDiv = document.getElementById("occResultsContainer");
   var occMap = document.getElementById("occMap1");
   var sumOccSetMeta = document.getElementById("sumOccSetMeta");
   var step2Button = document.getElementById("step2Button");
   
   occSetInput.value = "";
   occSetSpeciesText.value = "";
   removeChildrenFromNode(occSetDiv);
   removeChildrenFromNode(occMap);
   removeChildrenFromNode(sumOccSetMeta);
   
   step2Button.disabled = true;
}

/* ......................................................................... */
function clearAlgorithm()
{
   var algoSelect = document.getElementById("defAlgoSelect");
   var algoParamsId = document.getElementById("algoParamsIdForAlgo");
   var algParamContainer = document.getElementById("algParamContainer");
   var step3Button = document.getElementById("step3Button");
   var saveButton = document.getElementById("postAlgoParamButton");
   
   if (algParamContainer)
   {
      removeChildrenFromNode(algParamContainer);
   }
   
   if (saveButton)
   {
      saveButton.disabled = true;
   }
   
   if (algoParamsId)
   {
      removeChildrenFromNode(algoParamsId);
   }
   
   algoSelect.selectedIndex = 0;
   
   step3Button.disabled = true;
}

/* ......................................................................... */
function clearScenarios()
{
   var mdlScnSelect = document.getElementById("modScnSelect");
   var prjScnSelect = document.getElementById("prjScnSelect");
   var reviewButton = document.getElementById("step4Button");
   var scnLayersCont = document.getElementById("scnLayersContainer");
   
   removeChildrenFromNode(scnLayersCont);
   scnLayersCont.className = "hideMe";
   mdlScnSelect.selectedIndex = 0;
   removeChildrenFromNode(prjScnSelect);
   reviewButton.disabled = true;
}

/* ......................................................................... */
function updateOccurrenceSet(req)
{
   req = req.request;
   if (req.readyState === 4)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var occSetId = document.getElementById("occSetId").value;
      var occSetInput = document.getElementById("spInputText");
      var occSetSpeciesText = document.getElementById("spInput");
      var occSetDiv = document.getElementById("occResultsContainer");
      var sumOccSetMeta = document.getElementById("sumOccSetMeta");
      removeChildrenFromNode(occSetDiv);

      if (req.status === 200)
      {
         var jObj = JSON.parse(xDoc);
         var occTitle = jObj.title;
         var displayName = jObj.displayName;
         var fromGbif = jObj.fromGbif;
         var queryCount = jObj.queryCount;
         var realCount = jObj.count;
         var metadataUrl = jObj.metadataUrl;
         var points = jObj.point;
         occPoints = points;
         
         kmlUrl = metadataUrl + "/kml";
         
         occSetSpeciesText.value = displayName;
         
         var occHTML = "<b>" + displayName + "</b><br />";
         occHTML += occTitle + "<br />";
         if (queryCount > 0)
         {
            occHTML += "Number of Points: " + queryCount + "<br />";
         }
         occSetDiv.innerHTML = occHTML;
         sumOccSetMeta.innerHTML = occHTML;
   
         var step2Button = document.getElementById("step2Button");

         if (parseInt(queryCount) > 0)
         {
            createOccMap("occMap1", occSetId);
            step2Button.disabled = false;
         }
         else if (fromGbif === "False")
         {
            createOccMap("occMap1", occSetId);
            step2Button.disabled = false;
         }
         else
         {
            removeChildrenFromNode(document.getElementById("occMap1"));
            step2Button.disabled = true;
         }
      }
      else
      {
         occSetInput = "";
         occSetSpeciesText = "";
         if (req.status === 404)
         {
            alert("The desired occurrence set (" + occSetId + ") was not found.");
         }
         else
         {
            alert(req.status);
         }
      }
   }
}

/* ......................................................................... */
function checkOccurrenceSet()
{
   var occSetId = document.getElementById("occSetId").value;
   if (occSetId.length !== 0)
   {
      var occSetText = document.getElementById("spInputText");
      occSetText.value = occSetId;
      
      var url = "/services/occurrences/" + occSetId + "/json?fillPoints=false";
      var method = "GET";
      var contentType = "text/json";
      
      openPopUp("loadingPopUp");
      var occReq = new XMLDoc(true, "");
      occReq.loadXMLDoc(url, method, contentType, updateOccurrenceSet);
   }
}

/* ......................................................................... */
function notifyOccId(id)
{
   var occPopDiv = document.getElementById("pointsPopUp");
   removeChildrenFromNode(occPopDiv);
   
   var occSuccessDiv = document.createElement("div");
   occSuccessDiv.className = "successPopDiv";
   
   var occDivHeader = document.createElement("h3");
   occDivHeader.innerHTML = "Successfully posted occurrence set: " + id;
   occSuccessDiv.appendChild(occDivHeader);
   occSuccessDiv.appendChild(document.createElement("br"));
   
   var contButton = document.createElement("input");
   contButton.type = "button";
   contButton.value = "Continue";
   contButton.onclick = function()
   {
      hidePopUp("pointsPopUp");
   };
   occSuccessDiv.appendChild(contButton);
   occPopDiv.appendChild(occSuccessDiv);
}

/* ......................................................................... */
function onOccIframeLoad()
{
   var tarIframe = document.getElementById("upload_target").contentWindow.document.body;
   var lmResponse = tarIframe.innerHTML;

   if (lmResponse.length > 0)
   {
      var jObjs = JSON.parse(lmResponse);
      
      var errIdx = jObjs.title.indexOf('error');
      if (errIdx > 0)
      {
         alert("Failed to upload points.  Please check that the file type specified is correct.");
      }
      
      for(var i=0,len=jObjs.urls.length;i<len;i++)
      {
         var url = jObjs.urls[i];
         var ind1 = url.indexOf('occurrences/');
         if (ind1 > 0 )
         {
            var id = url.substring(ind1+12, url.length);
            var occSet = document.getElementById("occSetId");
            occSet.value = id;
            checkOccurrenceSet();
            notifyOccId(id);
         }
         else
         {
            alert("Failed to upload points.  Please check that the file type specified is correct.");
         }
      }
   }
}

/* ......................................................................... */
function showModelScenarioLayers(req)
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var jObjs = JSON.parse(xDoc);
      var scnLyrsContainer = document.getElementById("scnLayersContainer");
      scnLyrsContainer.className = "showMeBlock";
      
      var scnLyrsHtml = jObjs.title + " layers<br />";
      
      for (var i=0, len=jObjs.layer.length; i<len; i++)
      {
         scnLyrsHtml += "&nbsp;&nbsp;&nbsp;&nbsp;" + jObjs.layer[i].title + "<br />";
      }
      scnLyrsContainer.innerHTML = scnLyrsHtml;
   }
}

/* ......................................................................... */
function buildAlgoParamsPostRequest(code, parameters)
   /*
   @summary: Builds a request that will be used to post algorithm parameters
   @param code: The algorithm code
   @param parameters: A list of algorithm parameters
   */
{
   var request = "<lm:request xmlns:lm='http://lifemapper.org'>\n";
   request += "   <lm:algoParamsSet>\n";
   request += "      <lm:algorithmCode>" + code + "</lm:algorithmCode>\n";
   request += "      <lm:parameters>\n";
   
   for (var i=0, len=parameters.length; i<len; i++)
   {
      var paramName = parameters[i];
      var value = document.getElementById(paramName).value;
      request += "         <lm:" + paramName + ">" + value + "</lm:" + paramName + ">\n";
   }
   
   request += "      </lm:parameters>\n";
   request += "   </lm:algoParamsSet>\n;"
   request += "</lm:request>\n";
   
   return request;
}

/* ......................................................................... */
function buildExperimentPostRequest(occSetId, algoParamSetId, modelScenario, 
                                                           projectionScenarios)
   /*
   @summary: Builds a request that will be used to post an experiment
   @param occSetId: The occurrence set id
   @param algoParamSetId: The algorithm parameter set id
   @param modelScenario: The model scenario id
   @param projectionScenarios: An array of projection scenario ids 
   */
{
   var request = "<lm:request xmlns:lm='http://lifemapper.org'>\n";
   request += "   <lm:experiment>\n";
   request += "      <lm:modelScenario>" + modelScenario + "</lm:modelScenario>\n";
   request += "      <lm:algorithmParametersId>" + algoParamSetId + "</lm:algorithmParametersId>\n";
   request += "      <lm:occurrenceSetId>" + occSetId + "</lm:occurrenceSetId>\n";
   
   for (var i=0; i < projectionScenarios.length; i++)
   {
      request += "      <lm:projectionScenario>" + projectionScenarios[i] + "</lm:projectionScenario>\n";
   }
   request += "   </lm:experiment>\n";
   request += "</lm:request>";
   
   return request;
}

/* ......................................................................... */
function newParamSet()
{
   var paramSelect = document.getElementById("algoParamsIdForAlgo");
   paramSelect.selectedIndex = 0;
   
   var validSet = true;
   
   for (var i=0; i < algoParams.length; i++)
   {
      var val = document.getElementById(algoParams[i]).value;
      if (!val.length || val === "")
      {
         validSet = false;
      }
   }
   
   var paramSaveButton = document.getElementById("postAlgoParamButton");
   if (validSet)
   {
      paramSaveButton.disabled = false;
   }
   else
   {
      paramSaveButton.disabled = true;
   }
   
   var step3Button = document.getElementById("step3Button");
   step3Button.disabled = true;
}

/* ......................................................................... */
function populateAlgoParamsSelect(req)
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var defaultValue = document.getElementById("algoDefaultParamId").value;
      var xDoc = req.responseText;
      var jObjs = JSON.parse(xDoc);
      var algPrmSelect = document.getElementById("algoParamsIdForAlgo");
      
      var algParamsId = document.getElementById("algoParamsId").value;
      
      for(var i=0,len=jObjs.items.length;i<len;i++)
      {
         var id = jObjs.items[i].id;
         var sel = false;
         if (algParamsId === id)
         {
            sel = true;
         }
         
         var opt = new Option(id, id, false, sel);
         algPrmSelect.options[i+2] = opt;
      }
      
      if (algParamsId === defaultValue)
      {
         algPrmSelect.selectedIndex = 1;
      }
   }
}

/* ......................................................................... */
function summarize()
{
   var occSetId = document.getElementById("occSetId").value;
   createOccMap("sumOccSetMap", occSetId);

   var sumPrjScnNames = document.getElementById("sumProjScenNames");
   var sumPrjScnIds = document.getElementById("sumProjScenIds");

   removeChildrenFromNode(sumPrjScnNames);
   removeChildrenFromNode(sumPrjScnIds);
   
   var prjScnVals = document.getElementById("prjScnSelect");

   var prjScnNames = "";
   var prjScnIds = "";
   
   projectionScenarios = [];
   
   for (var i=0; i < prjScnVals.options.length; i++)
   {
      if (prjScnVals.options[i].selected)
      {
         prjScnNames += prjScnVals.options[i].text + "<br /><br />";
         prjScnIds += "Scenario " + prjScnVals.options[i].value + "<br />";
         projectionScenarios.push(prjScnVals.options[i].value);
      }
   }
   sumPrjScnNames.innerHTML = prjScnNames;
   sumPrjScnIds.innerHTML = prjScnIds;
}

/* ......................................................................... */
function updateOccMap(val)
{
   var occSet = document.getElementById("occSetId");
   occSet.value = val;
   checkOccurrenceSet();
}

/* ......................................................................... */
function showAlgs(req)
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var jObjs = JSON.parse(xDoc);
      var algSelect = document.getElementById("defAlgoSelect");
      removeChildrenFromNode(algSelect);
      
      algSelect.options[0] = new Option("Please Select An Algorithm...", "-1", true, true);
      
      for(var i=0,len=jObjs.items.length;i<len;i++)
      {
         var val = jObjs.items[i].id;
         var title = jObjs.items[i].title;
         var ind = title.indexOf(': Default Values');
         if (ind > 0)
         {
            title = title.substring(0, ind);
         }
         algSelect.options[i+1] = new Option(title, val, false, false);
      }
   }
}

/* ......................................................................... */
function showModelScenarios(req)
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var jObjs = JSON.parse(xDoc);
      var modScnSelect = document.getElementById("modScnSelect");
      removeChildrenFromNode(modScnSelect);
      
      var defOpt = new Option("Please Select a Model Scenario...", "-1", true, true);
      modScnSelect.options[0] = defOpt;
      
      for (var i=0, len=jObjs.items.length;i<len;i++)
      {
         var value = jObjs.items[i].id;
         var title = jObjs.items[i].title;
         modScnSelect.options[i+1] = new Option(title, value, false, false);
      }
   }
}

/* ......................................................................... */
function showProjectionScenarios(req)
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var jObjs = JSON.parse(xDoc);
      var prjScnSelect = document.getElementById("prjScnSelect");
      removeChildrenFromNode(prjScnSelect);
      
      for (var i=0, len=jObjs.items.length;i<len;i++)
      {
         var value = jObjs.items[i].id;
         var title = jObjs.items[i].title;
         prjScnSelect.options[i] = new Option(title, value, false, false);
      }
   }
}

/* ......................................................................... */
function notifyExpId(id)
{
   var expDiv = document.getElementById("expPopUp");
   
   var expSuccessDiv = document.createElement("div");
   expSuccessDiv.className = "successPopDiv";
   
   var expDivHeader = document.createElement("h3");
   expDivHeader.innerHTML = "Lifemapper On Demand Experiment: " + id;
   expSuccessDiv.appendChild(expDivHeader);
   expSuccessDiv.appendChild(document.createElement("br"));
   var expStatusHeader = document.createElement("h5");
   expStatusHeader.innerHTML = "Status: Launched";
   expSuccessDiv.appendChild(expStatusHeader);
   expSuccessDiv.appendChild(document.createElement("br"));
   
   var expUrl = "/services/experiments/" + id;
   
   var expDivAnchor = document.createElement("a");
   expDivAnchor.href = expUrl;
   expDivAnchor.innerHTML = "Experiment " + id;
   expDivAnchor.target = "_blank";
   expSuccessDiv.appendChild(expDivAnchor);
   
   expSuccessDiv.appendChild(document.createElement("br"));
   expSuccessDiv.appendChild(document.createElement("br"));
   
   var contButton = document.createElement("input");
   contButton.type = "button";
   contButton.value = "OK";
   contButton.onclick = function()
   {
      hidePopUp("expPopUp");
   };
   expSuccessDiv.appendChild(contButton);
   expDiv.appendChild(expSuccessDiv);
   
   var finishButton = document.getElementById("stepFinishButton");
   finishButton.value = "Go to Experiment";
   finishButton.onclick = function()
   {
      window.location.href = expUrl;
   };

   openPopUp("expPopUp");
}

/* ......................................................................... */
function getAlgoCode(req)
   /*
   @summary: Ajax function to get an algorithm code and then request that 
             algorithm parameters select gets updated.
   */
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var algObj = JSON.parse(xDoc);
      var algCode = document.getElementById("algoCode");
      var algPrmSelect = document.getElementById("algoParamsIdForAlgo");
      
      var code = algObj.code;
      
      var url = "/services/algoparams/json?algorithmCode=" + code;
      var method = "GET";
      var contentType = "text/json";
      
      openPopUp("loadingPopUp");
      var algPrmsReq = new XMLDoc(true, "");
      algPrmsReq.loadXMLDoc(url, method, contentType, populateAlgoParamsSelect);
   }
}

/* ......................................................................... */
function getScenarioLayers(scn)
{
   var url = "/services/scenarios/" + scn + "/json";
   var method = "GET";
   var contentType = "text/json";
   
   openPopUp("loadingPopUp");
   var scnReq = new XMLDoc(true, "");
   scnReq.loadXMLDoc(url, method, contentType, showModelScenarioLayers);
}

/* ......................................................................... */
function changePage(pageNumber)
   /*
   @summary: Changes page by activating a new div 
   */
{
   var link1 = document.getElementById("link1");
   var link2 = document.getElementById("link2");
   var link3 = document.getElementById("link3");
   var link4 = document.getElementById("link4");
   
   var div1 = document.getElementById("page1");
   var div2 = document.getElementById("page2");
   var div3 = document.getElementById("page3");
   var div4 = document.getElementById("page4");
   
   var a1 = document.getElementById("a1");
   var a2 = document.getElementById("a2");
   var a3 = document.getElementById("a3");
   var a4 = document.getElementById("a4");

   if (pageNumber === 1)
   {
      link1.className = "odActiveStep";
      link2.className = "odDisabledStep";
      link3.className = "odDisabledStep";
      link4.className = "odDisabledStep";
      
      div1.className = "showMeBlock";
      div2.className = "hideMe";
      div3.className = "hideMe";
      div4.className = "hideMe";
      
      a1.onclick = function() 
                   { 
                      return changePage(1);
                   };
      a2.onclick = function() 
                   { 
                      return false;
                   };
      a3.onclick = function() 
                   { 
                      return false;
                   };
      a4.onclick = function() 
                   { 
                      return false;
                   };
   }
   else if (pageNumber === 2)
   {
      link1.className = "odCompletedStep";
      link2.className = "odActiveStep";
      link3.className = "odDisabledStep";
      link4.className = "odDisabledStep";
      
      div1.className = "hideMe";
      div2.className = "showMeBlock";
      div3.className = "hideMe";
      div4.className = "hideMe";

      a1.onclick = function()
                   {
                      return changePage(1);
                   };
      a2.onclick = function()
                   {
                      return changePage(2);
                   };
      a3.onclick = function()
                   {
                      return false;
                   };
      a4.onclick = function()
                   {
                      return false;
                   };
   }
   else if (pageNumber === 3)
   {
      link1.className = "odCompletedStep";
      link2.className = "odCompletedStep";
      link3.className = "odActiveStep";
      link4.className = "odDisabledStep";
      
      div1.className = "hideMe";
      div2.className = "hideMe";
      div3.className = "showMeBlock";
      div4.className = "hideMe";

      a1.onclick = function()
                   {
                      return changePage(1);
                   };
      a2.onclick = function()
                   {
                      return changePage(2);
                   };
      a3.onclick = function()
                   {
                      return changePage(3);
                   };
      a4.onclick = function()
      {
         return false;
      };
   }
   else if (pageNumber === 4)
   {
      link1.className = "odCompletedStep";
      link2.className = "odCompletedStep";
      link3.className = "odCompletedStep";
      link4.className = "odActiveStep";
      
      div1.className = "hideMe";
      div2.className = "hideMe";
      div3.className = "hideMe";
      div4.className = "showMeBlock";

      a1.onclick = function()
                   {
                      return changePage(1);
                   };
      a2.onclick = function()
                   {
                      return changePage(2);
                   };
      a3.onclick = function()
                   {
                      return changePage(3);
                   };
      a4.onclick = function()
                   {
                      return changePage(4);
                   };
      summarize();
      return false;
   }
   return false;
}

/* ......................................................................... */
function updateOccFromAC(sTypes, aArgs)
{
   var textInput = document.getElementById("spInputText");
   var oMyAcInstance = aArgs[0];
   var elListItem = aArgs[1];
   var oData = aArgs[2];
   var species = oData.name;
   var occSetId = oData.occSetId;
   
   if (species !== "No Suggestions")
   {
      textInput.value = "";
      updateOccMap(occSetId);
   }
   else
   {
      var acInput = document.getElementById("spInput");
      acInput.value = "";
   }
}

/* ......................................................................... */
function updateOccFromInput(val)
{
   clearOccurrenceSet();
   var acInput = document.getElementById("spInput");
   acInput.value = "";
   updateOccMap(val);
}

/* ......................................................................... */
function getAlgorithms()
   /*
   @summary: Calls Ajax function to get algorithms for algorithm select
   */
{
   var url = "/services/lm2/algoparams/json?paramsType=default";
   var method = "GET";
   var contentType = "text/json";
   
   openPopUp("loadingPopUp");
   var algsReq = new XMLDoc(true, "");
   algsReq.loadXMLDoc(url, method, contentType, showAlgs);
}

/* ......................................................................... */
function populateModelScenarios()
{
   var url = "/services/scenarios/json?keyword=observed";
   var method = "GET";
   var contentType = "text/json";
   
   openPopUp("loadingPopUp");
   var modScnsReq = new XMLDoc(true, "");
   modScnsReq.loadXMLDoc(url, method, contentType, showModelScenarios);
}

/* ......................................................................... */
function postExperiment(req)
{
   req = req.request;
   if (req.readyState === 4)
   {
      hidePopUp("loadingPopUp");
      if (req.status === 202)
      {
         var xDoc = req.responseText;
         var jObjs = JSON.parse(xDoc);
         
         for (var i=0,len=jObjs.urls.length;i<len;i++)
         {
            var url = jObjs.urls[i];
            
            var ind1 = url.indexOf('experiments/');
            if (ind1 > 0)
            {
               var id = url.substring(ind1+12, url.length);
               notifyExpId(id);
            }
         }
      }
      else
      {
         alert("Failed to post experiment.  Status returned: " + req.status);
      }
   }
}

/* ......................................................................... */
function updateAlgoParamsSelect(value)
{
   if (value >= 0)
   {
      var defaultValue = document.getElementById("algoDefaultParamId").value;
      
      var algPrmSelect = document.getElementById("algoParamsIdForAlgo");
      removeChildrenFromNode(algPrmSelect);

      var algParamsIdHidden = document.getElementById("algoParamsId");
      algParamsIdHidden.value = value;
      
      var opt = new Option("New...", "-1", false, false);
      algPrmSelect.options[0] = opt;
      
      opt = new Option("Default", defaultValue, true, true);
      algPrmSelect.options[1] = opt;
      
      var url = "/services/algoparams/" + value + "/json";
      var method = "GET";
      var contentType = "text/json";
      
      openPopUp("loadingPopUp");
      var algPrmReq = new XMLDoc(true, "");
      algPrmReq.loadXMLDoc(url, method, contentType, getAlgoCode);
   }
}

/* ......................................................................... */
function updateProjectionScenarios(modelScenario)
{
   var step4Button = document.getElementById("step4Button");
   step4Button.disabled = false;
   
   var modScnVal = document.getElementById("modScnValue");
   modScnVal.value = modelScenario;
   
   var modScnSelect = document.getElementById("modScnSelect");
   var modScnText = modScnSelect.options[modScnSelect.selectedIndex].text;

   var sumModScnNames = document.getElementById("sumModScenNames");
   var sumModScnIds = document.getElementById("sumModScenIds");
   
   removeChildrenFromNode(sumModScnNames);
   removeChildrenFromNode(sumModScnIds);
   
   sumModScnNames.innerHTML = modScnText;
   sumModScnIds.innerHTML = "Scenario " + modelScenario;
   
   var url = "/services/scenarios/json?matchingScenario=" + modelScenario;
   var method = "GET";
   var contentType = "text/json";

   openPopUp("loadingPopUp");
   var prjScnsReq = new XMLDoc(true, "");
   prjScnsReq.loadXMLDoc(url, method, contentType, showProjectionScenarios);
   
   getScenarioLayers(modelScenario);
}

/* ......................................................................... */
function init()
{
   getAlgorithms();
   populateModelScenarios();
   var step2Button = document.getElementById("step2Button");
   var step3Button = document.getElementById("step3Button");
   var step4Button = document.getElementById("step4Button");
   
   step2Button.disabled = true;
   step3Button.disabled = true;
   step4Button.disabled = true;
   checkOccurrenceSet();
}

function setFocusDelayed()
{
   global_valfield.focus();
}

function setfocus(valfield)
{
   global_valfield = valfield;
   setTimeout('setFocusDelayed()', 100);
}

/* ......................................................................... */
function showAlg(req)
{
   req = req.request;
   if (req.readyState === 4 && req.status === 200)
   {
      hidePopUp("loadingPopUp");
      var xDoc = req.responseText;
      var algObj = JSON.parse(xDoc);
      var algBox = document.getElementById("algParamContainer");
      
      var sumAlgMeta = document.getElementById("sumAlgo");
      var sumAlgParams = document.getElementById("sumAlgoParams");
      
      removeChildrenFromNode(sumAlgMeta);
      removeChildrenFromNode(sumAlgParams);
      
      var metaHTML = algObj.title + "<br />";
      metaHTML += "Algorithm Code: " + algObj.code + "<br />";
      sumAlgMeta.innerHTML = metaHTML;
      
      var paramsHTML = "Algorithm Parameters:<br />";
      
      var algoCodeInput = document.getElementById("algoCode");
      algoCodeInput.value = algObj.code;
      
      var algTable = document.createElement("table");
      algTable.className = "algorithmParametersTable";
      
      var algTableBody = document.createElement("tbody");
      
      var algHeadRow = document.createElement("tr");
      
      var algHeadParamName = document.createElement("th");
      algHeadParamName.className = "algorithmParameters";
      algHeadParamName.innerHTML = "Parameter Name";
      
      var algHeadValue = document.createElement("th");
      algHeadValue.className = "algorithmParameters";
      algHeadValue.innerHTML = "Value";
      
      var algHeadRange = document.createElement("th");
      algHeadRange.className = "algorithmParameters";
      algHeadRange.innerHTML = "Range";
      
      var algHeadDefault = document.createElement("th");
      algHeadDefault.className = "algorithmParameters";
      algHeadDefault.innerHTML = "Default";
      
      algHeadRow.appendChild(algHeadParamName);
      algHeadRow.appendChild(algHeadValue);
      algHeadRow.appendChild(algHeadRange);
      algHeadRow.appendChild(algHeadDefault);
      
      algTableBody.appendChild(algHeadRow);

      algoParams = [];
      
      for (var obj in algObj.parameters)
      {
         if (true)
         {
            var name = "[" + obj + "]";
            var n = "";
            for (var i=1, len=name.length; i < len -1; i++)
            {
               n += name.charAt(i);
            }
         
            var opts = [];
            var min = " ";
            var max = " ";
            var def = " ";
            min = algObj.parameters[n].min;
            max = algObj.parameters[n].max;
            def = algObj.parameters[n]["default"];
         
            if (algObj.parameters[n].option)
            {
               opts = algObj.parameters[n].option;
            }
         
            var range = "";
            if (min && min !== "")
            {
               range += algObj.parameters[n].min + " <= ";
            }
            range += "x";
            if (max && max !== "")
            {
               range += " <= " + algObj.parameters[n].max;
            }
         
            if (opts && opts.length > 0)
            {
               range = opts;
            }
         
            var algDataRow = document.createElement("tr");
         
            var algDataParamName = document.createElement("td");
            algDataParamName.className = "algorithmParameters";
            algDataParamName.innerHTML = n;
         
            var algDataValue = document.createElement("td");
            algDataValue.className = "algorithmParameters";
            
            var hideElMin = document.createElement("input");
            hideElMin.type = "hidden";
            if (min)
            {
               hideElMin.value = min;
            }
            hideElMin.id = n + "Min";
            
            var hideElMax = document.createElement("input");
            hideElMax.type = "hidden";
            if (max)
            {
               hideElMax.value = max;
            }
            hideElMax.id = n + "Max";

            var hideElOpts = document.createElement("input");
            hideElOpts.type = "hidden";
            if (opts)
            {
               hideElOpts.value = opts;
            }
            hideElOpts.id = n + "Opts";
            
            var inputEl = document.createElement("input");
            inputEl.type = "text";
            inputEl.value = algObj.parameters[n].value;
            inputEl.id = n;
            inputEl.onchange = function()
                               {
                                  var min = document.getElementById(this.id + "Min").value;
                                  var max = document.getElementById(this.id + "Max").value;
                                  var opts = document.getElementById(this.id + "Opts").value;
                                  var val = this.value;
                                  
                                  if (validate(val, min, max, opts))
                                  {
                                     newParamSet();
                                  }
                                  else
                                  {
                                     // Set focus back to element
                                     setfocus(this);
                                     // disable save button
                                     var paramSaveButton = document.getElementById("postAlgoParamButton");
                                     paramSaveButton.disabled = true;
                                  }
                               };
            algDataValue.appendChild(inputEl);
            algDataValue.appendChild(hideElMin);
            algDataValue.appendChild(hideElMax);
            algDataValue.appendChild(hideElOpts);
            
            paramsHTML += "&nbsp;&nbsp;&nbsp;" + n + ": " + algObj.parameters[n].value + "<br />";
         
            algoParams.push(n);
         
            var algDataRange = document.createElement("td");
            algDataRange.className = "algorithmParameters";
            algDataRange.innerHTML = range;
         
            var algDataDefault = document.createElement("td");
            algDataDefault.className = "algorithmParameters";
            algDataDefault.innerHTML = def;
         
            algDataRow.appendChild(algDataParamName);
            algDataRow.appendChild(algDataValue);
            algDataRow.appendChild(algDataRange);
            algDataRow.appendChild(algDataDefault);
         
            algTableBody.appendChild(algDataRow);
         }
      }
      
      sumAlgParams.innerHTML = paramsHTML;
      
      removeChildrenFromNode(algBox);
      algTable.appendChild(algTableBody);
      algBox.appendChild(algTable);
      
      algBox.appendChild(document.createElement("br"));
      
      var step3Button = document.getElementById("step3Button");
      step3Button.disabled = false;
   }
}

/* ......................................................................... */
function saveExperiment()
{
   var occSetId = document.getElementById("occSetId").value;
   var algoParamSetId = document.getElementById("algoParamsId").value;
   var modelScenario = document.getElementById("modScnValue").value;
   
   var request = buildExperimentPostRequest(occSetId, algoParamSetId, 
                                           modelScenario, projectionScenarios);
   
   var url = "/services/experiments/json";
   var method = "POST";
   var contentType = "text/json";
   
   openPopUp("loadingPopUp");
   var postExpReq = new XMLDoc(true, request);
   postExpReq.loadXMLDoc(url, method, contentType, postExperiment);
}

/* ......................................................................... */
function changeAlgoParams(value)
   /*
   @summary: Changes the displayed algorithm parameters
   @param value: The algorithm parameter set id to change to
   */
{
   var algPrmDiv = document.getElementById("algParamContainer");
   
   if (value >= 0)
   {
      var url = "/services/algoparams/" + value + "/json";
      var method = "GET";
      var contentType = "text/json";
      
      openPopUp("loadingPopUp");
      var algPrmReq = new XMLDoc(true, "");
      algPrmReq.loadXMLDoc(url, method, contentType, showAlg);
   }
   else
   {
      for (var i=0,len=algoParams.length; i < len; i++)
      {
         document.getElementById(algoParams[i]).value = "";
      }
      document.getElementById("step3Button").disabled = true;
   }
}

/* ......................................................................... */
function changeAlgoParamsFromSelect(value)
   /*
   @summary: Changes algorithm parameters from the parameters select box
   */
{
   document.getElementById("algoDefaultParamId").value = value;
   updateAlgoParamsSelect(value);
   changeAlgoParams(value);
}

/* ......................................................................... */
function changeAlgoParamsFromText(value)
   /*
   @summary: Changes algorithm parameters from text input
   */
{
   changeAlgoParams(value);
}

/* ......................................................................... */
function updateAlgoParamsWithNew(id)
{
   hidePopUp("algPopUp");
   updateAlgoParamsSelect(id);
   changeAlgoParams(id);
}

/* ......................................................................... */
function notifyAlgId(id)
{
   var algPopDiv = document.getElementById("algPopUp");
   removeChildrenFromNode(algPopDiv);
   
   
   var apSuccessDiv = document.createElement("div");
   apSuccessDiv.className = "successPopDiv";
   
   var algDivHeader = document.createElement("h3");
   algDivHeader.innerHTML = "Successfully posted algorithm parameter set: " + id;
   apSuccessDiv.appendChild(algDivHeader);
   apSuccessDiv.appendChild(document.createElement("br"));
   
   var contButton = document.createElement("input");
   contButton.type = "button";
   contButton.value = "Continue";
   contButton.onclick = function()
   {
      updateAlgoParamsWithNew(id);
      hidePopUp("pointsPopUp");
   };
   apSuccessDiv.appendChild(contButton);
   algPopDiv.appendChild(apSuccessDiv);

   var paramSaveButton = document.getElementById("postAlgoParamButton");
   paramSaveButton.disabled = true;

   openPopUp("algPopUp");
}

/* ......................................................................... */
function postAlgorithmParameters(req)
{
   req = req.request;
   if (req.readyState === 4)
   {
      hidePopUp("loadingPopUp");
      if (req.status === 201)
      {
         var xDoc = req.responseText;
         var jObjs = JSON.parse(xDoc);
      
         for(var i=0,len=jObjs.urls.length;i<len;i++)
         {
            var url = jObjs.urls[i];
            
            var ind1 = url.indexOf('algoparams/');
            if (ind1 > 0)
            {
               var id = url.substring(ind1+11, url.length);
               notifyAlgId(id);
            }
            
         }
      }
      else
      {
         alert("Failed to post algorithm parameters.  Status returned: " + req.status);
      }
   }
}

/* ......................................................................... */
function saveAlgoParams()
{
   var algoCode = document.getElementById("algoCode").value;
   var parameters = algoParams;
   var request = buildAlgoParamsPostRequest(algoCode, parameters);

   var url = "/services/algoparams/json";
   var method = "POST";
   var contentType = "text/json";
   
   openPopUp("loadingPopUp");
   var postAlgReq = new XMLDoc(true, request);
   postAlgReq.loadXMLDoc(url, method, contentType, postAlgorithmParameters);
}

/* ......................................................................... */
function createOccMap(divName, id)
{
   var mapDiv = document.getElementById(divName);
   removeChildrenFromNode(mapDiv);
   var img = new Image();
   var imgUrl = "http://lifemapper.org/ogc?map=data_" + id + "&layers=bmng,occ_" + id + "&request=GetMap&service=WMS&version=1.1.0&bbox=-180.0,-90.0,180.0,90.0&srs=epsg:4326&format=image/png&width=450&height=225&styles=&color=ff0000";
   img.src = imgUrl;
   mapDiv.appendChild(img);
}

/* ......................................................................... */
function validate(value, min, max, opts)
{
   if (min && min !== "")
   {
      if (eval(min) > eval(value))
      {
         alert("Value is outside of range: " + value + " < " + min);
         return false;
      }
      
      if (eval(max) < eval(value))
      {
         alert("Value is outside of range: " + value + " > " + max);
         return false;
      }
   }
   
   if (opts)
   {
      opts = opts.split(",");
   }

   if (opts && opts.length > 0)
   {
      var ret = false;
      for (var i=0; i<opts.length;i++)
      {
         if (value === opts[i])
         {
            ret = true;
         }
      }
      if (!ret)
      {
         alert("Value (" + value + ") is not in list of options: " + opts);
         return false;
      }
   }
   
   return true;
}

/* ......................................................................... */
