/* --------------------------------------------------------------------------* 
 *              Parameter plugin                                             *
 * Note:this script relies on code from /pathways/zxml.js                    *
 *---------------------------------------------------------------------------*/

//* Global Variables *
var paramPtr;

var ParamList = Class.create(AjaxPlugin, {
  initialize: function (element_id, config_file, session_object)
  {
  
    paramPtr = this;
    
    // Remember our host element
    this.hostElementID = element_id;
    this.config_file = config_file;
    this.paramslist = new Array();
    this.sessionPtr = session_object;
    this.sessionData = "";
       
    // Todo:? an associative array to hold our event handler pointers
    this.eventHandlers = [];
    
    // Set up our HTML:
    this.initializeHtml();

    // Get our configuration and display ourself:
    this.showParamList(); 
  },
  
  //*---------------------------------------------------------------------------*
  initializeHtml: function()
  { //Todo:? remove the 'form'? just use the hostelementID when creating param fields.
    var myHtml = 
                 "<form id=\"parameterForm\" style=\"border:0px\" method=\"get\">"+
                 //"<a class=plugtitle>Design Parameters</a> <br />"+
                 //" action=\"parameterSubmit\" method=\"post\">\n"; //?
                 // "style=\"left:110px; top:5px; width:100px;\" />" +
                 // "<input type=submit value=\" GetParams \" "+
                 // A key piece:
                 //"onclick=\"javascript:getParameters();\" " +                 
                  "</form>" +
                  "<span id=\"paramHelpPopup\"><a>testing</a></span>";

    // Add this HTML to our host element
    var hostElement = document.getElementById(this.hostElementID);
    hostElement.innerHTML = myHtml;
  }, // End of this.initializeHtml()
  

  //*---------------------------------------------------------------------------*
  showParamList: function()
  {
    var URL = this.config_file;
    
    new Ajax.Request(URL, 
                     {
                       method: 'get',
                       onSuccess: function(transport) {
                           paramPtr.initializeParameterBox(transport.responseText)
                       },
                       onFailure: function(transport) {
                           throw("ajax call error: " + URL + 
                                 " - " + transport.statusText);
                       }
                     });
    
  },// End of this.showParamList()

  //*---------------------------------------------------------------------------*
  // Parse the XML data and put it into the HTML elements 
  initializeParameterBox: function(appJSON)
  {  
    // create an XML DOM document, load XML data into it and parse DOM document
    var appData = appJSON.evalJSON();
    if (typeof(appData.application) != "object")
      throw "Unable to retrieve design_param list from server data";
    else
      appData = appData.application;

    var parameterForm = $("parameterForm"); 

    // First, retrieve any stored parameter values from our session, which
    // we will use for initialization here
    var sessionDataString = this.sessionPtr.getParam("paramSessionData");
    if (sessionDataString !== '')
    {
      this.sessionData = sessionDataString.evalJSON();
    }
    else {this.sessionData = "";}
    

    // Create an empty table to hold the parameters
    var paramTable = document.createElement('table');

    // Loop through each of the design_params
    appData.design_params.each(function(param) {
      //console.log(param.name);

      // create param fields:insert a row:
      pRow = paramTable.insertRow(0);
      // Add a tooltip with the help text:
      //pRow.onmouseover = _paramShowHelp;
      //pRow.onmouseout  = _paramDismissHelp;
      //pRow.title = pHelp;
      // Insert the 3 cells in the row:
      var pLabel = pRow.insertCell(0); pLabel.align="right";//label
      var pInput = pRow.insertCell(1); //pInput.width="200";//input field
      var pRange = pRow.insertCell(2); //pRange.width="50";
      pRange.className = 'paramRangeCell';//range
      
      var pHelpCell  = pRow.insertCell(3);
			var helpBalloon = new HelpBalloon({
        //icon:    '../shared/images/icon_question.gif',
        returnElement: true,
				title:   param.name,
				content: param.helptext
			});

      var helpDiv = $div({id: param.name + '_help',
                         'class':'webApps_button',
                         style: 'padding:0px;'});
      $(pHelpCell).appendChild(helpDiv);
      helpDiv.appendChild(helpBalloon._elements.icon);

      var newInput;

      // create input param fields according to param data type
      // list type: create drop down list
      if (param.datatype == 'list')
      {
        newInput = document.createElement("select");
        newInput.id = 'param_' + param.name;
       
        param.values.each(function(value){
          // create new options and add them to select box
	        var newSelectOption = document.createElement("option");
          newSelectOption.text = value.value;
          newSelectOption.value = value.value;
          // add the option to the select
          
          try {
          newInput.add(newSelectOption, null); // standards compliant; doesn't work in IE
          }
          catch(ex) {
            newInput.add(newSelectOption); // IE only
          }
        }); // list values loop
      } // datatype == list
      else // for all other data types other than 'list'
      {
        newInput   = document.createElement('input');
        newInput.type  = 'text';
        newInput.name  = param.name; 
        newInput.id    = 'param_' + param.name;
        newInput.className = 'paramInput';
  
      }// end of param datatype:if-else
      
      // associate a validation function to the param field
      // Note:only int, float, seq are validated. text is ingored
      //newInput.onchange = checkValueA;
      newInput.onchange = "validateField('param_" + param.name + "','" + param.datatype   + "','" +
                                              param.lower_bound  + "','" + param.upper_bound + "','" + 
                                              param.default_value + "')"; 
                                               
      var onChangeHandler = new Function(newInput.onchange);
      if (newInput.addEventListener) {
         newInput.addEventListener('change', onChangeHandler, false );
      } else if (newInput.attachEvent) {
        newInput.attachEvent('onchange', onChangeHandler);
      }		
      // disable param field
      if (!param.editable) 
      {
        newInput.disabled = 1; //newInput.readOnly = 1; 
      }

      // set label
      //pLabel.appendChild(document.createTextNode(pDisplayName+': '));
      pLabel.innerHTML = "<a class=\"paramLabel\">" + param.display_name +
      "</a><span style=\"display:none;\">" + param.helptext + "</span>";

      // set default value and newInput to form input field
      newInput.value = param.default_value;
      pInput.appendChild(newInput); //input field
      // set range field
      if (param.datatype == 'integer' || param.datatype == 'float')
        pRange.appendChild(document.createTextNode(param.lower_bound+' - '+param.upper_bound)); //range
//      if (!param.visible) {$(pInput).hide(); $(pLabel).hide(); $(helpDiv).hide()}; //hide the parameter

      if (!param.visible) {$(pRow).hide();}; //hide the parameter
    }); // end of param loop

    //console.log("table"+ paramTable.innerHTML);
    parameterForm.appendChild(paramTable);

    paramTable.style.background = '#eee';

  }, // End of this.initializeParameterBox()

  //*---------------------------------------------------------------------------*
	getParametersXML: function(format)
	{ 
     var param_elems=$("parameterForm").getElements();
     var pXml = "";

	  param_elems.each(function(param)
     { 
       var param_name = param.id;

       param_name = param_name.replace(/^param_/, ""); // Figure out a better way for this
       if (format == 'LONGFORMAT')
       {
         pXml += '  <param><name>'+param_name + '</name><value>'+
                $F(param) + "</value></parameter>\n";
       }
       else
       {
         pXml += '  <parameter name="'+param_name + '">'+
                $F(param) + "</parameter>\n";
       }
     });
    
	  return pXml;
	},// End of this.getParametersXML()

  //
  saveSessionData: function()
  {
    var obj = $H({}); 
    var x=$("parameterForm");
    for (var i=0;i < x.length; i++)
    {
       obj[x.elements[i].id] = $F(x.elements[i].id);
    } 
    var pJson = obj.toJSON();
    
    //console.log ("pJson>>"+ pJson);
    this.sessionData = pJson.evalJSON();

    this.sessionPtr.setParam("paramSessionData", pJson);
  },

  //*---------------------------------------------------------------------------*
	getParameterValue: function(paramName)
	{ 
    return $F('param_' + paramName); 
	},// End of this.getParameterValue

  //*---------------------------------------------------------------------------*
	setParameterValue: function(paramName, paramValue)
	{ 
     var paramField = $('param_' + paramName);

     if (paramField === null)
       return;
     
     if (paramField.type == 'select-one')
     {
       for (var i = 0; i < paramField.options.length; i++) 
       {
	      if (paramField.options[i].text == paramValue )
	        paramField.options[i].selected = true;
	    }
	  }
     else if (paramField.type == 'text')
     { paramField.value = paramValue;}
     
     return true;
     
	},// End of this.setParameterValue

  //----------------------------------------------------------------------------
  setEventHook: function(event_name, javascript_func)
  {
    this.eventHandlers[event_name] = javascript_func;  
  },// End of setHook()
  
  //----------------------------------------------------------------------------
  raiseEvent: function(event_name, parameter, new_value)
  {
    var function_ptr = this.eventHandlers[event_name];
    if (function_ptr)
    {
      function_ptr(parameter, new_value);
    }
  }// End of raiseEvent()


}); // End of paramList object

