/*
	CSPBroker.js
	Copyright (c) 2000 InterSystems Corp. ALL RIGHTS RESERVED.
*/


function cspInsertCode(object,event,code)
{
	// create a new handler function
	// if there was an old one, invoke it from the new one.

	if (object['old' + event] != null) {
		// handler already added
		return;
	}

	var old = '';

	if (object[event] != null) {
		object['old' + event] = object[event];
		old = 'return old' + event + '();'
	}

	object[event] = new Function(code + old);
}

function cspUnloadPopup()
{
	if (self.cspPopupWindow != null) {
		self.cspPopupWindow.close();
	}

	return true;
}

function cspGetSearchValues(form)
{
	var query = '';
	for (var i = 1; i < arguments.length; i++) {
		query = query + ((i > 1) ? '&' : '') + 'PARM=';
		if (form[arguments[i]] != null) {
			query = query + cspEncodeUTF8(form[arguments[i]].value);
		}
	}
	return query;
}

function cspFindCookie(name)
{
	var one;
	var all = document.cookie.split('; ');
	for (var i = 0; i < all.length; i++) {
		one = all[i].split('=');
		if (name == one[0]) {
			return unescape(one[1]);
		}
	}
	return null;
}

function cspOpenSession(target,url,name,features,replace)
{
	var win = null;
	var cookie = cspFindCookie('CSPSESSIONID');

	// get rid of session cookie to force new window to have a new session
	self.document.cookie = 'CSPSESSIONID=' + escape('garbage') + '; expires=Fri, 02-Jan-1970 00:00:00 GMT';

	if (cspOpenSession.arguments.length == 2) {
		win = target.open(url);
	}
	else if (cspOpenSession.arguments.length == 3) {
		win = target.open(url,name);
	}
	else if (cspOpenSession.arguments.length == 4) {
		win = target.open(url,name,features);
	}
	else if (cspOpenSession.arguments.length == 5) {
		win = target.open(url,name,features,replace);
	}

	// restore value of cookie
	self.document.cookie = 'CSPSESSIONID=' + escape(cookie);

	return win;
}

function cspFindBroker()
{
	var broker;
	var err;

	var ver = navigator.appVersion.toLowerCase();
	if ((-1 != ver.indexOf("msie")) && (-1 != ver.indexOf("mac"))) {
		err='The CSP Broker is not supported on Mac versions of Internet Explorer';
		if (typeof cspRunServerMethodError == 'function')
			cspRunServerMethodError(err);
		alert(err);
		return null;
	}

	if (navigator.javaEnabled() == false) {
		err='Must have Java enabled to use hyperevent call';
		if (typeof cspRunServerMethodError == 'function')
			cspRunServerMethodError(err);
		alert(err);
		return null;
	}

	// This works on IE, Netscape
	broker = self.document.CacheCSPBroker;
	if (null != broker) {
		return broker;
	}

	// This works for Opera
	broker = document.applets["CacheCSPBroker"];
	if (null != broker) {
		return broker;
	}

	// Could not find a broker

	return null;
}

function cspFindFrame()
{
	var iframe;
	var browserVer;
	var browserName = navigator.appName.toLowerCase();
    var appVer = navigator.appVersion.toLowerCase();

    // Note: On IE, start of appVersion return 3 or 4
    // which supposedly is the version of Netscape it is compatible with.
    // So we look for the real version further on in the string
    if (browserName == "microsoft internet explorer") {
		var iePos  = appVer.indexOf('msie');
		browserVer = parseInt(appVer.substring(iePos+5,appVer.indexOf(';',iePos)));
    } else {
		browserVer = parseInt(appVer);
	}

	if (browserName == "netscape") {
		if (browserVer >= 5) {
			iframe = window.document.getElementById('cspBrokerFrame');
		} else {
			iframe = window.document.cspBrokerLayer;
		}
	} else if (browserName == "microsoft internet explorer") {
		// For IE use the SCRIPT tag which appears in the object model except on the mac
		if (-1 != appVer.indexOf("mac")) {
			if (browserVer > 5) {
				iframe = window.document.getElementById('cspBrokerFrame');
			} else {
				iframe = window.document.all.cspBrokerFrame;
			}
		} else if (browserVer > 5) {
			iframe = window.document.getElementById('cspBrokerScript');
		} else {
			iframe = window.document.all.cspBrokerScript;
		}
	} else {
		iframe = window.document.getElementById('cspBrokerFrame');
	}

	return iframe;
}

