/*
 * Title:       Javascript Library Manager
 * Author:		Mark Ragan
 * Copyright:	Copyright (c) 2002, Mark Ragan
 * Version:		1.2
 *
 * This software is protected under the copyright laws as an unpublished work
 * which was created in the year(s) indicated above, and may not be used without
 * the written consent of Mark Ragan mragan @ austin.rr.com.
 * ALL RIGHTS RESERVED
 */

debugMode = new Boolean(false);

/* -------------------------------------------------------------------------------------------    
    Object:      rc_LibManager
	
    Description: rc_LibManager is an object which instantiates realJSLibManager such that
	             only one realJSLibManager exists; i.e. a singleton of sorts
				 
    Methods:     none; constructor only
  ------------------------------------------------------------------------------------------- */
  function rc_LibManager ()
  {
    //
    //  Protect this object so that it's a singleton
    //
	if ( (rc_LibManager.instance == "undefined") ||
	     (rc_LibManager.instance == null) ||
		 (rc_LibManager.instance == undefined))
    {
      rc_LibManager.instance = new realLibManager();
    }
	
    return rc_LibManager.instance;	

    /* -------------------------------------------------------------------------------------------    
      Object:      realLibManager
	
      Description: this object is the actual library manager.  It tracks the libraries to load,
	               which have loaded and logs all activity regarding the process.
				 
      Methods:     load - identifies a library to load
	               register - registers the library as having been loaded
    ------------------------------------------------------------------------------------------- */		
    function realLibManager()
    {
      this.libList = new Array();							
	  this.subDomain = new String("");         //the subdomain name
      this.codeFolder = new String("/code/");  //path within the subdomain for the code base  
      
      var loc = new String(window.location);
      var path = new String(window.location.pathname);		
      this.prefix = loc.substring(0, loc.length - path.length);

      // Write header init string to log
      this.log = new rc_logger();
      var header = rc_logger.replaceToken(this.log.headerFormat, "$HEADER$", "Initializing Javascript Library Manager");
      header = rc_logger.replaceToken(header, "$VERSION$", "1.0");
      header = rc_logger.replaceToken(header, "$DATE$", new Date());		
      this.log.append(header);
			
      //
      //  Load a library
      //
      function load(name)
      {
        var url = new String("");
        if ((this.prefix == "file://") || (this.prefix == "file:///"))
          url = this.codeFolder + name;
        else
          url = this.prefix + this.subDomain + this.codeFolder + name;

		if (debugMode.valueOf() == true)
          alert("request for " + url);
		  
        //  see if entry is already being or has been loaded			
        for (var s=0; s < this.libList.length; s++)
        {
          if (this.libList[s].name == name)
          {
            if (debugMode.valueOf() == true)		  
              alert("load: found in array");
			  
            //  Library is already loaded or about to be... write log entry
            if (this.libList[s].registered == true)
            {
              var detail = this.log.loadFormat;
              detail = rc_logger.replaceToken(this.log.loadFormat, "$URL$", "$URL$ <font color='CCCCCC'>{already loaded}</font>");
              detail = rc_logger.replaceToken(detail, "$URL$", url);
              this.log.append(detail);
			  
              if (debugMode.valueOf() == true) 
                alert("load: already got it " + url);							
            }
            else 
            {
              var detail = this.log.loadFormat;
              detail = rc_logger.replaceToken(this.log.loadFormat, "$URL$", "$URL$ <font color='CCCCCC'>{already scheduled for loading}</font>");
              detail = rc_logger.replaceToken(detail, "$URL$", url);
              this.log.append(detail);

              if (debugMode.valueOf() == true)			  
                alert("load: already getting it " + url);
            }					
            return;
          }
        }
				
        // load library
        this.libList[this.libList.length] = new libEntry(name, url, new Boolean(false));
        var include = "<" + "SCRIPT " + "LANGUAGE='JavaScript1.2' " +
        "SRC='" + url + "' " +
		"TYPE='text/javascript'" + ">" + "<\/" + "SCRIPT" + ">";
	
        if (debugMode.valueOf() == true)
          alert("load: " + url);
        document.write(include);
        if (debugMode.valueOf() == true)
          alert("included:\r\n"	 + include);
				
        this.log.append(rc_logger.replaceToken(this.log.loadFormat, "$URL$", url));
      }
      this.load = load;

      //
      //  Register that a library was loaded
      //
      function register(name)
      {
        for (s=0; s < this.libList.length; s++)
        {
          if (this.libList[s].name == name)
          {
            this.libList[s].registered = new Boolean(true);
            this.log.append(rc_logger.replaceToken(this.log.loadedFormat, "$URL$", this.libList[s].url));
			
            if (debugMode.valueOf() == true)			
              alert("returning " + this.libList[s].name + " = " + name);
			  
            return;						
          }					
        }		
        var detail = rc_logger.replaceToken(this.log.loadedFormat, "$URL$", "$URL$ <font color='CCCCCC'>{load request entry not found}</font>");
        detail = rc_logger.replaceToken(detail, "$URL$", name);
        this.log.append(detail);				  
      }	
      this.register = register;
	  
	  function testme() { alert("the realLibManager has been instantiated"); }
	  this.testme = testme;

      /* -------------------------------------------------------------------------------------------    
        Object:      libEntry
	
        Description: this is really just a value object to hold information about a library entry
				 
        Methods:     none; constructor only
      ------------------------------------------------------------------------------------------- */			
      function libEntry (name, url, registered)
      {
        this.name = name;
        this.url = url;
        this.registered = registered;
      }				
    }
		
    /* -------------------------------------------------------------------------------------------    
      Object:      rc_logger
	
      Description: rc_logger is a logging object which provides an area in which to write logging
	               material/text and to write it out.     
	  			 
      Methods:     append - appends the provided string to the end of the current log
	               clear - clears the log
				   write - returns the log contents
				   replaceToken - a STATIC method which returns a string where tokens are
				                  replaced with values
    ------------------------------------------------------------------------------------------- */		
    function rc_logger()
    {
      this.log = new String("");
      this.headerFormat = new String("<font face='Verdana, Arial, Helvetica, sans-serif' color='#CC6600' size='2'>$HEADER$ $VERSION$ $DATE$</font>");
      this.loadFormat   = new String("<li>" + 
                                     "  <font face='Arial, Helvetica, sans-serif' size='2'>" +
                                     "    <font color='#666666'>Load: </font>" + 
                                     "    <font color='#3333CC'> $URL$ </font>" +
                                     "  </font>" + 
                                     "</li>");
      this.loadedFormat = new String("<li>" +
                                     "  <font face='Arial, Helvetica, sans-serif' size='2'>" + 
                                     "    <font color='#666666'>Loaded:</font>" + 
                                     "    <font color='#CC3333'> $URL$ </font>" + 
                                     "  </font>" + 
                                     "</li>");						
		
      //
      //  Append the given string to the log
      //
      function append(string)
      {
        this.log += string;
      }
      this.append = append;

      //
      //  Clear the log
      //
      function clear()
      {
        this.log = new String("");
      }
      this.clear = clear;

      //
      //  Display the log
      //
      function write() 
      {
        return (this.log);
      }
      this.write = write;
	  								
      //
      //  A static method on the prototype object which replaces the specified token with the given value
      //
      function replaceToken (stream, token, value)
      {
        var a1 = new String(stream);			
        var newStream = new String("");								
        var p1 = a1.indexOf(token);
						
        if ( p1 >= 0 )
          newStream = a1.substr(0,p1) + value + a1.substr(p1 + token.length, a1.length-(p1 + token.length));
        else
          newStream = new String(stream);
					
        return newStream;
      }						  
      rc_logger.replaceToken = replaceToken;		  
    }
  }
  
//first and ONLY instance of the manager
  jsMgr = new rc_LibManager();
  jsMgr.codeFolder = "/resources/code/";	
