// page_GasMix.js - javascript for the gas mix search and editor pages.
//
// Actions:

function GasMixSearchPageObject ()
{}

GasMixSearchPageObject.prototype.vars =
{
	timerID: null,
	timerRunning: false
};

GasMixSearchPageObject.prototype.init = function(arg)
{
//	alert('In init()');

	document.getElementById("gm_txtGasMixDescSearch").value = '';
	document.getElementById("gm_GasMixSuggestions").innerHTML='';
	document.getElementById("gm_GasMixSuggestions").style.display = "none";
};

GasMixSearchPageObject.prototype.stopTimer = function()
{
	if (this.vars.timerRunning)
		clearTimeout(this.vars.timerID);
	this.vars.timerRunning = false;
};

GasMixSearchPageObject.prototype.GasMixDescSearch = function()		// Show suggested GasMix - actual query delayed by timer
{
//trace('GasMix.GasMixDescSearch()');
	this.stopTimer();
        this.vars.timerRunning = true;
        this.vars.timerID = self.setTimeout("gasMixSearch.submitFilteredGasMixDescSearch()", 400);	// Hold the request for 400 mSecs.
};

GasMixSearchPageObject.prototype.submitFilteredGasMixDescSearch = function()		// Timer base submission of search
{
	var textNode = document.getElementById("gm_txtGasMixDescSearch");
	var textVal = util.trim(textNode.value);
//trace('desc search:'+textVal);
	xajax_searchGasMixDescriptions(textVal);
};

GasMixSearchPageObject.prototype.unselectGasMix = function()		// Cancel search based on empty search key
{
	trace('in GasMixSearchPageObject.unselectGasMix()');
};

GasMixSearchPageObject.prototype.selectGasMix = function()		// Select customer from search list
{
	// This is a callback function which is attached to a DOM object by Teuker.
	// The 'this' pointer refers to the DOM object, not to this class.

	trace('in gasMixSearch.selectGasMix()'+this.id);
//	alert('Selected GasMix with UID:'+this.id+'.  Will use to display Gas Mix for edit.');
	xajax_selectGasMix(this.id);				// Tell app about selected (this clears the autosuggest)
};

var gasMixSearch = new GasMixSearchPageObject;

// ---------------------------------------------------------------------------------------------------

function GasMixEditorPageObject ()
{}

GasMixEditorPageObject.prototype.vars =
{
	description: null,
	component: null,
	componentList: null,		// Associative array of components
	indexedComponentList: null,	// Sorted array of component UIDs, arranged by concentration
	componentCt: 0
};

GasMixEditorPageObject.prototype.resetEditorTable = function()
{
	var tableNode = document.getElementById("gm_tblEditor").getElementsByTagName("TBODY").item(0); //	??? Why item(0)?
	var rows = tableNode.getElementsByTagName("tr");

	for (var i = rows.length-1; i >= 0; --i)	// Reverse order to avoid reindexing when rows are deleted
	{
		var row = rows[i];
		var id = row.id;
		if (id.substr(0, 6) == 'gm_row' && id != 'gm_rowAdd' && id != 'gm_rowTemplate')
		{
			row.parentNode.removeChild(row);
		}
	}
};

GasMixEditorPageObject.prototype.init = function(arg)
{
//	alert('In init()');

	document.getElementById("GasMixesError").innerHTML='';
	this.vars.componentList = new Object();	// Key/value pairs - don't use array
	this.vars.indexedComponentList = new Array();
	this.initComponent();
	this.resetEditorTable();
};

GasMixEditorPageObject.prototype.initComponent = function()
{
//	alert('In init()');

	// NOTE: Do NOT change these names without changing the PHP variables names
	// used by the GasMix create/update functions.
	this.vars.component = new Object();
	document.getElementById("gm_selMixComponent").options[0].selected = true;
	this.vars.component.ID = 0;
	document.getElementById("gm_txtComponentAmount").value = '';
	this.vars.component.amount = '';
	this.vars.component.conc = 0;
	document.getElementById("gm_selComponentUnits").options[0].selected = true;
	this.vars.component.units = -1; // Zero flags unselected
	this.vars.component.unitText = '';
	document.getElementById("gm_txtPercentLEL").value = '';
	this.vars.component.percentLEL = '';

	this.enableComponentAdd();
};

GasMixEditorPageObject.prototype.load = function(jsonText)
{
//	alert('In load('+jsonText+')'); // !!! This appears to be called twice - dig into this

	var jsonT = eval( '('+jsonText+')' ); // !!! Use JSON parser
	this.init();

	this.vars.description = jsonT.Description;
	document.getElementById("gm_gasMixName").value = this.vars.description;
	for (var comp in jsonT)
	{
		if (typeof jsonT[comp] == "function")
			continue;

		if (comp != 'Description')
		{
			var component = jsonT[comp];
			this.vars.component.ID = comp;
			this.vars.component.cpntName = component.Name;
			this.vars.component.amount = component.Quantity;
			this.vars.component.percentLEL = component.PercentLEL;
			this.vars.component.unitText = (component.Units == 'BAL' ? 'Balance' : component.Units);
//			this.vars.component.conc = component.QuantityPPB;
			this.vars.component.conc = this.convertToPPM(this.vars.component.amount, this.vars.component.unitText);

			this.addComponent();
		}
	}
	selectPage('gasMixEditorPage');
}