function cspCallServerMethod(method)
{
	var arg;
	var err;
	var iframe = cspFindFrame();
	if (iframe == null) {
		err='Unable to locate cspBrokerFrame/cspBrokerScript/cspBrokerLayer tag.\nCould be unsupported browser version.\nUpgrade to a newer version.';
		if (typeof cspRunServerMethodError == 'function')
			cspRunServerMethodError(err);
		alert(err);
		return;
	}
	var cookie = cspFindCookie('CSPSESSIONID');

	// Setup the IFrame with the same session cookie
	if (cookie != null ) {
		iframe.cookie = 'CSPSESSIONID=' + escape(cookie);
	}

	var url = "%25CSP.Broker.cls";
	var n;
	url = url + "?WARGC=" + (cspCallServerMethod.arguments.length - 1);
	if (navigator.appName == "Microsoft Internet Explorer") {
		if (-1 != navigator.appVersion.indexOf("Mac")) {
			url = url + "&WJSEVENT=" + method;
		} else {
			url = url + "&WSCRIPT=" + method;
		}
	} else {
		url = url + "&WJSEVENT=" + method;
	}
	for (var i = 1; i < cspCallServerMethod.arguments.length; i++) {
		arg = cspCallServerMethod.arguments[i];
		if (typeof arg != "object") {
			// Convert boolean to Cache value before sending
			if (typeof arg == "boolean") arg = cspMakeBoolean(arg);

			if ((arg != null) && (arg.length > 32000)) {
				alert( 'Argument ' + i + ' too long.');
			}
			url = url + "&WARG_" + i + "=" + cspEncodeUTF8(arg);
		} else if (arg != null) {
			n = 0;
			for (var el in arg) {
				url = url + "&W" + i + "=" + cspEncodeUTF8(arg[el]);
				n = n + 1;
			}
			url = url + "&WLIST" + i + "=" + n;
		}
	}
	iframe.src = url;
}

function cspRunServerMethod(method)
{
	return cspIntRunServerMethod(method,cspRunServerMethod.arguments);
}

function cspIntRunServerMethod(method, args)
{
	var arg;
	var obj = cspFindBroker();
	if (null == obj) {
		err='Unable to locate CacheCSPBroker applet!'
		// Allow caller to override our error handling
		if (typeof cspRunServerMethodError == 'function')
			return cspRunServerMethodError(err);
		alert(err);
		return null;
	}

	var cookie = cspFindCookie('CSPSESSIONID');
	// If Mozilla for Mac, then indicate to applet that cookie
	// must be explicitly added to work around bug.
	if (cookie != null) {
		if (-1 != navigator.appVersion.indexOf("Macintosh")) {
			cookie = '+' + cookie;
		}
	}
	obj.startEvent(cookie, method);
	for (var i = 1; i < args.length; i++) {
		arg = args[i];
		if (typeof arg != "object") {
			// Convert boolean to Cache value before sending
			if (typeof arg == "boolean") arg = cspMakeBoolean(arg);

			// Force arg to string to work around IE problem
			// with passing empty form text field. There is a problem with Sun JVM 1.2
			// when you pass '' it takes this as null. So to hack around this bug we
			// call the addNullStringParam method rather than addParam!
			if ((typeof arg == "string") && (arg == '')) {
				obj.addNullStringParam();
			} else {
				if ((arg != null) && (arg.length > 32000)) {
					alert( 'Argument ' + i + ' too long.');
				}
				obj.addParam(arg);
			}
		} else {
			// If array, then create placeholder and add each element
			obj.addVector();
			for (var el in arg) {
				obj.addElement(arg[el]);
			}
		}
	}

	var r = obj.doEvent();
	var js = new String(obj.getJS());
	var err = new String(obj.getBrokerError());

	// Allow caller to override our error handling
	if ((err.length > 0) && (typeof cspRunServerMethodError == 'function')) {
		return cspRunServerMethodError(err)
	}

	if (err.length > 0) {
		js = 'alert(\'An error occurred while processing an event\\n\\n' + err + '\');';
	}
	if (js.length > 0) {
		var bidding = new Function('CSPPage', js);
		bidding(self);
	}

	// In Java plug-in 1.4.1, Java method may return value of type object rather than string.
	// Workaround this problem by forcing to string
	if (typeof r == "object") r = r + "";

	return r;
}

// Convert JavaScript boolean value to Cache %Boolean (1 or 0)
// in order for #server and #call %Boolean arguments to have a consistent value.
function cspMakeBoolean(boolarg)
{
	// Comment "return boolarg ? 1 : 0;" and uncomment "return boolarg;"
	//   to return to previous functionality for compatibility.

	// The next line converts true/false to 1/0
	return boolarg ? 1 : 0;

	// The next line does no conversion and is the previous default -- initially commented.
	//return boolarg
}

// utilities used by bound forms

// test if the specified field within a form is empty
function cspIsFieldEmpty(form,field)
{
	var element=self.document[form][field];
	var val;

	if ((element.type == 'select-one') || (element.type == 'select-multiple')) {
		val = cspGetSelectList(element);
		return (val.length == 0)
	}


	val = element.value;

	if ((val == null) || (val == '')) {
		return true;
	}

	// strip white space and test
	for (var i=0; val.length > i; i++) {
		var c = val.charAt(i);
		if ((c != ' ') && (c != '\n') && (c != '\t')) {
			return false;
		}
	}

	return true;
}

