/**
 *
 * To be called once, onload.
 *
 */
function expgrp_init(){
  //TODO figure out how to attach this handler and have it actually cancel unload
  window.onbeforeunload="return expgrp_onunload()";
  $$("h3.tab").each(function(tab){
  	var tabLink=tab.down("a");
  	//override default onclick handler
  	tabLink.onclick=null;
  	tabLink.onclick=function(){expgrp_showTab(this);return false;};
  });
	
  plateViewSelectedExperiments=findPlateViewSelectedExperiments();
  $$('option[value="updating"]').each(function(opt){
    opt.disabled="disabled";
  });
  
  //don't just call them directly - avoid "script running slowly" (was an issue with IE6)
  setTimeout("updateQuickSetupFormFields()",10);
  setTimeout("initialisePlateViewFormFields()",10);
}

function expgrp_showTab(elem){
	if(changedFields.length>0){
	  alert("You have unsaved changes on this tab. You must save these before continuing.")
	  return false;
	}
	tab_showTab(elem);
}
/**
 * Make sure only the first experiment in the group is selected,
 * then populate the plate view form fields with its values.
 */
function initialisePlateViewFormFields(){
  var experimentIDs=new Array();

  //Make sure only first experiment checkbox is checked.
  var expCheckboxes=$$("#plateView_selections input");
  expCheckboxes.each(function(checkbox){
  	checkbox.checked="";
  });
  expCheckboxes[0].checked="checked";
	  
  var firstExperiment=experiments[findPlateViewSelectedExperiments()[0]];

  //status
    var field=$("plateview").down(".status");
    field.value=firstExperiment["status"];
  //params
  Object.keys(protocol["params"]).each(function(pd){
    var field=$("plateview").down("."+pd);
    var firstExptValue=firstExperiment["params"][pd];
    
    if(field.hasClassName("checkbox")){
      field.checked=("yes"==firstExptValue.toLowerCase()) ? "checked" : "";
    } else {
	  field.value=firstExptValue;
    }
  });

  //inputs
  Object.keys(protocol["inputs"]).each(function(is){
    var firstExptHook=firstExperiment["inputs"][is]["hook"];
    var firstExptAmount=firstExperiment["inputs"][is]["amount"];

    var fields=$("plateview").getElementsBySelector("."+is);
    fields.each(function(field){
      var fieldClasses=$w(field.className);
      if(-1!=fieldClasses.indexOf("amount")){
          field.value=firstExptAmount;
      } else if(-1!=fieldClasses.indexOf("sample")){
          updateSampleSelect(field,firstExperiment["inputs"][is]["name"],firstExptHook);
      }
    });
  });
}



function expgrp_onunload(){
	return true;
   //TODO This fails
   if(changedFields.length<1) {
     return true;
   }
   return confirm("You have unsaved changes. If you leave this page, they will be lost.\n\nContinue?");
}

/***************************************************************************************
 * Utility functions
 ***************************************************************************************/

//holds the value of a SELECT onfocus - IE doesn't support "disabled" on options, 
//so we may need to reset onchange. Snarl.
var currentSelectValue="";

function fixSelectOnFocus(sel){
  currentSelectValue=sel.value;
  return true;
}

function optionDisabled(sel){
	if(!document.all){
		//shouldn't have got here anyway, but 
		return false; 
	}
	if(sel.options[sel.selectedIndex].disabled || "dummy"==sel.value){
		//restore
		sel.value=currentSelectValue;
		return true;
	}
	return false;
}


function findRefInputSampleForElement(elem){
  var input="";
  Object.keys(protocol["inputs"]).each(function(ris){
    if(""!=input){ return input; }
    if(elem.hasClassName(ris)){
      input=ris;
    }
  });
  return input;
}


/***************************************************************************************
 * Plate view experiment selection
 ***************************************************************************************/

var plateViewSelectedExperiments=new Array();