GasMixEditorPageObject.prototype.componentConcentrationOrder = function(a, b)
{
	// 'a' and 'b' are UIDs, not components.  Use them to refer
	// to objects in componentList.  Do not use 'this' as this function
	// is called from within the scope of the document and not this object.

	var rslt = gasMixEditor.vars.componentList[a].conc - gasMixEditor.vars.componentList[b].conc;
	if (rslt != 0)
		return rslt;
	
	if (gasMixEditor.vars.componentList[a].cpntName < gasMixEditor.vars.componentList[b].cpntName)
		return -1;
	if (gasMixEditor.vars.componentList[a].cpntName > gasMixEditor.vars.componentList[b].cpntName)
		return 1;

	return 0;
}

GasMixEditorPageObject.prototype.createEdgeArray = function()
{
	// Build an array of compoent UIDs.  Sort the array by component concentations.
	// This yields the display order for the components.

	this.vars.indexedComponentList.length = 0;
	for (var comp in this.vars.componentList)
	{
		if (typeof this.vars.componentList[comp] == "function")
			continue;

		this.vars.indexedComponentList.push(comp);
	}
	this.vars.indexedComponentList.sort(this.componentConcentrationOrder);
}

GasMixEditorPageObject.prototype.enableComponentAdd = function()
{
	// Evaluate all items on the "Add" row to determine if the component "Add" button is
	// to be enabled.  If it is, take the opportunity to compute the quantity in a common
	// PPB notation (PCT multiplied by 10,000,000).

	if (this.vars.component.ID == 0 || (this.vars.component.ID in this.vars.componentList)
	|| (this.vars.component.unitText != 'Balance'
		&& (isNaN(this.vars.component.amount) || Number(this.vars.component.amount) <= 0))
	|| this.vars.component.units <= 0)
	{
		document.getElementById("gm_btnComponentAdd").disabled = true;
	}
	else
	{
		document.getElementById("gm_btnComponentAdd").disabled = false;

		// We know the row is valid, so we remove errors (somewhat kludgy).  Take
		// the opportunity to compute a concentration in PPB for sorting.

		document.getElementById("GasMixesError").innerHTML='';
		this.vars.component.conc = this.convertToPPM(this.vars.component.amount, this.vars.component.unitText);
	}
}

GasMixEditorPageObject.prototype.convertToPPM = function(amount, units)
{
	switch(units)
	{
	  case 'PPB' :	return amount;
	  case 'PPM' :	return amount * 1000;
	  case 'PCT' :	return amount * 10000000;
	  case 'Balance' : return 1000000000;
	}
}

GasMixEditorPageObject.prototype.updateGasMixDescription = function(node)
{
	this.vars.description = util.trim(node.value);
}

GasMixEditorPageObject.prototype.setComponent = function(element)
{
	var idx = element.selectedIndex;
	var selText = element.options[idx].text;
	var selVal = element.options[idx].value;

	document.getElementById("GasMixesError").innerHTML='';
	if (selVal in this.vars.componentList)
		document.getElementById("GasMixesError").innerHTML="The selected component in already in the mix.";

//	alert('In setComponent('+selVal+', '+selText+')');
	this.vars.component.ID = selVal;
	this.vars.component.cpntName = selText;
	this.enableComponentAdd();
};

GasMixEditorPageObject.prototype.setAmount = function(element)
{
	var textVal = util.trim(element.value);
//	alert('In setAmount('+textVal+')');
	document.getElementById("GasMixesError").innerHTML='';
	if (isNaN(textVal) || Number(textVal) <= 0) {
//		alert('err');
		document.getElementById("GasMixesError").innerHTML="The amount '"+textVal+"' is not a positive number.";
	}
	this.vars.component.amount=textVal;
	this.enableComponentAdd();
};

GasMixEditorPageObject.prototype.setUnits = function(element)
{
	var idx = element.selectedIndex;
	var selText = element.options[idx].text;
	var selVal = element.options[idx].value;

//	alert('In setUnits('+selVal+', '+selText+')');
	this.vars.component.units = selVal;
	this.vars.component.unitText = selText;
	this.enableComponentAdd();
};

GasMixEditorPageObject.prototype.setPercentLEL = function(element)
{
	var textVal = util.trim(element.value);
//	alert('In setPercentLEL('+textVal+')');
	document.getElementById("GasMixesError").innerHTML='';
	if (textVal > '' && (isNaN(textVal) || Number(textVal) <= 0)) {
//		alert('err');
		document.getElementById("GasMixesError").innerHTML="The percent LEL amount '"+textVal+"' is not a positive number.";
	}
	this.vars.component.percentLEL=textVal;
	this.enableComponentAdd();
};

