/*
 * @fileoverview WebAuroraEnvironment is intended to model a runtime environment for loading other web
 * functionality, such as RIA/JavaScript files onto the page. Example code:
 * <pre>
 *    @lt;script src="path/to/core.js"&gt;&lt;/script&gt;
 *    @lt;script type="text/javascript"&gt;
 *       // Module is already defined by core.js for clink.
 *       Module.load("meta","project","release");
 *    &lt;/script&gt;
 * </pre>
 */

var Module;

/** 
 * Construct a new WebAuroraEnvironment instance
 * @class WebAuroraEnvironment is the class designed to be a 
 * representation of the hosted toolkit environment, similar
 * to the Morgan Stanley Aurora environment found elsewhere.
 * The purpose is to bring the same convenience of "module load" 
 * commands, and the abstractions they provide to web developers, as 
 * well as provide several convenience methods similar to that of
 * other "runtime environments."
 */
function WebAuroraEnvironment(){
	/**
         * @private
         */
        this.mode = "local";

        // Default
        this.prefix="/ria/webaurora/docs/";

	  // Auto-discover location
        var s=0;
        var _script_tags=document.getElementsByTagName("script");
        var endsWith=function(str, substr){
           return (str && str.indexOf(substr) == (str.length-substr.length));
        };
        for(s=0;s<_script_tags.length;++s){ 
           var src=_script_tags[s].src;
            if(src){
	      if(src.indexOf("://")>-1)
                 {
                   src=src.substring(src.indexOf("://")+3);
                   src=src.substring(src.indexOf("/"));
                 }
            if(endsWith(src,"core.js") || endsWith(src,"core-debug.js")) {
                this.prefix=src.substring(0, src.lastIndexOf("/")+1);
             }
           }
        }
	 
	/**
         * @private
         */
	this.suffix=".js";

	/**
         * @private
         * Make the Path of a module to meta/proj/release
         */
	this.makeModulePath=function(m,p,r,suff){
	     // if just a url is specified, use it
	     if(!p && !r) return this.stripExternalRef(m);

             // build the m/p/r path
             return this.prefix+m+"/"+p+"/incr/etc/modules/"+r+ ((suff)?this.suffix:"");
	}

	/**
         * The generate the path prefix for a MPR linked into the WebAurora Environmentiables
         * @param m meta
         * @param p project
         * @param r release
         */
	this.makePath=function(m,p,r){
	     // if just a url is specified, use it
	     if(!p && !r) return this.stripExternalRef(m);

           // build the m/p/r path
           return this.prefix + m +"/" + p + "/" + r + "/";
	}

	/**
         * @private
         */
        this.env=new Object();

	/**
         * @private
         */
        this.loaders=new Object();

	/**
         * The sets an environment variable (make sure it's safe for JS Object[key] notation)
         * The idea here is that modules could set this, and pages which load the module
         * can then get the Environment variables
         * @param k javascript object[key] 
	 * @param v value (technically could be of any type...)
         */
        this.setEnv=function(k,v){ 
		this.env[k]=v;
		}

	/**
         * The gets an environment variable previously set
         * @param k javascript object[key] 
	 * @returns the value set for this key
         */
        this.getEnv=function(k){ return this.env[k];}

         /**
         * The similar to LOADEDMODULES - this is an associative array of all modules
         * loaded in this environment.
         * @private
         */
        this._loadedModules=new Object();
        
         /**
         * This makes a normalized key to stick into loaded_modules and verify if things are loaded.
         * @private
         */
	this.normalize=function(m,p,r){ return (m+"__"+p+"__"+r).toLowerCase();};

         /**
         * This checks whether the given meta/project/release is already loaded.
         * @param m metaproject (or the path of a JS file, if no other args are passed)
         * @param p project
         * @param r release
         * @type boolean
         * @returns Whether m/p/r is loaded
         */
        this.isLoaded=function(m,p,r){
		var xkey=this.normalize(m,p,r);
		return(this._loadedModules[xkey]!=null);
	};


        /**
         * Gets a "loader" based on the MPR specified in the arguments
         * This is useful for loading subpackages.  You can call {@link WebAuroraSubLoader#load} or {@link WebAuroraSubLoader#loadAll} on this
         * and it will load submodules under a folder with the "release" number
         * @see WebAuroraSubLoader
         * @param m metaproject 
         * @param p project
         * @param r release
         * @returns void
         */
        this.getLoader=function(m,p,r){
		var key=this.normalize(m,p,r);	
		var loader=this.loaders[key];
		if(loader) {
		   return loader;
		}
		else {
		   loader=new WebAuroraSubLoader(this,this.makeModulePath(m,p,r,false)+"/");
		   var __path=this.makePath(m,p,r);
		   this.setEnv(p.toUpperCase()+"_PATH",__path);
		   this.loaders[key]=loader;
		   return loader;
		}
	}
	
        /**
         * Loads the requested module into the environment
         * You can also load your own module by calling loadJavascript(url) if you want
         * @param m metaproject 
         * @param p project
         * @param r release
         * @type boolean
         * @returns void
         */
        this.load=function(m,p,r){
	 var key=this.normalize(m,p,r);	
 	 var url=this.makeModulePath(m,p,r,true); 
	 try{
		if(this.isLoaded(m,p,r)) {
			return;
		}
		this.loadJavaScript(url);
		this._loadedModules[key]="true";
	 } catch (e){ this.handleError(e); }
	};


        /**
         * Loads a JavaScript file into the page 
         * @param {String} url the url of the javascript file
         */
        this.loadJavaScript=function (url){
              url = this.stripExternalRef(url);
              document.writeln("<scri"+"pt src='"+url+"' type='text/javascript'></sc"+"ript>");
	};

        /**
         * Loads a JavaScript file into the page 
         * @param {String} url the url of the javascript file
         */
        this.loadStyleSheet=function(url){
              url = this.stripExternalRef(url);
	      document.writeln("<li"+"nk rel='stylesheet' href='"+url+"' type='text/css'></li"+"nk>");
        };


        /**
         * Strips out any double slashes, double dots, or cross domain references.
         * @param s string
         */
        this.stripExternalRef=function(s){
              var exprs = [/\.\.+/g,/\/\/+/g,/\\\\+/g,/\:+/g,/\'+/g,/\%+/g];
              for(var i=0; i<exprs.length; i++)
              {
                s = s.replace(exprs[i], '');
              }

              return s;
        }

        /**
         *  Overwritable error handler
         */
        this.handleError=function(e) {
        }
 
	return this;
};

/** 
 * Construct a new WebAuroraSubLoader instance. You shoudl never need to call this, as {@link WebAuroraEnvironment#getLoader} gets you one of these from the environment.
 * @class WebAuroraSubLoader is designed to load "sub" modules
 * This is a wrapper which is produced when you call  {@link WebAuroraEnvironment#getLoader} 
 * It is designed to allow sub-packages within a given MPR to be loaded easily. This is constructed by Module.getLoader() call
 * so you should never really need to construct one of these.
 * @constructor
 * @param {WebAuroraEnvironment} env_  
 * @param {String} prefix_  The path underneath which the submodules reside
 * 
 */

function WebAuroraSubLoader(env_, prefix_){
	/**
         * @private
         */
	this.environment=env_;

	/**
         * @private
         */
	this.prefix=prefix_;

	/**
         * @private
         */

	this.loaded=new Object();

	/**
         * @private
         */
	this.normalize=function(str){ return str.toLowerCase(); }
	
 	/**
         * Loads an array of subpackages
         * @param {Array} pkgs an array of packages.
         */

      this.loadAll=function(pkgs_){
          for(i=0;i<pkgs_.length;++i) this.load(pkgs_[i]);
      };

	 /**
         * Loads a subpackage, if it's not already loaded
         * @param {String} url the url of the sub-package module file (m/p/r/submodule.js)
         */
	this.load=function(pkg){
		var p=this.normalize(pkg);
		if (this.loaded[p]) {
			return;
		}
		this.loaded[p]=pkg;
		this.environment.loadJavaScript(prefix_+pkg+".js");
	};
};

if(!Module)
{
  Module = new WebAuroraEnvironment();
}