function toggleExperimentSelection(box){
  var toggledExptId=box.id.substr(3);
  var otherSelectedExpts=findPlateViewSelectedExperiments().without(toggledExptId);

  var toggledExperiment=experiments[toggledExptId];
  //first ticked one that *isn't* the one we changed
    
  var statusSelect =$$("#paramlist .status")[0];
  var paramFields  =$$("#paramlist .param");
  var sampleKeys=Object.keys(protocol["inputs"]);
  var paramKeys=Object.keys(protocol["params"]);
  
  if(box.checked){
    /* adding the experiment to the selection
     * 
     * for all values:
     * if != in all previously selected, nothing to do
     * else compare to FIRST previously selected
     */

  	//ASSUME there was one selected already - shouldn't be able to select none.
  	if(otherSelectedExpts.length>0){
      var firstOtherSelectedExperiment=experiments[otherSelectedExpts[0]];

      if(""!=statusSelect.value){
        if(toggledExperiment["status"]!=firstOtherSelectedExperiment["status"]){
       	  statusSelect.value="";
        } //else nothing to do
      }
      sampleKeys.each(function(key){
	    //ASSUME only one select and one input per inputsample
        var sampleSelect=$$("#paramlist select."+key)[0];
        var sampleAmount=$$("#paramlist input."+key)[0];
	    if("various"!=sampleSelect.value){
		  if(toggledExperiment.inputs[key]["hook"]!=firstOtherSelectedExperiment.inputs[key]["hook"]){
			sampleSelect.value="various";
          }
   	    }
	    if(""!=sampleAmount.value){
		  if(toggledExperiment.inputs[key]["amount"]!=firstOtherSelectedExperiment.inputs[key]["amount"]){
			sampleAmount.value="";
		  }
	    }
      });
      paramKeys.each(function(key){
        //ASSUME only one field per param
        var paramField=$$("#paramlist ."+key)[0];
        if(""!=paramField.value){
	      if(toggledExperiment.params[key]!=firstOtherSelectedExperiment.params[key]){
			paramField.value="";
		  }
	    }
      });
  	}
  } else {
  	//removing the experiment from the selection
 	
    /*
     * for all values:
     * if != in all previously selected, full equality check on remaining
     * else nothing to do
     */
    var selectedExperiments=findPlateViewSelectedExperiments();
    var firstSelectedExperiment=experiments[selectedExperiments[0]];
    if(""==statusSelect.value){
      //full status checks
      var newStatus=firstSelectedExperiment["status"];
      for(i=0;i<selectedExperiments.length;i++){
      	if(newStatus!=experiments[selectedExperiments[i]]["status"]){
      		newStatus="";
      		break;
      	}
      }
      statusSelect.value=newStatus;
    }
    sampleKeys.each(function(key){
      var sampleSelect=$$("#paramlist select."+key)[0];
      var sampleAmount=$$("#paramlist input."+key)[0];
      var currentSample=sampleSelect.value;
      var currentAmount=sampleAmount.value;
	  if(""==currentAmount || "various"==currentSample){
          var amountsEqual=true;
          var samplesEqual=true;
	      var newSampleHook=firstSelectedExperiment["inputs"][key]["hook"];
	      var newSampleName=firstSelectedExperiment["inputs"][key]["name"];
	      var newSampleAmount=firstSelectedExperiment["inputs"][key]["amount"];
	      for(i=0;i<selectedExperiments.length;i++){
	      	var exptSample=experiments[selectedExperiments[i]]["inputs"][key];
	      	if("various"==currentSample && exptSample["hook"]!=newSampleHook){
	      		samplesEqual=false;
	      	}
	      	if(""==currentAmount && exptSample["amount"]!=newSampleAmount){
	      		amountsEqual=false;
	      	}
	      	if(!samplesEqual && !amountsEqual){
	      		break;
	      	}
	      }
		  if(samplesEqual){
		  	updateSampleSelect(sampleSelect,newSampleName,newSampleHook);
		  } else {
		  	updateSampleSelect(sampleSelect,"Various","various");
		  }
		  sampleAmount=(amountsEqual) ? newSampleAmount: "";
      }
    });
    paramKeys.each(function(key){
      //ASSUME only one field per param
      var paramField=$$("#paramlist ."+key)[0];
      if(""==paramField.value){
		//full equality check on param
		// - may not be needed, but not sure how to avoid
		var firstParamValue=firstSelectedExperiment["params"][key];
        var allEqual=true;
        for(i=0;i<selectedExperiments.length;i++){
	      if(experiments[selectedExperiments[i]]["params"][key]!=firstParamValue){
			allEqual=false;
			break;	      	
	      }
	    }
	    if(allEqual){
	      paramField.value=firstParamValue;
	    }
      }
     });
    
  }
}

