/**
 *	Copyright 2002-2006 by Earth Resource Mapping Ltd.  All rights reserved.
 *	Image Integration Framework generated pages may only be served by organizations that have
 *	a license for the Image Integration Framework product. Image Integration Framework may only be used by
 *	Application Service Providers (ASPs) with a license for the Image Integration Framework ASP Edition product.
 */

/**
* @class Interfaces to DoL's Address search web service
* @constructor
* @base SIX.Access
*/
SIX.Access.SOAP = function (service) {
	SIX.Access.call(this, service);
	this.name = "SOAP";
	this.version = "1.0";
	this.hasMetadata = false;
	this.hasLegend = false;
	this.hasSearch = false;		// may be set later
	this.hasQuery = false;
	this.canReorder = false;
	this.nNumInvalidRequests = 0;
	this.tMapTimer = null;
	this.nTimeout = 500;
	this.sSelectedResultId = "";
	this.dSelectedResultLabelX = 0.0;
	this.dSelectedResultLabelY = 0.0;
	this.aSelectedResultLabel = new Array();	
	this.xml = new SIX.Xml();
}
SIX.Util.extend(SIX.Access.SOAP, SIX.Access);

SIX.Access.SOAP.prototype.loadMap = function (map)
{
}

SIX.Access.SOAP.prototype.loadLayers = function (map)
{
}

SIX.Access.SOAP.prototype.queryLayers = function (map) {
}

SIX.Access.SOAP.prototype.search = function ()
{	
	if (this.service.currentSearch > -1) 
	{	
		var search = this.service.searches[this.service.currentSearch];	
		search.decodeForm();
		var catalog = this.service.catalog;	
		if (catalog.maps.length)
			this.searchMap(catalog.maps[0],search);
	}
}

