/*
 * <copyright>
 *  Copyright (c) Hyperwave GmbH 2010
 * </copyright>
 *
 * <file>
 *  Name:       JSIncludeHandler.js
 *  Created:    Jan 26, 2010
 *  $Id: $
 * </file>
 */

// <JSClass Name="com.hyperwave.net.JSIncludeHandler">
//----------------------------------------------------------------------
/**
 * Handles dynamic includes of JS files and retrives JS includes from the head section
 * of the HTML.
 * 
 */

initPackage("com.hyperwave.net");

defineClass ( "com.hyperwave.net.JSIncludeHandler",
              function ( class$ )
{

  class$.constructor = function( theParam )
  {
    if ( theParam == "__proto__")
      return;

  }
  
  /**
   * Returns the loaded scripts of the given document.
   * 
   * @param theDocument: document || null: the document from which
   *    head section the included scripts are retrieved
   */
  class$.static_.getLoadedScripts = function( theDocument ){
    var the_document = theDocument || document;
    var header = the_document.getElementsByTagName("head")[0];
    var tmp_scripts = header.getElementsByTagName("script");
    var loaded_scripts = [];
    for (var s=0; s<tmp_scripts.length; s++ ) {
      if ( tmp_scripts[s].src &&
           tmp_scripts[s].src.length > 0 ) {
        
        // src with host
        loaded_scripts.push(tmp_scripts[s].src);
        // src without host
        loaded_scripts.push(tmp_scripts[s].src.replace(/https?:\/\/[^\/]*/, ""));
      }
    }
    
    return loaded_scripts;
  }

  /**
   * Includes the given scripts into the given document
   *
   * @param theScripst: object[]: the scripts to include
   *   <ul><li>src: string || null: the src of the script - if null text 
                 has to be given</li>
   *       <li>text: string || null: the script itself - ignored if a src is used</li>
   *       <li>callback: function || null: callback function which is call when
                 the script is loaded - only usefull if a scr is used</li>
   *   </ul>
   * @param theDocument: document || null: the document used
   *    to include the given scripts
   * 
   */
  class$.static_.loadScripts = function( theScripts, theDocument ){
    var the_document = theDocument || document;
    
    var header = the_document.getElementsByTagName("head")[0];
    var loaded_scripts = this.getLoadedScripts(the_document);
    var script;
    for (var s=0; s<theScripts.length; s++) {
      if ( theScripts[s].src &&
           theScripts[s].src.length > 0) {
        if (!this.isInArray(theScripts[s].src, loaded_scripts)) {
          
          // needs to be appenden this way, will not be evaluated via prototype...
          script = the_document.createElement('script');
          script.type = 'text/javascript';
          script.src = theScripts[s].src;
          if (theScripts[s].callback) {
            script.onload = theScripts[s].callback;
            script.onreadystatechange = function() {
              if (this.readyState == 'complete') {
                this.onload();
              }
            }
          }
          header.appendChild(script);
          
          // src with host
          loaded_scripts.push(theScripts[s].src);
          // src without host
          loaded_scripts.push(theScripts[s].src.replace(/https?:\/\/[^\/]*/, ""));
          
        }
      } else {
        $(header).insert(
          "<script type='text/javascript'>" + theScripts[s].text + "</script>"
        );
      }
    }
  }
  
  /**
   * Cleans up a given URL by executing ".."-path-operations
   * e.g.
   *    /Site/__config__/xsltemplates/../snippets/scripts/newsticker.js
   *    ==>
   *    /Site/__config__/snippets/scripts/newsticker.js
   * 
   * @param theUrl: string: the url to clean up
   * @return string: the ceaned up url
   */
  class$.static_.cleanupUrl = function(theUrl) {
    var url_array = theUrl.split("/");
    var new_url_array = [];
    for(var i=0; i<url_array.length; i++) {
      if( url_array[i] == ".." && 
          new_url_array.length != "" && 
          new_url_array[new_url_array.length-1] != ".." && 
          new_url_array[new_url_array.length-1] != ".") {
        new_url_array.pop();
      }
      else {
        new_url_array.push(url_array[i]);
      }
    }
    
    return new_url_array.join("/");
  }
  
  /**
   * Determinates wheather a given url is contained in a given array or not.
   * The url is cleaned up with com.hyperwave.net.JSIncludeHandler.static_.cleanupUrl for testing.
   * 
   * @param needle: string: the string to search for
   * @param haystack: array: the array to search in
   * 
   * @return: bool
   */
  class$.static_.isInArray = function(needle, haystack) {
    for(var i=0; i<haystack.length;i++)  {
      
      if(haystack[i] == needle || haystack[i] == this.cleanupUrl(needle)) {
        return true;
      }      
    }
    return false;
  }

});
// </JSClass>