function findPlateViewSelectedExperiments(){
  var boxes=$("plateView_selections").getElementsBySelector(".checkbox");
  var pvSelectedExperiments=new Array();
  boxes.each(function(box){
    if(box.checked){
      var exId=box.id.substr(3)
      pvSelectedExperiments.push(exId);
    }
  });
  if(pvSelectedExperiments.length<1){
    initialisePlateViewFormFields();
  }
  plateViewSelectedExperiments=pvSelectedExperiments;
  return plateViewSelectedExperiments;
}

/***************************************************************************************
 * Main update handling
 ***************************************************************************************/
function addToChangedFields(field){
	//remove any previous update
    changedFields=changedFields.without(field);
	changedFields.push(field);
}
function clearChangedFields(){
	changedFields.length=0;
}


function findExperimentsToUpdate(elem){
  var exptsToUpdate=new Array();
  if(elem.up("#spreadsheet")){
    exptsToUpdate.push(elem.up("tr").id);
  } else if(elem.up("#quicksetup")){
    exptsToUpdate=Object.keys(experiments);
  } else if(elem.up("#plateview")){
    exptsToUpdate=findPlateViewSelectedExperiments();
  }
  return exptsToUpdate;
}


//TODO Remove duplicate methods
function updateFromSpreadsheet(field){
  field=Element.extend(field);
  addToChangedFields(field);
}
function updateFromPlateView(field){
  field=Element.extend(field);
  addToChangedFields(field);
  return;
}
function updateFromQuickSetup(field){
  field=Element.extend(field);
  addToChangedFields(field);
  return;
}

/**
 * Given a form field, determines the value that should be sent to the server.
 * SELECTS and text fields: field.value
 * Checkboxes: "yes" or "no"
 * Sample amounts: field value + unit
 *
 * @param field The form field that was changed
 * @return An array containing the value to be submitted.
 */
function extractValueFromField(field){
  var valuesToUpdate=new Object();
  field=Element.extend(field);
  var classes=$w(field.className);
  var val=field.value;
  if(-1!=classes.indexOf("status")){
    valuesToUpdate["status"]=field.value;
  } else if(-1!=classes.indexOf("param")) {
    //it's a parameter
    if(-1!=classes.indexOf("checkbox")){
      val=(field.checked)?"yes":"no";
    }
    var keys=Object.keys(protocol["params"]);
    for(var i=0;i<keys.length;i++){
      if(-1!=classes.indexOf(keys[i])){
        definitionKey=keys[i];
        definition=protocol["params"][keys[i]];
        break;
      }
    }
    //TODO validate the param, then...
    valuesToUpdate[definitionKey]=val;
  } else if(-1!=classes.indexOf("input")) {
    //it's an input sample
    keys=Object.keys(protocol["inputs"]);
    for(var i=0;i<keys.length;i++){
      if(-1!=classes.indexOf(keys[i])){
        definitionKey=keys[i];
        definition=protocol["inputs"][keys[i]];
        break;
      }
    }
  } else if(-1!=classes.indexOf("output")) {
    //it's an output sample
    keys=Object.keys(protocol["outputs"]);
    for(var i=0;i<keys.length;i++){
      if(-1!=classes.indexOf(keys[i])){
        definitionKey=keys[i];
        definition=protocol["outputs"][keys[i]];
        break;
      }
    }
  } else if(-1!=classes.indexOf("amount")  && -1==classes.indexOf("input") && -1==classes.indexOf("output")  ){
    //TODO Remove duplication and bizarre logic between this and next block
    var ris=findRefInputSampleForElement(field);
    valuesToUpdate[ris+":amount"] = val+ protocol["inputs"][ris]["displayUnit"];
    if(0==val){
        valuesToUpdate[ris+":sample"]="";
    }
  }
  if(-1!=classes.indexOf("input")||-1!=classes.indexOf("output")){
    if(-1!=classes.indexOf("amount")){
      //TODO validate numeric and 0+
      valuesToUpdate[definitionKey+":amount"]=val+definition["displayUnit"];
      if(0==val){
        valuesToUpdate[definitionKey+":sample"]="";
      }
    } else if (-1!=classes.indexOf("sample")){
      //sample - handle this in a different function chain
        if(""==val) {
        	val="[none]";
        }
        valuesToUpdate[definitionKey+":sample"]=val;
    }
  }

  return valuesToUpdate;
}

