//==============================================================================
// cfxEngine
// born by  : shawn oster
//
// history  :
//
// 1.3 added metadata support
//
// 1.2 added packageData
//
// 1.1 added parseData and loadDataFormat routines
//
// 1.0 initial release
//
//==============================================================================
// encapsulates the various methods of the activex print object
//==============================================================================

//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
function cfxEngine(login, password, obj)
{

	// attempt to create engine
	try
	{
		// first attempt to use the engine object on the page
		if (obj == undefined)
		{
			this.activeX = document.getElementById('lawe');
			if (this.activeX == null)
			{
			    this.activeX = new ActiveXObject("CfxWebLibrary.CfxWebEngine");
			    this.activeX.LocationUrl = location.hostname;
			}
		}
		else
		{
			this.activeX = obj;
		}

		if (IsLocal == 'true')
		{
		    this.activeX.LocationUrl = TestUrl;
		}

	    this.login = login;
		this.password = password;
		this.isValid = true;
	}
	catch(e)
	{
		this.activeX = undefined;
		this.isValid = false;
	}

  if (!this.isValid) {
  	return;
	}

  this.version = this.activeX.version;
  this.lastError = '';

  // handles any engine errors by displaying a message with the appropriate error message
  this.handleEngineError = function(e)
  {
  	this.lastError = e.description;
  	alert(format(localPrintEngineError, this.lastError));
  }

	//------------------------------------------------------------------------------
	// Job methods
	//------------------------------------------------------------------------------

	// isCached
	this.isCached = function(jobId)
	{
		return this.activeX.GetCachedJobVersion(jobId) > 0;
	}
	// cacheJob
	this.cacheJob = function(jobId)
	{
		return this.activeX.CacheJob(jobId);
	}

	//------------------------------------------------------------------------------
	// Data methods
	//------------------------------------------------------------------------------

	// importData
	this.importData = function(jobId)
	{
		try {
			return this.activeX.ImportData(this.login, jobId);
		} catch(e) {
			this.handleEngineError(e);
		}
	}

	// export grid data as a csv file
	this.exportData = function(xmlData)
	{
		try {

			return this.activeX.ExportCSVData(xmlData);

		} catch(e) {
			this.handleEngineError(e);
		}
	}


	// rememberData
	this.rememberData = function(jobId, data)
	{
		try {
			return this.activeX.RememberData(this.login, jobId, data);
		} catch(e) {
			this.handleEngineError(e);
		}
	}
	// retrieveData
	this.retrieveData = function(jobId)
	{
		try {
			return this.activeX.RetrieveData(this.login, jobId);
		} catch(e) {
			this.handleEngineError(e);
		}
	}
	// getDataFormat
	this.getDataFormat = function(jobId)
	{
		try {
			return this.activeX.getDataFormat(jobId);
		} catch(e) {
			this.handleEngineError(e);
		}
	}
	// loadDataFormat
	this.loadDataFormat = function(jobId)
	{
		// get the dataformat in xml from the cached job
		this.xmlDataFormat = this.getDataFormat( jobId );
		if ((this.xmlDataFormat) && (this.xmlDataFormat.length > 0))
		{
			var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
			xmlDoc.async = false;
			if (!xmlDoc.loadXML( this.xmlDataFormat ))
				alert(xmlDoc.parseError.reason);

			var fieldDefs = xmlDoc.documentElement.getElementsByTagName('fielddef');
			this.dataFormat = new Array();
			this.dataFormat.length = fieldDefs.length;

			// changed from using nextNode to a for loop because of Gary.
			// His copy of MS XMLDOM crashed, reporting the "nextNode" method didn't exist
			for (var i = 0; i < fieldDefs.length; i++) {
				var fieldDef = new Array();
				fieldDef[0] = fieldDefs.item(i).attributes.getNamedItem('name').text;
				fieldDef[1] = fieldDefs.item(i).attributes.getNamedItem('fieldsize').text;
				this.dataFormat[i] = fieldDef;
			}
		}
		return this.dataFormat;
	}
	// parseData
	this.parseData = function(jobId, data)
	{
		if (data.length == 0)
			return false;

		//
		// Parse header to ensure it matches the current field header
		//
		var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
		xmlDoc.preserveWhiteSpace = true;
		xmlDoc.async = false;
		xmlDoc.resolveExternals = false;
		if (!xmlDoc.loadXML( data ))
			alert(xmlDoc.parseError.reason);


		//
		// Check: Are the number of fields the same?
		//
		var fieldDefs = xmlDoc.documentElement.getElementsByTagName('fielddef');

		// load the dataformat if it hasn't already been
		if (this.dataFormat == undefined)
			this.loadDataFormat(jobId);

		if (this.dataFormat.length != fieldDefs.length) {
			alert( 'Number of fields are different' );
			return 0;
		}

		//
		// Check: are the field names the same?
		//
		var fieldDefNode;
		for (i=0; i < this.dataFormat.length; i++) {
			fieldDefNode = fieldDefs.nextNode;
			if (this.dataFormat[i][0] != fieldDefNode.attributes.getNamedItem('name').text) {
				alert( 'Field name is different' );
				return 0;
			}
		}

		//
		// Create and populate a records array with all of the data
		//
		var records = new Array();

		var recordIndex = 0;
		var fieldIndex = 0;

		var rows = xmlDoc.documentElement.getElementsByTagName('row');
		var rowNode = rows.nextNode;
		var valueAttrib;
		while (rowNode != null)
		{
			var record = new Array();
			record.length = 0;

			fieldIndex = 0;
			var fields = rowNode.selectNodes('field');
			var fieldNode = fields.nextNode;
			while (fieldNode != null)
			{
				valueAttrib = fieldNode.attributes.getNamedItem('value');
				if (valueAttrib != undefined) {
					record[fieldIndex++] = valueAttrib.text;
				 } else {
					record[fieldIndex++] = '';
				 }
				fieldNode = fields.nextNode;
			}
			rowNode = rows.nextNode;

			// add the record to the array of all records
			records[recordIndex++] = record;
		}

		return records;
	}
	// package data - takes a JavaScript array of arrays and packages it in the
	// correct xml data format required by the ActiveX.  Assumes field values are
	// in the same order as the fields returned from loadDataFormat
	//
	this.packageData = function(jobId, records)
	{
		// load the dataformat if it hasn't already been
		if (this.dataFormat == undefined)
			this.loadDataFormat(jobId);

		// allow zero records to be used.  it isn't technically an error condition
		// it just doesn't make a lot of sense
		var recordCount = records.length;
		if (recordCount > 0) {
			if (records[0].length != this.dataFormat.length) {
				alert('packageData needs the exact number of fields for jobId [' + jobId + '], found ' + records[0].length + ' and was expecting ' + this.dataFormat.length);
				return '';
			}
		}

		// create xml object
		var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
		xmlDoc.async = false;
		xmlDoc.resolveExternals = false;

		// version and processing instructions
		pi = xmlDoc.createProcessingInstruction("xml", "version=\"1.0\" standalone=\"yes\"");
		xmlDoc.appendChild(pi);

		// header
		var curDate = new Date();
		datapacket = xmlDoc.createElement('datapacket');
		datapacket.setAttribute("version", "2.100");
		datapacket.setAttribute("datapacket", "datapacket");
		datapacket.setAttribute("destination", "");
		datapacket.setAttribute("day", curDate.getDate());
		datapacket.setAttribute("month", (curDate.getMonth()+1));
		datapacket.setAttribute("year", curDate.getYear());
		datapacket.setAttribute("hour", curDate.getHours());
		datapacket.setAttribute("min", curDate.getMinutes());
		datapacket.setAttribute("sec", curDate.getSeconds());
		datapacket.setAttribute("msec", curDate.getMilliseconds());
		xmlDoc.appendChild(datapacket);

		// dataformat
		var xmlFormat = new ActiveXObject('Microsoft.XMLDOM');
		xmlFormat.async = false;
		xmlFormat.resolveExternals = false;
		xmlFormat.loadXML(this.xmlDataFormat);
		datapacket.appendChild(xmlFormat.documentElement);

		// records
		recorddata = xmlDoc.createElement("recorddata");
		recorddata.setAttribute("count", recordCount);
		var fieldCount = this.dataFormat.length;

		for (var i = 0; i<recordCount; i++) {
			rowNode = xmlDoc.createElement("row");
			for (var j = 0; j<fieldCount; j++) {
				field = xmlDoc.createElement("field");
				field.setAttribute("name", this.dataFormat[j][0]);
				field.setAttribute("value", records[i][j]);
				rowNode.appendChild(field);
			}
			recorddata.appendChild(rowNode);
		}
		datapacket.appendChild(recorddata);

		// return the entire xml
		return xmlDoc.xml;
	}

	//------------------------------------------------------------------------------
	// Print methods
	//------------------------------------------------------------------------------

	// get the inventory amount
	this.getInventory = function()
	{
		return this.activeX.GetInventoryAmount(this.login, this.password);
	}

	// printerNames
	this.getPrinterNames = function()
	{
		var names = new Array();
		this.activeX.GetPrinterNames(names);
		return names;
	}
	// printAlignmentPage
	this.printAlignmentPage = function(jobId, options)
	{
		return this.activeX.printAlignmentPage(jobId, options);
	}
	// printSample
	this.printSample = function(jobId, data, options)
	{
		return this.activeX.printSample(jobId, data, options);
	}
	// printjob
	this.printJob = function(jobId, data, options, metadata)
	{
		var printResult;

		// handle older activex controls that don't have metadata
		if (metadata == undefined)
			printResult = this.activeX.printJob(this.token, this.login, this.password, jobId, data, options);
		else
			printResult = this.activeX.printJob(this.token, this.login, this.password, jobId, data, options, metadata);

		if ((this.activeX.PrinterName != null) && (this.activeX.PrinterName != ''))
			createCookie('LastUsedPrinter', this.activeX.PrinterName);

		return printResult;
	}
	// printJobFromString
	this.printJobFromString = function(jobXml, data, options, metadata)
	{
		var printResult;

		// handle older activex controls that don't have metadata
		if (metadata == undefined)
			printResult = this.activeX.printJobFromJobString(this.token, this.login, this.password, jobXml, data, options);
		else
			printResult = this.activeX.printJobFromJobString(this.token, this.login, this.password, jobXml, data, options, metadata);

		if ((this.activeX.PrinterName != null) && (this.activeX.PrinterName != ''))
			createCookie('LastUsedPrinter', this.activeX.PrinterName);

		return printResult;
	}
	// printSetupSheet
	this.printSetupSheet = function(jobId, options)
	{
		return this.activeX.printAlignmentPage(jobId, options);
	}
	// printQCSheet
	this.printQCSheet = function(qcSheetId, options)
	{
		return this.activeX.printQCSheet(qcSheetId, options);
	}

	//------------------------------------------------------------------------------
	// Reprint methods
	//------------------------------------------------------------------------------

	// hasReprint
	this.hasReprint = function(jobId)
	{
		return this.activeX.HasReprint(this.login, jobId);
	}
	// retrieveReprintData
	this.retrieveReprintData = function(jobId)
	{
		return this.activeX.RetrieveReprintData(this.login, jobId);
	}
	// reprintJob
	this.reprintJob = function(jobId, options)
	{
		return this.activeX.ReprintJob(this.token, this.login, this.password, jobId, options);
	}
}

//------------------------------------------------------------------------------
// Helper Functions
//------------------------------------------------------------------------------
// attempts to get a new engine object, if that fails then the user will be
// redirected to the wizardCheck page
function tryGetEngine(login, password)
{
	var engine = new cfxEngine(login, password);
	if (!engine.isValid)
	{
  	// Redirect to check page
  	alert('Unable to load ActiveX control.  Redirecting you to the download page.');
  	window.open('wizardCheck.aspx?return=' + encodeURIComponent(location.href), 'checkPage', '', true);
  	return;
  }
	return engine;
}