// in lieu of proper resource registration, this will allow targeting of SCRIPT resources
$resource = function $resource(id, win) {
    var scripts = (win||window).document.getElementsByTagName("SCRIPT");
    for (var i=0; i< scripts.length; i++)
        if (scripts[i].src.match("#resource"+id))
            return scripts[i];
};
var net = {
    modules : {},
    _stubs : {},
    // Basic AJAX encapsulator
    AJAX : function AJAX(uri,options) {
        var ajax;
        if (window.XMLHttpRequest)
            ajax = new XMLHttpRequest();
        else
            for (var s in {"Msxml2.XMLHTTP.6.0":null,"Msxml2.XMLHTTP.3.0":null,"Msxml2.XMLHTTP":null,"Microsoft.XMLHTTP":null})
                try { ajax = new ActiveXObject(s); if (ajax) break } catch (e){};
        ajax.open('GET', uri, true);
        return ajax;
    },
    // Basic JSON encapsulator (uses JSONP)
    JSON : function JSON(uri,options) {
        var id = net.getID();
        options = options || {};
        options.jsonp = options.jsonp || encodeURI("$resource('"+id+"').responseData = ");
        uri += (uri.match("?") ? "&" : "?") + "jsonp=" + options.jsonp;
        uri += "#resource" + id;
        var json = document.createElement("SCRIPT");
        json.src = uri;
        json.type = "text/javascript";
        json.send = function send() {document.documentElement.lastChild.appendChild(json)};
        return json;
        // ToDo: synchronous version?
    },
    // ToDo: support and emulation for cross-frame fetches via HTML5 PostMessage()
    // Generalized RPC abstraction
    RPC : function RPC(uri, rpcCallback, rpcOptions) {
        var rpc, rpcType;
        if (rpcOptions)
            rpcType = rpcOptions.type;
        if  (rpcType == "json" || rpcType == "jsonp") {
            rpc = net.JSON(uri,rpcOptions);
            rpc.onload = function() { rpcCallback( rpc.responseData ) };
        } else {
            rpc = net.AJAX(uri,rpcOptions);
            rpc.onreadystatechange = function() { if (rpc.readyState == 4) rpcCallback( (rpcType=="ajax-xml") ? rpc.responseXML : rpc.responseText ) };
        }
        rpc.send(null);
        return rpc;
    },
    // unique IDs for in-browser objects (these are not to be considered unique in the client-server context)
    getID : (function() {
        var nextID = 0;
        function getID() {
            var id = nextID;
            nextID++;
            return id;
        }
        return getID;
    })(),
    // returns either the module (if pre-loaded) or null to signify in-process
    getModule : function getModule(modName, modURI, modOpts) {
        modOpts = modOpts || {};
        // module has not been requested
        if (!net.modules[modName] && !net._stubs[modName]) {
            if (!modURI)
                throw new Error("Module "+modName+" is unknown.");
            net._stubs[modName] = new net._Stub(modName, modURI, modOpts);
        }
        // ToDO: allow waiting on a pending module via modOpts.callback
        // module is pending
        if (!net.modules[modName])
            return null;
        // module name is not unique
        if (modURI && modURI != net.modules[modName].uri)
            throw new Error("Naming conflict between "+modName+"("+modURI+")"+
                        " and "+modName+"("+net.modules[modName].uri+")");
        return net.modules[modName];
    },
    _Stub : function _Stub(modName, modURI, modOpts) {
        this.name = modName;
        this.uri = modURI;
        this.options = modOpts;
        this.resource = new net.RPC(
            modURI,
            function callback(response) {
                var mod;
                if (modOpts.type=="json" || modOpts.type=="jsonp")
                    net.modules[modName] = mod = response;
                else
                    mod = new net.Module(modName, modURI, response, modOpts);
                delete net._stubs[modName].resource;
                delete net._stubs[modName];
                if (modOpts.callback)
                    modOpts.callback(mod);
            },
            modOpts
        );
        this.resource.send(null);
        //ToDo: JSONP
    },
    Module : function Module(modName, modURI, modSrc, modOpts) {
        this.uri = modURI;
        var modPrefix = "(function(" + (modOpts.args || []).join(",") + ") {\n\n";
        if (modOpts["export"])
            modPrefix += "var EXPORTED_SYMBOLS = modOpts['export'];\n";
        modPostfix = "for (var i = 0; i < EXPORTED_SYMBOLS.length; i++)\n" +
                "\tthis[EXPORTED_SYMBOLS[i]] = eval(EXPORTED_SYMBOLS[i]);\n" +
                "\n})";
        eval(modPrefix + modSrc + modPostfix).apply(this, modOpts.argv||[]);
        net.modules[modName] = this;
    }
};