/**
 * Prepares a set of parameters for an AJAX update
 * 
 * //Deprecated?
 *
 * TODO this doesn't handle gradients, copyfromplate, etc
 *      - assumes value same for all experiments
 *
 * @param experimentsToUpdate An array of experiment IDs, in the form
 *                             exNNNN, where NNNN is the PiMS "dbId"
 * @param values A map of key-value pairs, in the form
 *                 pdNNNN = 23                     //number param
 *                 pdNNNN = "Hello"                //text param
 *                 pdNNNN = "yes"|"no"             //boolean param
 *                 isNNNN:amount ="2uL"            //sample amount
 *                 isNNNN:sample ="hook.of.sample" //sample hook
 */
function updateExperiments(experimentsToUpdate,values){
  var postParams={};
  var keys=Object.keys(values);

  experimentsToUpdate.each(function(exp){
    keys.each(function(key){
      postParams[exp+":"+key] = values[key]; //URL-escape value?
    });
  });
  updateExperimentsAjaxRequest(postParams);
}


function updateFromChangedFields(){
	if(1>changedFields.length){
		alert("Nothing to save.")
		return false;
	}
	var postParams={};
	changedFields.each(function(field){
		var experimentsToUpdate=findExperimentsToUpdate(field);
		var valuesToUpdate=extractValueFromField(field);
		var valueKeys=Object.keys(valuesToUpdate);
		valueKeys.each(function(vkey){ // :status, :pd123, is122:sample
			experimentsToUpdate.each(function(exkey){ //ex1234
				postParams[exkey+":"+vkey]=valuesToUpdate[vkey];
			});
		});		
	});

	updateExperimentsAjaxRequest(postParams);
	clearChangedFields();
}

/**
 * Makes an AJAX POST to the server, to update values for
 * a number of experiments
 * 
 * @param postParams A map of key-value pairs in the form ex123:status = "Failed"
 */
function updateExperimentsAjaxRequest(postParams){
  openModalDialog("<img src='"+contextPath+"/images/icons/actions/waiting.gif' alt='' />"
    +" Updating..."
  	,"Saving changes"
  );
  //do the AJAX bit
  var req=new Ajax.Request(
    contextPath+"/update/UpdateExperimentGroup/"+experimentGroup.hook,
    {
      method:"post",
      parameters:postParams,
      onSuccess:function(transport){ updateExperiments_onSuccess(transport); },
      onFailure:function(transport){ ajax_onFailure(transport); }
    }
  );

}


