// sjcObjects.js
// Copyright (C) 2005 San Joaquin County Community Development Geographic Information Systems, ALL RIGHTS RESERVED
// initial creation: 01/14/2004 David Bollinger
//


//====================
com = new function() {
//====================
	//-----------
	// properties
	//-----------
	this.bOkToSend = true;
	this.sXMLHeader = '<?xml version="1.0" encoding="UTF-8" ?>';
	this.fnReceive = null;
	//--------
	// methods
	//--------
	this.getPostForm = function() {
  	if (log.enabled) log.trace('com.getPostForm');
  	return parent.PostFrame.document.forms[0];
	}
	this.hideSplashes = function() {
		if (log.enabled) log.trace('com.hideSplashes');
  	hideRetrieveMap();
  	hideRetrieveData();
	}
	this.send = function(sURL,sXML,fnReceive) {
		if (log.enabled) {
			log.trace('com.send');
			log.dump('url: ' + sURL + '\nxml: ' + sXML);
		}
		var frm = this.getPostForm();
  	if (frm) {
			if (this.bOkToSend) {
				this.bOkToSend = false;
				frm.action = sURL + "&ClientVersion=4.0&Form=True&Encode=False";
				frm.ArcXMLRequest.value = this.sXMLHeader + sXML;
				frm.RedirectURL.value = "";
				frm.FormCharset.value = "ISO-8859-1";
				frm.BgColor.value = "#000000";
				frm.JavaScriptFunction.value = "parent.MapFrame.com.receive";
				this.fnReceive = fnReceive;
				if (!this.fnReceive)
					log.mark('ERROR: fnReceive is null');
				frm.submit();
			} else {
				alert('Still awaiting response from last map request, please wait, then try again.');
				this.hideSplashes();
			}
		} else {
			alert('Unable to communicate with server.  Try reloading this page.');
			this.hideSplashes();
		}
	}
	this.receive = function(sXML) {
		if (log.enabled) {
			log.trace('com.receive');
			log.dump('xml: ' + sXML.replace(/>/g, '>\n'));
		}
		this.bOkToSend = true;
  	var sError = getXMLErrorMessage(sXML);
		if (sError != '') {
			alert('ERROR: ' + sError);
		} else {
			if (this.fnReceive) {
				this.fnReceive(sXML);
			} else {
				//	alert('Internal Error:  No receiving function has been set, please contact webmaster.');
				// this error can occur if viewer is refreshed with prior content in the post form, ignore for now
			}
		}
	}
	this.generatePostFrame = function(win) {
		if (!win) return;
		var doc = win.document;
		if (!doc) return;
		doc.open();
		doc.writeln('<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">');
		doc.writeln('<HTML>');
		doc.writeln('<HEAD>');
		doc.writeln('	<TITLE>Default Form</TITLE>');
		doc.writeln('	<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">');
		doc.writeln('		function passXML() { }');
		doc.writeln('	</SCRIPT>');
		doc.writeln('</HEAD>');
		doc.writeln('<BODY BGCOLOR="White" onload="passXML()">');
		doc.writeln('	<P>');
		doc.writeln('		<FORM ACTION="" METHOD="POST" name="theForm">');
		doc.writeln('		<INPUT TYPE="Hidden" NAME="ArcXMLRequest" SIZE="40">');
		doc.writeln('		<INPUT TYPE="Hidden" NAME="JavaScriptFunction" VALUE="parent.MapFrame.processXML">');
		doc.writeln('		<INPUT TYPE="Hidden" NAME="RedirectURL" VALUE="">');
		doc.writeln('		<INPUT TYPE="Hidden" NAME="BgColor" VALUE="#000000">');
		doc.writeln('		<INPUT TYPE="Hidden" NAME="FormCharset" VALUE="UTF-8">');
		doc.writeln('	</FORM>');
		doc.writeln('</BODY>');
		doc.writeln('</HTML>');
		doc.close();
	}
}

