﻿/*
  Injects the javascript LookingGlass counterpart.  All interaction is mediated through this object.
  Only the LookingGlass variable itself is put in the global namespace.
*/

var LookingGlass = new function(){
	var regcount = 0; //index into registry for next registered item
	var registry = this.registry = {}; //empty associative array
	
	var registerObject = this.registerObject = function(obj){
		if (!('_lookingGlassProxy' in obj)){
			obj._lookingGlassProxy = {id:regcount++, 
				jsProxy:true,
				jsType:typeof(obj)};
			registry[obj._lookingGlassProxy.id] = obj;
		}
		return obj._lookingGlassProxy;
	}

	this.callFunction = function(objid, funname, args){
	  var obj = registry[objid];
	  //need to reverse translate any args which are proxied js objects here.
	  try {
		var intermediate = obj[funname].apply(obj, untranslate(args));
		var toreturn = translate(intermediate);
		return toreturn;
	  }catch(error){
		this.debug("error:", e);
	  }
	}
	
	this.getProperty = function(objid, propname){
	  var obj = registry[objid];
	  if (typeof(obj[propname]) == 'function'){
		obj[propname].origThis = obj;
	  }
	  return translate(obj[propname]);
	}
	
	this.hasProperty = function(objid, propname){
	  var obj = registry[objid];
	  return propname in obj; 
	}
	
	this.setProperty = function(objid, propname, val){
	  var obj = registry[objid];
	  obj[propname] = untranslate(val);
	}
	
	this.invokeProxiedFunction = function(objid, funargs){
	  var obj = registry[objid]; //should be a Function
	  var untransArgs = untranslate(funargs);
	  var origThis = obj.origThis;
	  if (typeof(origThis) == undefined){
		origThis = null;
	  }
	  var intermediate = obj.apply(origThis, untransArgs);
	  return translate(intermediate);
	}

	this.$ = function(){
	  var dolla = window.$;
	  var context = window;
	  if (typeof(dolla) == 'undefined'){
		dolla = document.getElementById;
		context = document;
	  }
	  var toreturn = dolla.apply(context, arguments);
	  if (typeof(toreturn) != 'undefined'){
		var t2 = translate(toreturn);
		return t2;
	  }else{
		return undefined;
	  }
	}
	
	this.eval = function(evalarg){
	  return translate(eval(evalarg));
	}
	
	this.debug = function(){
	  if (typeof(console) != 'undefined'){
		console.log.apply(console, arguments);
	  }else{
		alert(arguments.join("|"));
	  }
	}
	
	//register if necessary.
	//outgoing js -> as
	var translate = function translate(thing){
	  if ((typeof(thing) == "object")||(typeof(thing) == "function")){
		return registerObject(thing);
	  }
	  return thing;
	}
	
	//incoming as -> js
	var untranslate = function untranslate(thing){
	  if (typeof(thing) == "object"){
		//if thing is an array, untranslate the parts
		if (thing instanceof Array){
		  var toreturn = [];
		  for (var i = 0; i < thing.length; i++){
			toreturn[i] = untranslate(thing[i]);
		  }
		  return toreturn;
		}else if (thing.jsProxy){
		  //if thing is an object with jsProxy = true, return proxied from registry
		  return registry[thing.id];
		}else{
		  //it's a plain jane object
		  return thing;
		}
	  }else{
		return thing;
	  }
	}
};
		