/**
**	PURPOSE: sends search to Arcims server
**	ACCEPTS: map object, search object
*/ 
SIX.Access.SOAP.prototype.searchMap = function (map, search, nSearchOffset)
{	
	if( !this.service.loaded || !map.loaded /*|| !this.service.isOnline */)
		return;
		
	this.service.busy(true);
	this.service.nLayersLoadState = SIX.eLayersLoadState.LOADED;
	
	if (arguments.length < 3) 
	{
		if (this.tMapTimer)
			clearTimeout(this.tMapTimer);	
		this.tMapTimer = setTimeout("" + this.myself + ".searchMap(" + map.myself + "," + search.myself + ",0)", this.nTimeout);
		return;
	}

	search.decodeForm();
	
	if (search.resultsField)
	{
		search.deleteResults();
		search.addResult(search.sLoadingResults);
	}
	
	if (nSearchOffset == 0)
		this.sSearchText = "";

	if (((search.fields.length - search.nNumHiddenFields) == 1) && (search.bSubmitOnLoad == false))
	{		
		if (nSearchOffset == 0)
		{
			for (var i=0; i<search.fields.length; i++)
			{
				if (search.fields[i].style == "string")
				{
					this.sSearchText = search.fields[i].value;
					break;
				}
			}
		}
		
		if (this.sSearchText == "") 			
		{
			if (this.tMapTimer)
				clearTimeout(this.tMapTimer);
			if (search.resultsField) 
			{
				search.deleteResults();
				search.addResult(search.sNoResults);	
			}
			return;
		}						
	}				
	
	search.nSearchOffset = nSearchOffset;
	
	while (this.xml.rootXml.hasChildNodes())
			this.xml.rootXml.removeChild(this.xml.rootXml.lastChild);

	var piXML = this.xml.rootXml.createProcessingInstruction("xml", "version='1.0'");
	this.xml.rootXml.appendChild(piXML);

	var nodeSOAPENVEnvelope = this.xml.rootXml.createElement("SOAP-ENV:Envelope");
	nodeSOAPENVEnvelope.setAttribute("xmlns:SOAP-ENV","http://schemas.xmlsoap.org/soap/envelope/");
	
	var nodeSOAPENVHeader = this.xml.rootXml.createElement("SOAP-ENV:Header");
	nodeSOAPENVEnvelope.appendChild(nodeSOAPENVHeader);		
		
	var nodeSOAPENVBody = this.xml.rootXml.createElement("SOAP-ENV:Body");
	nodeSOAPENVEnvelope.appendChild(nodeSOAPENVBody);
	    
	var nodeFindAddress = this.xml.rootXml.createElement("findAddress");
	nodeFindAddress.setAttribute("xmlns","http://ws.hraddress.lands.nsw.gov"); 	
	nodeSOAPENVBody.appendChild(nodeFindAddress);
	
	for( var i=0; i<search.fields.length; i++ ) 
	{	
		var field = search.fields[i];
		var aKeys = field.key.split(";");
		for (var j=0; j<aKeys.length; j++)
		{	
			var key = aKeys[j];
			var nodeSearchField = this.xml.rootXml.createElement(key);
			nodeFindAddress.appendChild(nodeSearchField);
			
			if (!((field.style == "number") && isNaN(field.value)))
			{
				var value = this.getFieldValue(field, key);
				var textNodeSearchFieldValue = this.xml.rootXml.createTextNode(value);
				nodeSearchField.appendChild(textNodeSearchFieldValue);	
			}
		}				
	}	
	
	var nodeMaxResults = this.xml.rootXml.createElement("maxResults");
	nodeFindAddress.appendChild(nodeMaxResults);
	
	var textNodeMaxResults = this.xml.rootXml.createTextNode(search.nSearchCount);	   
	nodeMaxResults.appendChild(textNodeMaxResults);	
	   
	this.xml.rootXml.appendChild(nodeSOAPENVEnvelope);   
	    
	var	 url  = 'mode=0;action=POST;';
		url += 'worldTLX=' + map.tlx + ';worldTLY=' + map.tly + ';worldBRX=' + map.brx + ';worldBRY=' + map.bry + ';';
		
		url += 'url=http://' + this.service.host + '/' + this.service.service + ';header=soapAction:\"\";';
		url += 'body=' + this.xml.rootXml.xml;
	
	var control = document[map.uid];
	
	var result = map.setLayerParameter(this.service.uid, url);	
}

SIX.Access.SOAP.prototype.responseMap = function (map, layerName, url, body, action, tlx, tly, brx, bry, response)
{
	var retVal = true;
	if( response == "NCS_OVERLAY_SUCCESS" ) {
		this.service.busy(false);
		return true;
	}
	
	// replace any &amps - for image web server arcXML service
	var re = new RegExp ('&amp;', 'gi') ;// replace front slash characters
	var sResponse = response.replace(re, '&') ;
	
	var control = document[map.uid];

	this.xml.loadXmlText(response);
	
	var valid = false;
	
	if (this.service.currentSearch > -1)
	{
		this.service.searchResponse(map);
		valid = true;
	}
		
	if (!valid ) 
	{
		this.service.busy(false);
		SIX.App.popupAlert(this.service.name + " (" + this.access.name + ") Error.","The map server reported an error.",sResponse);
		retVal = false;
	}
	return retVal;
}