// trim the trailing spaces from a string
function cspTrim(string)
{
	for (var i = string.length - 1; i >= 0; i--) {
		if (string.charAt(i) != ' ') {
			return string.substr(0, i + 1);
		}
	}

	return '';
}

// trim the trailing spaces from a string
function cspString(string)
{
	return (string.length > 0) ? string : '';
}

// return the current value of select control 'select'
function cspGetSelectValue(select)
{
	var opt;
	var values;

	if (select == null) {
		return null;
	}

	if (select.type == 'select-one') {
		values = (select.selectedIndex < 0) ? '' : select.options[select.selectedIndex].value;
	} else if (select.type == 'select-multiple') {
		for (var i=0; i < select.options.length; i++) {
			opt = select.options[i];
			if (opt.selected) {
				values = opt.value;
			}
		}
	}

	return values;
}

// return the current list of selected values of select control 'select'
function cspGetSelectList(select)
{
	var opt;
	var index;
	var values = new Array();

	if (select == null) {
		return null;
	}

	if (select.type == 'select-one') {
		if (select.selectedIndex >= 0) {
			values[0] = select.options[select.selectedIndex].value;
		}
	} else if (select.type == 'select-multiple') {
		index = 0;
		for (var i=0; i < select.options.length; i++) {
			opt = select.options[i];
			if (opt.selected) {
				values[index] = opt.value;
				index = index + 1;
			}
		}
	}

	return values;
}

// set the selected value of select control 'select'
function cspSetSelectValue(select,val)
{
	var selected = false;

	if (select == null) {
		return;
	}

	for (var i = 0; select.options.length > i; i++) {
		if (select.options[i].value == val) {
			select.selectedIndex = i;
			selected = true;
		}
	}

	if (!selected) {
		select.selectedIndex = -1;
	}
}

// set the list of selected values of multiple select control 'select'
function cspSetSelectList(select,valList)
{
	if (select == null) {
		return;
	}

	select.selectedIndex = -1;  // clear all
	for (var i = 0; i < select.options.length; i++) {
		for (var j = 0; j < valList.length; j++) {
			if (select.options[i].value == valList[j]) {
				select.options[i].selected = true;
				break;
			}
		}
	}
}

// return the current value of radio control 'radio'
function cspGetRadioValue(radio)
{
	if (radio == null) {
		return null;
	}

	for (var i = 0; radio.length > i; i++) {
		if (radio[i].checked == 1) {
			return radio[i].value;
		}
	}

	return '';
}

// return the current list of checked values of multiple checkbox
function cspGetCheckList(checks)
{
	var index;
	var values = new Array();

	if (checks == null) {
		return null;
	}

	index = 0;
	for (var i = 0; i < checks.length; i++) {
		if (checks[i].checked) {
			values[index] = checks[i].value;
			index = index + 1;
		}
	}

	return values;
}

// set the list of selected values of multiple checkboxes
function cspSetCheckList(checks,valList)
{
	if (checks == null) {
		return;
	}

	for (var i = 0; i < checks.length; i++) {
		checks[i].checked=false;
		for (var j = 0; j < valList.length; j++) {
			if (checks[i].value == valList[j]) {
				checks[i].checked = true;
				break;
			}
		}
	}
}

// Escape the '+' character as well as those escaped by Javascript escape.
// This matches up unescaping that is done by CSP.
function cspEscape(str)
{
	return escape(str).replace('+','%2B');
}

var cspHexChars = "0123456789ABCDEF";

function cspEncodeChar(ch) {
	return '%' + cspHexChars.charAt(ch >> 4) + cspHexChars.charAt(ch & 0x0F);
}

function cspEncodeUTF8(s) {
	var sbuf = '';
	var len;
	var i;
	var ch;

	if (s==null) {
		return "";
	}

	s=s+""
	len = s.length;

	for (i = 0; i < len; i++) {
		ch = s.charCodeAt(i);
		if ( (65 <= ch && ch <= 90) || 		// 'A'..'Z'
		     (97 <= ch && ch <= 122) ||		// 'a'..'z'
		     (46 <= ch && ch <= 57) ) {		// '.', '/', '0'..'9'
			sbuf += s.charAt(i);
		} else if (ch == 32) {                   // space
			sbuf += '+';
		}

		else if (ch <= 0x007f) {                // other ASCII
			sbuf += cspEncodeChar(ch);
		} else if (ch <= 0x07FF) {                // non-ASCII <= 0x7FF
			sbuf += cspEncodeChar(0xc0 | (ch >> 6));
			sbuf += cspEncodeChar(0x80 | (ch & 0x3F));
		} else {                                  // 0x7FF < ch <= 0xFFFF
			sbuf += cspEncodeChar(0xe0 | (ch >> 12));
			sbuf += cspEncodeChar(0x80 | ((ch >> 6) & 0x3F));
			sbuf += cspEncodeChar(0x80 | (ch & 0x3F));
		}
	}
	return sbuf;
}