//*---------------------------------------------------------------------------*
function _showParameters()
{
  var sXml = getParameters();
  alert(sXml);
}

//*---------------------------------------------------------------------------*
function checkValueA(evt)
{
   var new_value = evt.currentTarget.value;
   alert("checkvalue: "+new_value);
}

//*---------------------------------------------------------------------------*
function validateField(field, data_type, min, max, def_val)
{
   efield = $(field);
   //alert("check valueC:value="+efield.value +',type=' + data_type +',min=' + min +',max='+ max);
   if ((data_type == 'integer') || (data_type == 'float'))
   {
     new_value = efield.value; new_value1 = new_value;
     new_value1 = new_value1.replace(/\s/g, ""); // remove all whitespaces
     new_value1 = new_value1.replace(/^[0]+/g, ""); // remove leading 0's
     //alert("new_value2:"+new_value);
     efield.value = new_value1; // put trimmed value into the field
     // if the value is a integer or float then check for valid range
     if ((data_type == 'integer' && (new_value1.match(/^[-+]?\d+$/))) || 
         (data_type == 'float' && (new_value1.match(/^[-+]?\d*\.?\d+$/))))
     {
       num = parseFloat(new_value1);
	    if (num < parseFloat(min) || num > parseFloat(max))
       {
         alert(field +":"+ num +" is out of valid range!\n Resetting back to the default value.");
         //set the value back to default value
 		   efield.value = def_val;
	    } 
     }
     else {alert('not is valid number');efield.value = def_val;}
   }
   else if (data_type == 'sequence') //sequence
   {  
      new_value = efield.value;
      // check for valid sequence
      if (!(new_value.match(/^[ACGTN-]*[ACGTN-]+$/i)))
      {
        alert(new_value +" is NOT a sequence")
        //set the value back to default value
 		  efield.value = def_val; 
      }
   }
   else if ((data_type == 'text') || (data_type == 'list'))//text
   {  
      new_value = efield.options[efield.selectedIndex].text;
      // any text validation goes here
   }
   else {alert('invalid data type: '+ data_type);}
   
   //alert ("type:"+efield.type);
   paramPtr.saveSessionData();
   
   // Alert any interested parties that a value may have been changed:
   paramPtr.raiseEvent("param_changed", field, new_value);
   
   // This format is obsolete!  Remove it eventually:
   paramPtr.raiseEvent("param_change:" + field, new_value);
   
} // End of ValidateField

var saved_class = "";

// Display the help popup:
function _paramShowHelp(evt)
{
  var popup = $("paramHelpPopup")
  // This code assumes that the help text is a 'data island' inside the <a>
  // element in the first cell of the table:
  var help_text = this.firstChild.lastChild.innerHTML;
  saved_class = this.className; // Save the TR class
  this.className = "paramHelpHighlight"; // Highlight the background
  popup.innerHTML = "<a>" + help_text + "</a>";
  var containerTop = $("parameterForm");
  var mouseY = 15; //_paramMouseY(evt) - 250; //parseInt(containerTop);
  if (mouseY < 0) return;
  popup.style.top =  mouseY + "px";
  popup.onclick=_paramDismissHelp;
  popup.style.display = "inline";
  //popup.style.left = ?;

}

// Dismiss the help popup:
function _paramDismissHelp(evt)
{
  $("paramHelpPopup").style.display = "none";
  this.className = saved_class;
}

// This function gets the Y value of the event target
function _paramMouseY(evt) {
if (!evt) evt = window.event; 
if (evt.clientY)
return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
else if (evt.pageY) return evt.pageY;  
else return 0;
}

//*---------------------------------------------------------------------------*