SIX.Access.SOAP.prototype.searchAddress = function ()
{
	var bGotHouseNumber = false;//Optional
	var bGotRoadName = false;//Mandatory
	var bGotSuburbNameOrPostcode = false;
	
	if (this.service.currentSearch > -1) 
	{
		var search = this.service.searches[this.service.currentSearch];	
		search.decodeForm();
		
		for( var i=0; i<search.fields.length; i++ ) 
		{				
			switch(search.fields[i].key.toLowerCase())
			{
				case "housenum":
					if (search.fields[i].value != "")
						bGotHouseNumber = true;
					break;
				case "rdname":
					if (search.fields[i].value != "")
						bGotRoadName = true;
					break;
				case "suburb":
					if (search.fields[i].value != "")
						bGotSuburbNameOrPostcode = true;
					break;
				case "pcode":
					if (search.fields[i].value != "")
						bGotSuburbNameOrPostcode = true;
					break;
				case "suburb;pcode":
				case "pcode;suburb":
					if (search.fields[i].value != "")
						bGotSuburbNameOrPostcode = true;
					break;					
				default:
					break;
			}		
		}		
	
		var sErrorText = "";
		if (!bGotRoadName) 
			sErrorText += "Road name must be specified.\n";
		if (!bGotSuburbNameOrPostcode)
			sErrorText += "Suburb name or postcode must be specified.";
			
		if (sErrorText != "")
			alert(sErrorText);
		else
		{
			var catalog = this.service.catalog;	
			if (catalog.maps.length)
				this.searchMap(catalog.maps[0],search);
		}
	}
}

SIX.Access.SOAP.prototype.searchAddressResponse = function ()
{
	var nodeFindAddressReturn  = this.xml.rootXml.getElementsByTagName("findAddressReturn")[0];
	
	if (nodeFindAddressReturn && (this.service.currentSearch > -1)) 
	{
		var search = this.service.searches[this.service.currentSearch];
		var nodeAddresses = nodeFindAddressReturn.getElementsByTagName("addresses")[0];
		var sSearchField = "";
				
		if (search.resultsField && nodeAddresses) 
		{
			search.deleteResults();
		
			var addressNodes = nodeAddresses.getElementsByTagName("address");
			for( var i=0; i<addressNodes.length; i++ ) 
			{
				var aSearchResult = new Array();
				
				for (var j=0; j<search.resultsField.aFieldKeys.length; j++)
				{
					var nodeAddressPart = addressNodes[i].getElementsByTagName(search.resultsField.aFieldKeys[j])[0];
					var sAddressPartValue = "";
					if (nodeAddressPart && nodeAddressPart.childNodes.length)
						sAddressPartValue = nodeAddressPart.childNodes[0].nodeValue;
						
					var aFieldLookupTables = search.resultsField.aFieldLookupTables;
					if (aFieldLookupTables && aFieldLookupTables[j] && (sAddressPartValue != ""))
					{
						if (aFieldLookupTables[j]["#" + sAddressPartValue])
							sAddressPartValue = aFieldLookupTables[j]["#" + sAddressPartValue];
					}						
						
					aSearchResult[j] = sAddressPartValue;
				}
				
				search.addResult(aSearchResult,i);
			}
		
			if (addressNodes.length)
				search.sortResults();
			else
				search.addResult(search.sNoResults);	
			
			//Set focus back to first search field.
			var firstField = search.getFirstInputField();
			if (firstField) 
			{
				var elemFirstField = document.getElementById(firstField.uid);
				if (elemFirstField)
					elemFirstField.focus();	
			}	
		}
	}
}

SIX.Access.SOAP.prototype.getFieldValue = function (field, key)
{
	var value = field.value;
	switch (key)
	{
		case "pcode": 
			if (field.value.length != 4 || isNaN(parseInt(field.value)))
				value = "";		
			break;
		case "suburb": 
			if (!isNaN(parseInt(field.value)))
				value = "";	
			break;		
		default: 
			value = field.value;
			break;
	}
	return value;
}