function updateExperiments_onSuccess(transport){
  //check still logged in
  ajax_checkStillLoggedIn(transport);
  var responseObj ={};
  try{
    responseObj = transport.responseText.evalJSON(); //possibly surround in try-catch
  } catch(err){
    alert("unparsable JSON:\n"+transport.responseText);
    return false;
  }
  if(!responseObj["updated"]){
    //we got the wrong object somehow!
    //TODO error handling
    alert("There was an error - didn't receive an 'updated' object.");
    return false;
  }
  var updatedExperiments=responseObj["updated"]["experiments"];
  var numExpts=updatedExperiments.length;
try{
  for(var i=0;i<numExpts;i++){
  	var expt=updatedExperiments[i];
  	
    if(!expt){
    	//This probably means IE tripped over the trailing comma and went
    	//round the loop again, so just bail.
    	continue;
    }
    
    var exID="ex"+expt["dbId"];
    var exRow=$(exID);
    var jsExperiment=experiments[exID];

    if(null!=expt["status"]){
      var field=exRow.getElementsBySelector(".status")[0];
      jsExperiment["status"]=expt["status"];
      field.value=expt["status"];
    }
    if(null!=expt["inputs"]){
      if(!jsExperiment["inputs"]) { jsExperiment["inputs"]={}; }
      var iss=Object.keys(expt["inputs"]);
      iss.each(function(is){
        if(!jsExperiment["inputs"][is]) { jsExperiment["inputs"][is]={}; }
        if("[none]"==expt["inputs"][is]["hook"]){
          expt["inputs"][is]["hook"]="";
        }
        if(0==expt["inputs"][is]["amount"]){
          jsExperiment["inputs"][is]["name"]="";
          jsExperiment["inputs"][is]["hook"]="";
          jsExperiment["inputs"][is]["amount"]=0;
    	} else {
          jsExperiment["inputs"][is]["name"]=expt["inputs"][is]["name"];
          jsExperiment["inputs"][is]["hook"]=expt["inputs"][is]["hook"];
          jsExperiment["inputs"][is]["amount"]=parseFloat(expt["inputs"][is]["amount"]);
	    }
        var elems=exRow.getElementsBySelector("."+is);
        elems.each(function(elem){
          if(elem.hasClassName("amount")){
            elem.value=parseFloat(expt["inputs"][is]["amount"]);
          } else if(elem.hasClassName("sample")){
            updateSampleSelect(elem,expt["inputs"][is]["name"],expt["inputs"][is]["hook"])
          }
        });
      });
    }
 
    if(null!=expt["params"]){
      if(!jsExperiment["params"]) { jsExperiment["params"]={}; }
      var pds=Object.keys(expt["params"]);
      pds.each(function(pd){
        field=exRow.getElementsBySelector("."+pd)[0];
        if(field.hasClassName("checkbox")){
          field.checked= (expt["params"][pd]=="yes") ? "checked" : "";
          jsExperiment["params"][pd]=(expt["params"][pd]=="yes") ? "yes" : "no";
        } else {
          field.value=expt["params"][pd];
          jsExperiment["params"][pd]=expt["params"][pd];
        }
      });
    }
    if(null!=expt["outputs"]){
      if(!jsExperiment["outputs"]) { jsExperiment["outputs"]={}; }
      var oss=Object.keys(expt["outputs"]);
      oss.each(function(os){
        if(!jsExperiment["outputs"][os]) { jsExperiment["outputs"][os]={}; }
        if(""==expt["outputs"][os]["name"]){
          jsExperiment["outputs"][os]["name"]="";
          jsExperiment["outputs"][os]["hook"]="";
	    } else {
          jsExperiment["outputs"][os]["name"]=expt["outputs"][os]["name"];
          jsExperiment["outputs"][os]["hook"]=expt["outputs"][os]["hook"];
	    }
        var elems=exRow.getElementsBySelector("."+os);
        elems.each(function(elem){
          if(elem.hasClassName("sample")){
	        if(0==expt["outputs"][os]["amount"]){
              elem.value="";
	        } else {
              elem.value=expt["outputs"][os]["hook"];
	        }
          } else {
	        if(""==expt["outputs"][os]["name"]){
              elem.href="#";
              elem.innerHTML="None";
            } else {
              elem.href="/View/"+expt["outputs"][os]["hook"];
              elem.innerHTML=expt["outputs"][os]["name"];
	        }
          }
        });
      });
    }
    expt=null;
  }
} catch(err){
    alert("Error in updateExperiments_onSuccess, description follows:\n\n"+err.description
          +"\n\nPlease tell the PiMS developers about this message."
          +"\nWe recommend that you reload this page.");
    closeModalDialog();
    return false;
}
  //update QS and plateview boxes
  updateQuickSetupFormFields();
  updatePlateViewFormFields();

  responseObj=null; updatedExperiments=null; inputs=null; outputs=null; params=null;
  closeModalDialog();
}

function updateQuickSetupFormFields(){
  updateBulkEditFormFields("quicksetup");
}
function updatePlateViewFormFields(){
  updateBulkEditFormFields("plateview");
}

/*
 * Given a range of experiments, iterates through the params and samples
 * and sets the relevant bulk-update field (on quick setup or plate view)
 * to the value if all equal or "" if not equal.
 *
 * @param containingElementID "quicksetup" or "plateview"
 *
 */