GasMixEditorPageObject.prototype.addComponent = function()
{
//	alert('In addComponent()');

//	Store the current component (in the add row) into the component list.
//	Clone the template row, fill it in with the "added" data and insert it into the table
//	in the position defined by the edge array (current order is by concentration).

	this.vars.componentList[this.vars.component.ID] = this.vars.component;
	++this.vars.componentCt;
	this.createEdgeArray();

//	Find the rowID before which to insert this row.  Only search to the penultimate
//	element of the edge array.

	var insertBeforeRowNamed = "gm_rowAdd";	// Default is to add befor the "add" row
	for (var i = 0;  i < this.vars.indexedComponentList.length - 1; ++i)
	{
		if (this.vars.indexedComponentList[i] == this.vars.component.ID)
		{
			insertBeforeRowNamed = 'gm_row'+this.vars.indexedComponentList[i+1];
			break;
		}
	}

	// Clone the template row and initialize it.

	var tableNode = document.getElementById("gm_tblEditor").getElementsByTagName("TBODY").item(0); //	??? Why item(0)? - first one?
	var newRow = document.getElementById("gm_rowTemplate").cloneNode(true);	// Deep clone
	var columns = newRow.getElementsByTagName("td");
	var isBalanceGas = (this.vars.component.unitText == 'Balance');

	newRow.id='gm_row'+this.vars.component.ID;
	newRow.style.visibility="visible";

	columns[0].firstChild.nodeValue = 'T.B.D.';
	columns[1].firstChild.nodeValue = this.vars.component.cpntName;
	columns[2].firstChild.nodeValue = isBalanceGas ? '' : this.vars.component.amount + ' ' + this.vars.component.unitText;
	columns[3].firstChild.nodeValue = this.vars.component.percentLEL;
	columns[4].firstChild.name = this.vars.component.ID;
	columns[4].firstChild.onclick = this.deleteComponent;

	tableNode.insertBefore(newRow, document.getElementById(insertBeforeRowNamed));

	// Relabel the rows.  This is necessary as the DOM is reordered by the
	// insertion of the new row.
	// !!! Problem - the edge array is unstable when the components are of equal value (0, e.g.)
	// !!! Probably should order by position in the grid.

	for (i = 0;  i < this.vars.indexedComponentList.length; ++i)
	{
		var compID = this.vars.indexedComponentList[i];
		columns = document.getElementById("gm_row"+compID).getElementsByTagName("td");

		if (i == this.vars.indexedComponentList.length - 1	// Last element
		&& this.vars.componentList[compID].unitText == 'Balance')
		{
			columns[0].firstChild.nodeValue = 'Balance: ';
		}
		else
		{
			columns[0].firstChild.nodeValue = 'Component ' + (i+1) + ': ';
		}

	}

	this.initComponent();	// Re-init component add row
};

GasMixEditorPageObject.prototype.deleteComponent = function()
{
//	alert('In deleteComponent()');

//	It is always safe to delete a row in place as it does not destroy the
//	sort order.  However, the labels must be rewritten.  May as well
//	refresh the grid.

	var UID = this.name;
	var delRow = document.getElementById('gm_row'+UID);

//	Copy the values from the deleted row into the "add" row.  This facilitates
//	editing a component

	gasMixEditor.vars.component = gasMixEditor.vars.componentList[UID];

	util.setSelectionByText("gm_selMixComponent", gasMixEditor.vars.component.cpntName);
	document.getElementById("gm_txtComponentAmount").value = gasMixEditor.vars.component.amount;
	gasMixEditor.vars.component.units = util.setSelectionByText("gm_selComponentUnits", gasMixEditor.vars.component.unitText);
	document.getElementById("gm_txtPercentLEL").value = gasMixEditor.vars.component.percentLEL;

	delete gasMixEditor.vars.componentList[UID];
	--gasMixEditor.vars.componentCt;
	delRow.parentNode.removeChild(delRow);
	gasMixEditor.enableComponentAdd();
};

GasMixEditorPageObject.prototype.updateGasMix = function()
{
//	alert('updateGasMix');
	xajax_updateGasMix(this.vars.toJSONString());		// Tell app about selected (this clears the autosuggest)
}

GasMixEditorPageObject.prototype.createGasMix = function()
{
//	alert('createGasMix');
	xajax_createGasMix(this.vars.toJSONString());		// Tell app about selected (this clears the autosuggest)
}

GasMixEditorPageObject.prototype.deleteSelectedGasMix = function()
{
//	alert('deleteGasMix');
	xajax_deleteSelectedGasMix();					// Tell app about selected (this clears the autosuggest)
}			

var gasMixEditor = new GasMixEditorPageObject;
