
function FABridge(target,bridgeName)
{this.target=target;this.remoteTypeCache={};this.remoteInstanceCache={};this.remoteFunctionCache={};this.localFunctionCache={};this.bridgeID=FABridge.nextBridgeID++;this.name=bridgeName;this.nextLocalFuncID=0;FABridge.instances[this.name]=this;FABridge.idMap[this.bridgeID]=this;return this;}
FABridge.TYPE_ASINSTANCE=1;FABridge.TYPE_ASFUNCTION=2;FABridge.TYPE_JSFUNCTION=3;FABridge.TYPE_ANONYMOUS=4;FABridge.initCallbacks={};FABridge.userTypes={};FABridge.addToUserTypes=function()
{for(var i=0;i<arguments.length;i++)
{FABridge.userTypes[arguments[i]]={'typeName':arguments[i],'enriched':false};}}
FABridge.argsToArray=function(args)
{var result=[];for(var i=0;i<args.length;i++)
{result[i]=args[i];}
return result;}
function instanceFactory(objID)
{this.fb_instance_id=objID;return this;}
function FABridge__invokeJSFunction(args)
{var funcID=args[0];var throughArgs=args.concat();throughArgs.shift();var bridge=FABridge.extractBridgeFromID(funcID);return bridge.invokeLocalFunction(funcID,throughArgs);}
FABridge.addInitializationCallback=function(bridgeName,callback)
{var inst=FABridge.instances[bridgeName];if(inst!=undefined)
{callback.call(inst);return;}
var callbackList=FABridge.initCallbacks[bridgeName];if(callbackList==null)
{FABridge.initCallbacks[bridgeName]=callbackList=[];}
callbackList.push(callback);}
function FABridge__bridgeInitialized(bridgeName)
{var searchStr="bridgeName="+bridgeName;if(/Explorer/.test(navigator.appName)||/Konqueror|Safari|KHTML/.test(navigator.appVersion))
{var flashInstances=document.getElementsByTagName("object");if(flashInstances.length==1)
{FABridge.attachBridge(flashInstances[0],bridgeName);}
else
{for(var i=0;i<flashInstances.length;i++)
{var inst=flashInstances[i];var params=inst.childNodes;var flash_found=false;for(var j=0;j<params.length;j++)
{var param=params[j];if(param.nodeType==1&&param.tagName.toLowerCase()=="param")
{if(param["name"].toLowerCase()=="flashvars"&&param["value"].indexOf(searchStr)>=0)
{FABridge.attachBridge(inst,bridgeName);flash_found=true;break;}}}
if(flash_found){break;}}}}
else
{var flashInstances=document.getElementsByTagName("embed");if(flashInstances.length==1)
{FABridge.attachBridge(flashInstances[0],bridgeName);}
else
{for(var i=0;i<flashInstances.length;i++)
{var inst=flashInstances[i];var flashVars=inst.attributes.getNamedItem("flashVars").nodeValue;if(flashVars.indexOf(searchStr)>=0)
{FABridge.attachBridge(inst,bridgeName);}}}}
return true;}
FABridge.nextBridgeID=0;FABridge.instances={};FABridge.idMap={};FABridge.refCount=0;FABridge.extractBridgeFromID=function(id)
{var bridgeID=(id>>16);return FABridge.idMap[bridgeID];}
FABridge.attachBridge=function(instance,bridgeName)
{var newBridgeInstance=new FABridge(instance,bridgeName);FABridge[bridgeName]=newBridgeInstance;var callbacks=FABridge.initCallbacks[bridgeName];if(callbacks==null)
{return;}
for(var i=0;i<callbacks.length;i++)
{callbacks[i].call(newBridgeInstance);}
delete FABridge.initCallbacks[bridgeName]}
FABridge.blockedMethods={toString:true,get:true,set:true,call:true};FABridge.prototype={root:function()
{return this.deserialize(this.target.getRoot());},releaseASObjects:function()
{return this.target.releaseASObjects();},releaseNamedASObject:function(value)
{if(typeof(value)!="object")
{return false;}
else
{var ret=this.target.releaseNamedASObject(value.fb_instance_id);return ret;}},create:function(className)
{return this.deserialize(this.target.create(className));},makeID:function(token)
{return(this.bridgeID<<16)+token;},getPropertyFromAS:function(objRef,propName)
{if(FABridge.refCount>0)
{throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");}
else
{FABridge.refCount++;var retVal=this.target.getPropFromAS(objRef,propName);retVal=this.handleError(retVal);FABridge.refCount--;return retVal;}},setPropertyInAS:function(objRef,propName,value)
{if(FABridge.refCount>0)
{throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");}
else
{FABridge.refCount++;var retVal=this.target.setPropInAS(objRef,propName,this.serialize(value));retVal=this.handleError(retVal);FABridge.refCount--;return retVal;}},callASFunction:function(funcID,args)
{if(FABridge.refCount>0)
{throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");}
else
{FABridge.refCount++;var retVal=this.target.invokeASFunction(funcID,this.serialize(args));retVal=this.handleError(retVal);FABridge.refCount--;return retVal;}},callASMethod:function(objID,funcName,args)
{if(FABridge.refCount>0)
{throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");}
else
{FABridge.refCount++;args=this.serialize(args);var retVal=this.target.invokeASMethod(objID,funcName,args);retVal=this.handleError(retVal);FABridge.refCount--;return retVal;}},invokeLocalFunction:function(funcID,args)
{var result;var func=this.localFunctionCache[funcID];if(func!=undefined)
{result=this.serialize(func.apply(null,this.deserialize(args)));}
return result;},getUserTypeDescriptor:function(objTypeName)
{var simpleType=objTypeName.replace(/^([^:]*)\:\:([^:]*)$/,"$2");var isUserProto=((typeof window[simpleType]=="function")&&(typeof FABridge.userTypes[simpleType]!="undefined"));var protoEnriched=false;if(isUserProto){protoEnriched=FABridge.userTypes[simpleType].enriched;}
var toret={'simpleType':simpleType,'isUserProto':isUserProto,'protoEnriched':protoEnriched};return toret;},getTypeFromName:function(objTypeName)
{var ut=this.getUserTypeDescriptor(objTypeName);var toret=this.remoteTypeCache[objTypeName];if(ut.isUserProto)
{if(!ut.protoEnriched)
{for(i in window[ut.simpleType].prototype)
{toret[i]=window[ut.simpleType].prototype[i];}
window[ut.simpleType].prototype=toret;this.remoteTypeCache[objTypeName]=toret;FABridge.userTypes[ut.simpleType].enriched=true;}}
return toret;},createProxy:function(objID,typeName)
{var ut=this.getUserTypeDescriptor(typeName);var objType=this.getTypeFromName(typeName);if(ut.isUserProto)
{var instFactory=window[ut.simpleType];var instance=new instFactory(this.name,objID);instance.fb_instance_id=objID;}
else
{instanceFactory.prototype=objType;var instance=new instanceFactory(objID);}
this.remoteInstanceCache[objID]=instance;return instance;},getProxy:function(objID)
{return this.remoteInstanceCache[objID];},addTypeDataToCache:function(typeData)
{var newType=new ASProxy(this,typeData.name);var accessors=typeData.accessors;for(var i=0;i<accessors.length;i++)
{this.addPropertyToType(newType,accessors[i]);}
var methods=typeData.methods;for(var i=0;i<methods.length;i++)
{if(FABridge.blockedMethods[methods[i]]==undefined)
{this.addMethodToType(newType,methods[i]);}}
this.remoteTypeCache[newType.typeName]=newType;return newType;},addPropertyToType:function(ty,propName)
{var c=propName.charAt(0);var setterName;var getterName;if(c>="a"&&c<="z")
{getterName="get"+c.toUpperCase()+propName.substr(1);setterName="set"+c.toUpperCase()+propName.substr(1);}
else
{getterName="get"+propName;setterName="set"+propName;}
ty[setterName]=function(val)
{this.bridge.setPropertyInAS(this.fb_instance_id,propName,val);}
ty[getterName]=function()
{return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id,propName));}},addMethodToType:function(ty,methodName)
{ty[methodName]=function()
{return this.bridge.deserialize(this.bridge.callASMethod(this.fb_instance_id,methodName,FABridge.argsToArray(arguments)));}},getFunctionProxy:function(funcID)
{var bridge=this;if(this.remoteFunctionCache[funcID]==null)
{this.remoteFunctionCache[funcID]=function()
{bridge.callASFunction(funcID,FABridge.argsToArray(arguments));}}
return this.remoteFunctionCache[funcID];},getFunctionID:function(func)
{if(func.__bridge_id__==undefined)
{func.__bridge_id__=this.makeID(this.nextLocalFuncID++);this.localFunctionCache[func.__bridge_id__]=func;}
return func.__bridge_id__;},serialize:function(value)
{var result={};var t=typeof(value);if(t=="number"||t=="string"||t=="boolean"||t==null||t==undefined)
{result=value;}
else if(value instanceof Array)
{result=[];for(var i=0;i<value.length;i++)
{result[i]=this.serialize(value[i]);}}
else if(t=="function")
{result.type=FABridge.TYPE_JSFUNCTION;result.value=this.getFunctionID(value);}
else if(value instanceof ASProxy)
{result.type=FABridge.TYPE_ASINSTANCE;result.value=value.fb_instance_id;}
else
{result.type=FABridge.TYPE_ANONYMOUS;result.value=value;}
return result;},deserialize:function(packedValue)
{var result;var t=typeof(packedValue);if(t=="number"||t=="string"||t=="boolean"||packedValue==null||packedValue==undefined)
{result=this.handleError(packedValue);}
else if(packedValue instanceof Array)
{result=[];for(var i=0;i<packedValue.length;i++)
{result[i]=this.deserialize(packedValue[i]);}}
else if(t=="object")
{for(var i=0;i<packedValue.newTypes.length;i++)
{this.addTypeDataToCache(packedValue.newTypes[i]);}
for(var aRefID in packedValue.newRefs)
{this.createProxy(aRefID,packedValue.newRefs[aRefID]);}
if(packedValue.type==FABridge.TYPE_PRIMITIVE)
{result=packedValue.value;}
else if(packedValue.type==FABridge.TYPE_ASFUNCTION)
{result=this.getFunctionProxy(packedValue.value);}
else if(packedValue.type==FABridge.TYPE_ASINSTANCE)
{result=this.getProxy(packedValue.value);}
else if(packedValue.type==FABridge.TYPE_ANONYMOUS)
{result=packedValue.value;}}
return result;},addRef:function(obj)
{this.target.incRef(obj.fb_instance_id);},release:function(obj)
{this.target.releaseRef(obj.fb_instance_id);},handleError:function(value)
{if(typeof(value)=="string"&&value.indexOf("__FLASHERROR")==0)
{var myErrorMessage=value.split("||");if(FABridge.refCount>0)
{FABridge.refCount--;}
throw new Error(myErrorMessage[1]);return value;}
else
{return value;}}};var ASProxy=function(bridge,typeName)
{this.bridge=bridge;this.typeName=typeName;return this;};ASProxy.prototype={get:function(propName)
{return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id,propName));},set:function(propName,value)
{this.bridge.setPropertyInAS(this.fb_instance_id,propName,value);},call:function(funcName,args)
{this.bridge.callASMethod(this.fb_instance_id,funcName,args);},addRef:function(){this.bridge.addRef(this);},release:function(){this.bridge.release(this);}};