function updateBulkEditFormFields(containingElementId){
  var experimentIDs=new Array();
  if("quicksetup"==containingElementId){
    experimentIDs=Object.keys(experiments);
  } else if("plateview"==containingElementId){
    experimentIDs=plateViewSelectedExperiments;
  } else {
    alert("Error in updateBulkEditFormFields:\nNo element called "+containingElementId+", can't find fields to update.")
    return false;
  }

  var firstExperiment=experiments[experimentIDs[0]];
  //status
    var qsField=$(containingElementId).down(".status");
    var firstExptStatus=firstExperiment["status"];
    var allEqual=true;
    experimentIDs.each(function(ex){
      if(experiments[ex]["status"] != firstExptStatus){
  	    allEqual=false;
	    return;
      }
    });
    if(allEqual){
 	  qsField.value=firstExperiment["status"];
    } else {
 	  qsField.value="";
    }


  Object.keys(protocol["params"]).each(function(pd){
    var qsField=$(containingElementId).down("."+pd);
    var firstExptValue=firstExperiment["params"][pd];
    var allEqual=true;
    experimentIDs.each(function(ex){
      if(experiments[ex]["params"][pd] != firstExptValue){
        allEqual=false;
	    return;
      }
    });
    if(allEqual){
      if(qsField.hasClassName("checkbox")){
	qsField.checked=("yes"==firstExptValue.toLowerCase()) ? "checked" : "";
      } else {
	qsField.value=firstExptValue;
      }
    } else {
      if(qsField.hasClassName("checkbox")){
	qsField.checked="";
      } else {
	qsField.value="";
      }
    }
  });
  Object.keys(protocol["inputs"]).each(function(is){
    var firstExptHook=firstExperiment["inputs"][is]["hook"];
    var firstExptAmount=firstExperiment["inputs"][is]["amount"];
    var allAmountsEqual=true;
    var allSamplesEqual=true;
    experimentIDs.each(function(ex){
      var inputObject=experiments[ex]["inputs"][is];
      if(inputObject["amount"] != firstExptAmount){
      	allAmountsEqual=false;
      }
      if(inputObject["hook"] != firstExptHook){
	    allSamplesEqual=false;
      }
      if(!allAmountsEqual && !allSamplesEqual){
	    return;
      }
    });
    var qsFields=$(containingElementId).getElementsBySelector("."+is);
    qsFields.each(function(field){
      var fieldClasses=$w(field.className);
      if(-1!=fieldClasses.indexOf("amount")){
        if(allAmountsEqual){
          field.value=firstExptAmount;
        } else {
          field.value="";
        }
      } else if(-1!=fieldClasses.indexOf("sample")){
        if(allSamplesEqual){
          updateSampleSelect(field,firstExperiment["inputs"][is]["name"],firstExptHook);
        } else {
          updateSampleSelect(field,"Various","various");
        }
      }
    });
  });
}



/***************************************************************************************
 * Sample selection
 ***************************************************************************************/
function updateSampleSelect(sel,sampleName,sampleHook){
  sel.value=sampleHook;
  if(sampleHook!=sel.value){
    //this select doesn't have the appropriate option,
    //so make it and select it...
    var opt=document.createElement("option");
    opt.innerHTML=sampleName;
    opt.value=sampleHook;
    sel.appendChild(opt);
    sel.value=sampleHook;
  }
  updateViewLinkClickable(sel);
}

/*
 * Determines whether to make the "View" icon beside a sample SELECT clickable,
 * or greyed-out and non-clickable.
 *
 * @param elem The SELECT.
 */
function updateViewLinkClickable(elem){
  var val=elem.value;
  var icon=Element.extend(elem.parentNode).down("img");
  if(!icon) { return false; }
  if(""==val||"updating"==val||"search"==val||"various"==val){
    setViewLinkNotClickable(elem)
    return false;
  } else {
    setViewLinkClickable(elem)
    return true;
  }
}

/**
 * Makes a View icon beside a sample select clickable
 *
 * @param elem The SELECT.
 */