SIX.Access.SOAP.prototype.onSelectSearchResult = function ()
{
	var catalog = this.service.catalog;
	var map = catalog.maps[0];
	var nSelectedFeature = -1;
	var nPaddingFactor = 0.11;
	
	var search = this.service.searches[this.service.currentSearch];
	var dMinDeltaX = search.dMinZoomWidth;
	var dMinDeltaY = search.dMinZoomHeight;
	
	search.decodeForm();
	if (search.resultsField) 
	{
		nSelectedFeature = parseInt(search.resultsField.value);
		if (isNaN(nSelectedFeature) || (nSelectedFeature < 0))
			return;	
		
		var nodeFindAddressReturn  = this.xml.rootXml.getElementsByTagName("findAddressReturn")[0];
		if (nodeFindAddressReturn) 
		{
			var nodeAddresses = nodeFindAddressReturn.getElementsByTagName("addresses")[0];
			
			if (nodeAddresses) 
			{
				var addressNodes = nodeAddresses.getElementsByTagName("address");	
				
				var nodePropId = addressNodes[nSelectedFeature].getElementsByTagName("propId")[0];
				this.sSelectedResultId = "";
				if (nodePropId && nodePropId.childNodes.length)
					this.sSelectedResultId = nodePropId.childNodes[0].nodeValue;
					
				var dTopLeftX = 0.0;
				var dTopLeftY = 0.0;
				var dBottomRightX = 0.0;
				var dBottomRightY = 0.0;	
				var nEPSG = 0;			
				
				var nodeBoundingBox = addressNodes[nSelectedFeature].getElementsByTagName("bBox")[0];
		
				if (nodeBoundingBox) 
				{	
					var nodeCRS = nodeBoundingBox.getElementsByTagName("crs")[0]; 
					if (nodeCRS && nodeCRS.childNodes.length)
						nEPSG = parseInt(nodeCRS.childNodes[0].nodeValue);
					
					var nodeMinX = nodeBoundingBox.getElementsByTagName("minX")[0];
					var nodeMinY = nodeBoundingBox.getElementsByTagName("minY")[0];
					var nodeMaxX = nodeBoundingBox.getElementsByTagName("maxX")[0];
					var nodeMaxY = nodeBoundingBox.getElementsByTagName("maxY")[0];		

					if (nodeMinX && nodeMinX.childNodes.length)
						dTopLeftX = parseFloat(nodeMinX.childNodes[0].nodeValue);
					if (nodeMinY && nodeMinY.childNodes.length)
						dBottomRightY = parseFloat(nodeMinY.childNodes[0].nodeValue);
					if (nodeMaxX && nodeMaxX.childNodes.length)
						dBottomRightX = parseFloat(nodeMaxX.childNodes[0].nodeValue);
					if (nodeMaxY && nodeMaxY.childNodes.length)
						dTopLeftY = parseFloat(nodeMaxY.childNodes[0].nodeValue);			
						
					var dCenterY = dBottomRightY + (dTopLeftY - dBottomRightY)/2;
					var dCenterX = dTopLeftX + (dBottomRightX - dTopLeftX)/2;

					var dLocalTopLeftX = dTopLeftX;
					var dLocalTopLeftY = dTopLeftY;
					var dLocalBottomRightX = dBottomRightX;
					var dLocalBottomRightY = dBottomRightY;	
					var dTopLeftXMinDelta = dCenterX - dMinDeltaX/2;
					var dTopLeftYMinDelta = dCenterY + dMinDeltaY/2;
					var dBottomRightXMinDelta = dCenterX + dMinDeltaX/2;
					var dBottomRightYMinDelta = dCenterY - dMinDeltaY/2;						
					var map = catalog.maps[0];		
					var sLocalDatum = map.datum();	
					var sLocalProjection = map.projection();
					
					if (sLocalProjection.toLowerCase() != "geodetic") 
					{
						var aTopLeftCoordinate = map.getENPoint(dTopLeftX, dTopLeftY, sLocalDatum, sLocalProjection);
						var aBottomRightCoordinate = map.getENPoint(dBottomRightX, dBottomRightY, sLocalDatum, sLocalProjection);
						
						dLocalTopLeftX = parseFloat(aTopLeftCoordinate[0]);
						dLocalTopLeftY = parseFloat(aTopLeftCoordinate[1]);
						dLocalBottomRightX = parseFloat(aBottomRightCoordinate[0]);
						dLocalBottomRightY = parseFloat(aBottomRightCoordinate[1]);		
						
						//Calculate dMinDeltaY in northings.
						var aTopLeftMinDelta = map.getENPoint(dTopLeftXMinDelta, dTopLeftYMinDelta, sLocalDatum, sLocalProjection);
						var aBottomRightMinDelta = map.getENPoint(dBottomRightXMinDelta, dBottomRightYMinDelta, sLocalDatum, sLocalProjection);
						
						dTopLeftXMinDelta = parseFloat(aTopLeftMinDelta[0]);
						dTopLeftYMinDelta = parseFloat(aTopLeftMinDelta[1]);
						dBottomRightXMinDelta = parseFloat(aBottomRightMinDelta[0]);
						dBottomRightYMinDelta = parseFloat(aBottomRightMinDelta[1]);	
						dMinDeltaX = dBottomRightXMinDelta - dTopLeftXMinDelta;
						dMinDeltaY = dTopLeftYMinDelta - dBottomRightYMinDelta;											
					}	
						
					var nDeltaX = dLocalBottomRightX - dLocalTopLeftX;
					var nDeltaY = dLocalTopLeftY - dLocalBottomRightY;									
					var nPaddingX = nPaddingFactor * nDeltaX;
					var nPaddingY = nPaddingFactor * nDeltaY;
					var nPaddedDeltaX = 2 * nPaddingX + nDeltaX;								
					var nPaddedDeltaY = 2 * nPaddingY + nDeltaY;
					
					if (nPaddedDeltaX < dMinDeltaX)
					{ 
						dLocalTopLeftX = dTopLeftXMinDelta;
						dLocalBottomRightX = dBottomRightXMinDelta;	
					}															
					if (nPaddedDeltaY < dMinDeltaY)
					{ 
						dLocalTopLeftY = dTopLeftYMinDelta;
						dLocalBottomRightY = dBottomRightYMinDelta;	
					}
					
					var dTopLeftXPadded = dLocalTopLeftX - nPaddingX;
					var dTopLeftYPadded = dLocalTopLeftY + nPaddingY;
					var dBottomRightXPadded = dLocalBottomRightX + nPaddingX;
					var dBottomRightYPadded = dLocalBottomRightY - nPaddingY;

					var dPaddedWidth = dBottomRightXPadded - dTopLeftXPadded;
					var dPaddedHeight = dTopLeftYPadded - dBottomRightYPadded;				

					var dZoomAspectRatio = dPaddedWidth/dPaddedHeight;
					var dViewAspectRatio = (map.brx - map.tlx)/(map.tly - map.bry);

					if (dViewAspectRatio > dZoomAspectRatio)
					{
						var dTopLeftXZoom = dTopLeftXPadded - 0.5 * dPaddedWidth * (dViewAspectRatio / dZoomAspectRatio - 1);
						var dTopLeftYZoom = dTopLeftYPadded;
						var dBottomRightXZoom = dBottomRightXPadded - 0.5 * dPaddedWidth * (dViewAspectRatio / dZoomAspectRatio - 1);
						var dBottomRightYZoom = dBottomRightYPadded;					
					}
					else
					{
						var dTopLeftXZoom = dTopLeftXPadded
						var dTopLeftYZoom = dTopLeftYPadded + 0.5 * dPaddedHeight * (dZoomAspectRatio / dViewAspectRatio - 1);
						var dBottomRightXZoom = dBottomRightXPadded;
						var dBottomRightYZoom = dBottomRightYPadded - 0.5 * dPaddedHeight * (dZoomAspectRatio / dViewAspectRatio - 1);							
					}

                    var topMap = map.getTopMap();
                    var control = document[topMap.uid];
					control.SetExtents(dTopLeftXZoom, 
								dTopLeftYZoom, 
								dBottomRightXZoom,
								dBottomRightYZoom);							
				}	
			}
		}
	}
}