//====================
log = new function() {
//====================
	//-----------
	// properties
	//-----------
	this.enabled = false;
	this.win = null;
	this.doc = null;
	//--------
	// methods
	//--------
	this.enable = function() {
		this.win = window.open('','LOG','width=400,height=300,resizable=yes,scrollbars=yes');
		if (!this.win) return; // popup probably blocked
		this.doc = this.win.document;
		if (!this.doc) return; // unexpected error
		this.doc.open();
		this.doc.write('<HTML><HEAD><TITLE>LOG</TITLE><STYLE TYPE="text/css">body{font-name:Courier New,Times New Roman,Courier; font-size:8pt;} pre{margin:0;}</STYLE></HEAD><BODY>');
		this.enabled = true;
	}
	this.disable = function() {
		this.enabled = false;
		if (this.doc)	this.doc.close();
		this.doc = null;
		if (this.win) this.win.close();
		this.win = null;
	}
	this.alert = function(msg) {
		if (this.enabled) {
			msg = msg || '';
			window.alert(msg);
		}
	}
	this.dump = function(msg) {
		if (this.enabled) {
			msg = msg || '';
			msg = msg.replace(/&/g, '&amp;');
			msg = msg.replace(/'/g, '&apos;');
			msg = msg.replace(/>/g, '&gt;');
			msg = msg.replace(/</g, '&lt;');
			msg = msg.replace(/"/g, '&quot;');
			this.doc.write('DUMP: <PRE>' + msg + '</PRE>');
			this.line();
		}
	}
	this.line = function() {
		if (this.enabled) {
			this.doc.write('<HR size=1>');
		}
	}
	this.mark = function(msg) {
		if (this.enabled) {
			msg = msg || '';
			this.doc.write('MARK: ' + msg + '<BR><HR size=3>');
		}
	}
	this.trace = function(msg) {
		if (this.enabled) {
			msg = msg || '';
			msg = msg.replace(/\n/g, '<br>');
			this.doc.write('TRACE: ' + msg + '<BR>');
			this.line();
		}
	}
	this.extent = function() {
		var msg = 't.doZoomEnvelope( ' + parseInt(extent.minx) + ',' + parseInt(extent.miny) + ',' + parseInt(extent.maxx) + ',' + parseInt(extent.maxy) + ' );<BR>';
		this.doc.write(msg);
		this.line();
	}
}

//======================================
function ENVELOPE(minx,miny,maxx,maxy) {
//======================================
	this.calc = function() {
		this.width = Math.abs(this.maxx - this.minx);
		this.height = Math.abs(this.maxy - this.miny);
	}
	this.set = function(minx,miny,maxx,maxy) {
		this.minx = minx || 0;
		this.miny = miny || 0;
		this.maxx = maxx || 0;
		this.maxy = maxy || 0;
		this.calc();
	}
	this.setfrom = function(env) {
		this.minx = env.minx;
		this.miny = env.miny;
		this.maxx = env.maxx;
		this.maxy = env.maxy;
		this.calc();
	}
	this.inset = function(dx,dy) {
		this.minx += dx;
		this.maxx -= dx;
		this.miny += dy;
		this.maxy -= dy;
	}
	this.move = function(dx,dy) {
		this.minx += dx;
		this.maxx += dx;
		this.miny += dy;
		this.maxy += dy;
	}
	this.scale = function(factor) {
		var cx = (this.minx + this.maxx) / 2.0;
		var cy = (this.miny + this.maxy) / 2.0;
		this.width *= factor;
		this.height *= factor;
		this.minx = cx - (this.width / 2.0);
		this.maxx = cx + (this.width / 2.0);
		this.miny = cy - (this.height / 2.0);
		this.maxy = cy + (this.height / 2.0);
	}
	this.loadXML = function(sXML) {
		this.minx = s2n(getTagAttValue(sXML, 'ENVELOPE', 'minx', '0'));
		this.miny = s2n(getTagAttValue(sXML, 'ENVELOPE', 'miny', '0'));
		this.maxx = s2n(getTagAttValue(sXML, 'ENVELOPE', 'maxx', '0'));
		this.maxy = s2n(getTagAttValue(sXML, 'ENVELOPE', 'maxy', '0'));
		this.calc();
	}
	this.asXML = function() {
		var sXML = '<ENVELOPE ' +
			' minx="' + n2s(this.minx) + '"' +
			' miny="' + n2s(this.miny) + '"' +
			' maxx="' + n2s(this.maxx) + '"' +
			' maxy="' + n2s(this.maxy) + '"' +
			' />';
		return sXML;
	}
	this.set(minx,miny,maxx,maxy);
	return this;
}

extent = new ENVELOPE();
lastextent = new ENVELOPE();
fullextent = new ENVELOPE();
ovextent = new ENVELOPE();

//====================
map = new function() {
//====================
	//-----------
	// properties
	//-----------
	//--------
	// methods
	//--------
	this.request = function() {
		log.trace('map.request');
		showRetrieveMap();
		var sXML = this.asXML();
		com.send(imsURL, sXML, map.receive);
	}
	this.receive = function(sXML) {
		log.trace('map.receive');
		var sURL = getTagAttValue(sXML, 'OUTPUT', 'url', '');
		if (sURL != "") {
			extent.loadXML(sXML);
			calcScaleFactor();
			document.theImage.src = sURL;
		}
		legend.receive(sXML);
		if (ovmap.visible) {
			putExtentOnOVMap();
		}
		hideRetrieveMap();
	}
	this.asXML = function() {
		calcScaleFactor();
		var sXML = '<ARCXML version="1.1">\n<REQUEST>\n<GET_IMAGE>\n<PROPERTIES>\n';
		sXML += extent.asXML();
		sXML +=	'<IMAGESIZE height="' + iHeight + '" width="' + iWidth + '" />\n';
		sXML += layers.asXML();
		sXML += legend.asXML();
		sXML += '</PROPERTIES>\n';
		sXML += select.asXML();
		sXML += northarrow.asXML();
		sXML += scalebar.asXML();
		sXML += '</GET_IMAGE>\n</REQUEST>\n</ARCXML>';
		return sXML
	}
}

//=======================
layers = new function() {
//=======================
	//-----------
	// properties
	//-----------
	this.active = null;
	this.items = new Array();
	//--------
	// methods
	//--------
	this.clear = function() {
		this.items.length = 0;
		this.length = 0;
	}
	this.add = function(itm) {
		this.items[this.items.length] = itm;
	}
	this.get = function(n) {
		return this.items[n];
	}
	this.reverse = function() {
		this.items.reverse();
		for (var i=0, n=this.items.length; i<n; i++) {
			this.items[i].index = i;
			this[i] = this.items[i];
		}
		this.length = this.items.length;
		this.count = this.length;
	}
	this.asXML = function() {
		var sXML = '<LAYERLIST >\n';
		for (var i=0, n=this.items.length; i<n; i++) {
			sXML += '<LAYERDEF id="' + this.items[i].id + '" visible="' + ( (this.items[i].visible==1) ? 'true' : 'false') + '" />\n';
		}
		sXML += '</LAYERLIST>\n';
		return sXML;
	}
	this.parse = function(sXML) {
		this.clear();
		var lipos = 0;
		var sLayerInfo = getTagValue(sXML, lipos, '<LAYERINFO', '</LAYERINFO');
		while (sLayerInfo != '') {
			var info = new Object();
			info.name = getAttValue(sLayerInfo,'name');
			info.isfeature = (getAttValue(sLayerInfo,'type') == 'featureclass');
			info.visible = (getAttValue(sLayerInfo,'visible') == 'true') ? 1 : 0;
			info.id = getAttValue(sLayerInfo,'id',info.name);
			info.minscale = parseFloat(getAttValue(sLayerInfo,'minscale','0'));
			info.maxscale = parseFloat(getAttValue(sLayerInfo,'maxclass', '1.7976931348623157E308'));
			info.type = getTagAttValue(sLayerInfo,'FCLASS','type','image');
			info.idfield = (info.isfeature) ? '#ID#' : '';
			info.shapefield = (info.isfeature) ? '#SHAPE#' : '';
			this.add(info);
			lipos += sLayerInfo.length;
			sLayerInfo = getTagValue(sXML, lipos,'<LAYERINFO','</LAYERINFO');
		}
		this.reverse();
	}
	this.getIndexByName = function(name) {
		for (var i=0, n=this.items.length; i<n; i++)
			if (this.items[i].name == name)
				return i;
		return -1;
	}
	this.setActive = function(idx) {
		this.active = this.items[idx];
		select.clear();
	}
	this.setActiveByName = function(name) {
		var idx = this.getIndexByName(name);
		if (idx >= 0) this.setActive(idx);
	}
}

//=======================
select = new function() {
//=======================
	//-----------
	// properties
	//-----------
  this.count = 0;
	this.whereclause = '';
	//--------
	// methods
	//--------
	this.clear = function() {
		this.count = 0;
		this.whereclause = '';
	}
	this.asXML = function() {
		var sXML = '';
		if (this.whereclause == '') return sXML;
		if (layers.active.visible==0) return sXML;
		if ((mapScaleFactor<layers.active.minscale) || (mapScaleFactor>layers.active.maxscale)) return sXML;
		sXML +='<LAYER type="featureclass" name="Selected Feature" visible="true">\n';
		sXML +='<DATASET fromlayer="' + layers.active.id + '" />\n';
		sXML +='<QUERY where="' + this.whereclause + '" />\n';
		sXML +='<SIMPLERENDERER>\n';
		switch( layers.active.type ) {
			case 'point'  : sXML +='<SIMPLEMARKERSYMBOL color="255,0,0" type="Circle" width="10" />\n'; break;
			case 'line'   : sXML +='<SIMPLELINESYMBOL type="SOLID" color="255,0,0" width="3" />\n'; break;
			case 'polygon':	sXML +='<SIMPLEPOLYGONSYMBOL fillcolor="255,0,0" filltype="diagcross" filltransparency="1" boundarycolor="255,0,0" boundarywidth="2" />\n'; break;
		}
		sXML +='</SIMPLERENDERER>\n';
		sXML +='</LAYER>\n';
		return sXML;
	}
}

//=======================
legend = new function() {
//=======================
	//-----------
	// properties
	//-----------
	this.visible = false;
	this.width = 170;
	this.height = 300;
	this.imageurl = '';
	this.nomapflag = false;
	this.bkgndcolor = '216,224,216';
	//--------
	// methods
	//--------
	this.setSize = function(w,h) {
		log.trace('legend.setSize');
		this.width = w;
		this.height = h;
	}
	// there is no legend.request, use map.request instead
	// legend.receive is called by map.receive
	this.receive = function(sXML) {
		log.trace('legend.receive');
		this.imageurl = getTagAttValue(sXML, 'LEGEND', 'url', this.imageurl);
		if (this.visible) {
			this.display();
		}
	}
	this.whitebkgnd = function() {
		this.bkgndcolor = '255,255,255';
	}
	this.colorbkgnd = function() {
		this.bkgndcolor = '216,224,216';
	}
	this.asXML = function() {
		log.trace('legend.asXML');
		var sXML = '<LEGEND title="Legend" font="Arial" width="' + this.width + '" height="' + this.height + '" ' +
		   'autoextend="true" backgroundcolor="' + this.bkgndcolor + '" />\n';
		if (this.nomapflag) {
			sXML += '<DRAW map="false" />\n';
			this.nomapflag = false;
		}
		return sXML;
	}
	this.display = function() {
		log.trace('legend.display');
		parent.TabBarFrame.pressTab('legend');
	}
}

//======================
ovmap = new function() {
//======================
	this.visible = false;
	this.asXML = function(bDrawExtentBox) {
		var sXML =
			'<ARCXML version="1.1">\n' +
			' <REQUEST>\n' +
			'  <GET_IMAGE>\n' +
			'   <PROPERTIES>\n';
		if (ovextent.width > 0)
			sXML += ovextent.asXML();
		sXML +=
			'    <IMAGESIZE height="' + i2Height + '" width="' + i2Width + '" />\n' +
			'   </PROPERTIES>\n';
		if (bDrawExtentBox) {
			var eLeft = extent.minx;
			var eBottom = extent.miny;
			var eRight = extent.maxx;
			var eTop = extent.maxy;
			sXML +=
				'<LAYER type="acetate" name="ACETATE">\n' +
				' <OBJECT units="database">\n'+
				'  <LINE coords="' + n2s(eLeft) + ' ' + n2s(eBottom) + ';' + n2s(eLeft) + ' ' + n2s(eTop) + ';' + n2s(eRight) + ' ' + n2s(eTop) + ';' + n2s(eRight) + ' ' + n2s(eBottom) + ';' + n2s(eLeft) + ' ' + n2s(eBottom) + '">\n' +
				'   <SIMPLELINESYMBOL type="solid" color="255,0,0" width="3" />\n' +
				'  </LINE>\n' +
				' </OBJECT>\n' +
				'</LAYER>\n';
		}
		sXML +=
			'  </GET_IMAGE>\n' +
			' </REQUEST>\n' +
			'</ARCXML>';
		return sXML;
	}
}

//===========================
northarrow = new function() {
//===========================
	this.asXML = function() {
		var sXML =
			'<LAYER type="acetate" name="theNorthArrow">\n' +
			' <OBJECT units="pixel">\n' +
			'  <NORTHARROW type="4" size="12" coords="15 30" shadow="32,32,32" angle="0" antialiasing="True" overlap="False" />\n' +
			' </OBJECT>\n' +
			'</LAYER>\n';
		return sXML;
	}
}

//=========================
scalebar = new function() {
//=========================
	this.asXML = function() {
		var scaleunits = (mapScaleFactor < 10) ? 'feet' : 'miles';
		var sXML =
			'<LAYER type="acetate" name="theScaleBar">\n' +
			' <OBJECT units="pixel">\n' +
			'  <SCALEBAR screenlength="96" coords="5 3" font="Arial" fontsize="10" fontcolor="0,0,0" fontstyle="Regular" ' +
			'   barcolor="0,0,0" barwidth="7" antialiasing="True" precision="2" overlap="False" ' +
			'   mapunits="feet" scaleunits="' + scaleunits + '" />\n' +
			' </OBJECT>\n' +
			'</LAYER>\n';	
		return sXML;
	}
}


