var rpcifws = [];
var rpcforms = [];
var rpcqueue = [];
var rpcfree = -1;
var rpctimer = [];
function rpcmkifr(name) {
	var e;
 	if (document.getElementById) {
		e = document.createElement("iframe");
		e.style.width = "0";
		e.style.height = "0";
		e.style.border = "0";
		e.id = name;
		//e.name = name;
		document.body.appendChild(e);
	} else if (document.all) {
		var h = '<iframe id="' + name + '" name="' + name + '" style="border:0;width:0;height:0"></iframe>';
		document.body.insertAdjacentHTML("beforeEnd", h);
		e = document.all[name];
	}
	var w = e.contentWindow;
	w.name = name;
	return w;
}
var rpcmrQuote = /(["\\])/g;
function rpcmarshall(x) {
	switch (typeof x) {
		case "string":
			return '"' + x.replace(rpcmrQuote, "\\$1") + '"';
		case "number":
		case "function":
			return String(x);
		case "object":
			if (!x)
				return "null";
			else if ("length" in x) { // instanceof Array) {
				var a = [];
				for (var i = 0; i < x.length; i++)
					a[i] = rpcmarshall(x[i]);
				return "[" + a.join(",") + "]";
			} else if (x instanceof Date) {
				return "new Date(" + x.getTime() + ")";
			//} else if (x.toSource instanceof Function) {
			//	return x.toSource();
			} else {
				var a = [];
				for (y in x)
					a[a.length] = y + ":" + rpcmarshall(x[y]);
				return "{" + a.join(",") + "}";
			}
		case "boolean":
			return x ? "true" : "false";
		case "null":
		case "undefined":
			return "null";
	}
	throw new Error(0x80040200, "unknown value: " + x);
}
function rpc(fid, args, cont) {
	var idx;
	if (rpcfree >= 0) {
		idx = rpcfree;
		rpcfree = rpcqueue[rpcfree];
	} else
		idx = rpcqueue.length;
	/*
	if (idx) { // remove current
		var oc = rpcqueue[0];
		rpcqueue.splice(0, 1);
		oc(null);
		idx = 0;
	}
	*/
	rpcqueue[idx] = cont;
	if (!rpcifws[idx])
		rpcifws[idx] = rpcmkifr("rpcifr" + idx + "x" + new Date().getTime());
	var argsstr = rpcmarshall(args);
	if (argsstr.length > 256) {
		var rpcform;
		if (!(rpcform = rpcforms[idx])) {
			rpcform = rpcforms[idx] = document.createElement("form");
			rpcform.style.margin = "0";
			rpcform.target = rpcifws[idx].name;
			rpcform.action = "/cgi-bin/as.cgi/0000000/c/jsrpc.call";
			rpcform.method = "post";
			rpcform.innerHTML = '<input type="hidden" name="f"><input type="hidden" name="idx"><input type="hidden" name="args">';
			/*
			var a = ["f", "idx", "args"];
			for (var i = 0; i < a.length; i++) {
				var e = document.createElement("INPUT");
				e.type = "hidden";
				e.name = a[i];
				rpcform.appendChild(e);
			}
			*/
			document.body.appendChild(rpcform);
		}
		rpcform.f.value = fid;
		rpcform.idx.value = idx;
		rpcform.args.value = argsstr;
		rpcform.submit();
	} else
		rpcifws[idx].location.replace("/cgi-bin/as.cgi/0000000/c/jsrpc.call?f=" + fid + "&idx=" + idx + "&args=" + escape(argsstr));
	//rpctimer[idx] = setTimeout(function(){rpcfail(idx, "Timeout")}, 10000);
}
function rpcevent(idx, args) {
	clearTimeout(rpctimer[idx]);
	var cont = rpcqueue[idx];
	rpcqueue[idx] = rpcfree;
	rpcfree = idx;
	if (typeof cont != "function")
		throw new Error(0x80040200, "invalid callback @ " + idx + ": " + cont);
	cont(args);
}
function rpcfail(idx, msg) {
	clearTimeout(rpctimer[idx]);
	//var cont = rpcqueue[idx];
	rpcqueue[idx] = rpcfree;
	rpcfree = idx;
	//cont(null);
	throw new Error(0x80040200, msg);
}