function setViewLinkClickable(elem){
    var parentCell=elem.up("td");
    var icon=parentCell.down("img");
    var link=parentCell.down("a");
    icon.src=contextPath+"/images/icons/actions/view.gif";
    icon.title="View this sample";
    icon.alt="View this sample";
    link.href=contextPath+"/View/"+elem.value;
    icon.onclick=null;
}

/**
 * Makes a View icon beside a sample select greyed-out and non-clickable
 *
 * @param elem The SELECT.
 */
function setViewLinkNotClickable(elem){
    var parentCell=elem.up("td");
    var icon=parentCell.down("img");
    var link=parentCell.down("a");
    icon.src=contextPath+"/images/icons/actions/viewno.gif";
    icon.title="Can't view";
    icon.alt="Can't view";
    link.href="#";
    icon.onclick="return false;"
}

/**
 * Onchange handler for sample SELECT.
 *
 * Stores the element and sampleCategory info, and opens a selection window.
 *
 * @param elem the SELECT.
 */
function handleSampleSelectChange(elem){
  elem=$(elem);
  var val=elem.value;
  sampleUpdateInfo.sampleSelect=elem;
  var input=findRefInputSampleForElement(elem);
  if(!protocol["inputs"][input]){
    alert("Error in openSampleSelect - can't find a reference sample for "+input);
    return false;
  }
  if(!protocol["inputs"][input]["sampleCategory"]){
    alert("Error in openSampleSelect - can't find a sample category for "+input);
    return false;
  }
  sampleUpdateInfo.sampleCategory = protocol["inputs"][input]["sampleCategory"];

  if("updating"==val||"various"==val){
    //wtf, these should be disabled
    return false;
  } else if("search"==val){
    //open the popup window and find the sample
    sampleUpdateInfo.sampleSelect=elem;

    openModalWindow(
      contextPath
      +"/Search/org.pimslims.model.sample.Sample?isInModalWindow=yes&callbackFunction=doSampleSelectFromSearchWindow"
      +"&hook=org.pimslims.model.protocol.RefInputSample:"+protocol["inputs"][input]["dbId"]
      +"&sampleCategories="+sampleUpdateInfo.sampleCategory['name']
      +"&experimentGroup="+experimentGroup.hook
      ,
      "Search for samples of type \""+sampleUpdateInfo.sampleCategory['name']+"\""
    );
    elem.value=currentSelectValue; //just in case the user cancels
  } else {
    //it's "none" or a sample in the list
    addToChangedFields(elem);
  }
}


/**
 * Called from search/select in modal window. Extracts the sample
 * hook from the returned object and passes it to doSampleSelect.
 *
 * @param result An object returned from the search window, e.g.,
 *               { hook:"org.pimslims.sample.Sample:1234" }
 */
function doSampleSelectFromSearchWindow(result){
  if(!result["hook"]){
    alert("Error in doSampleSelectFromSearchWindow:/nResult doesn't appear to contain an object hook")
    return false;
  }
  closeModalWindow();

  var elem=sampleUpdateInfo.sampleSelect;
  updateSampleSelect(elem,result["name"],result["hook"]);
  addToChangedFields(elem);
}


/**
 * //deprecated?
 * 
 * Called on change, and after search/select in modal window.
 * Fires an AJAX request to update the appropriate experiments with selected sample.
 *
 * If sample hook is "", set amount to 0 as well.
 */
function doSampleSelect(hook){
  closeModalWindow();
  var paramsToUpdate={};
  var experimentsToUpdate=findExperimentsToUpdate(sampleUpdateInfo.sampleSelect);
  var elem=sampleUpdateInfo.sampleSelect;
  showUpdating(elem);
  var input= findRefInputSampleForElement(elem);
  if(""==hook){
    hook="[none]";
  }
  experimentsToUpdate.each(function(expt){
    paramsToUpdate[input+":sample"] = hook;
    if("[none]"==hook){
      paramsToUpdate[input+":amount"] = "0"+protocol["inputs"][findRefInputSampleForElement(elem)]["displayUnit"];
    }
  });

  setViewLinkNotClickable(elem);

  updateExperiments(experimentsToUpdate,paramsToUpdate);

}

