/*
 * <copyright>
 *  Copyright (c) Hyperwave GmbH 2010
 * </copyright>
 *
 * <file>
 *  Name:       XSLTransformationLoader.js
 *  Created:    Sept 07, 2010
 *  $Id: $
 * </file>
 */

//----------------------------------------------------------------------
initPackage("com.hyperwave.wcm");
initPackage("com.hyperwave.wcm.csjs");

// <JSClass Name="com.hyperwave.wcm.csjs.components.XSLTransformationLoader">
defineClass ( "com.hyperwave.wcm.csjs.components.XSLTransformationLoader",
              function ( class$ )
{
  /**
   * Private constructor. Use <code>static_.getInstance</code> instead.
   * @see com.hyperwave.wcm.csjs.components.XSLTransformationLoader#static_.getInstance
   */
  class$.constructor = function( aParam )
  {
    if ( aParam == "__proto__")
      return;

    class$.super_.constructor.call ( this );
    
    this.contentElementId_ = aParam.theElementId;
    this.contentString_ = "";
    this.xmlUrl_ = null;
    this.xslUrl_ = null;
    this.callback_ = null;
    this.setCurrentTimestamp();
    
  };
  
  class$.setCurrentTimestamp = function() {
  	this.currentTimestamp_ = new Date().getTime();
  };
  
  class$.static_.XML_URL_ATTRIBUTE_NAME = "data-xml";
  class$.static_.XSL_URL_ATTRIBUTE_NAME = "data-xsl";
  class$.static_.XSL_CALLBACK_ATTRIBUTE_NAME = "data-callback";
  class$.static_.CONTENT_CONTAINER_CSS_CLASS = "hw_dynamic_xml_content";
  
  class$.static_.instances_ = [];
  class$.static_.getInstance = function(id) {
    if(!this.instances_[id]) {
      this.instances_[id] = new com.hyperwave.wcm.csjs.components.XSLTransformationLoader({theElementId: id});
    }
    return this.instances_[id];
  };
  
  class$.static_.init = function(id, callback) {
  	try {
	  	var loader = com.hyperwave.wcm.csjs.components.XSLTransformationLoader.static_.getInstance(id);
	  	loader.setParametersByAttributes();
	  	loader.display();
	  	loader.executeCallback();
  	}
  	catch(e) {
  		// silent catch
  	}
  };
  
  class$.static_.registerToOnload = function(id, callback, count){
	  if (!count) {
	    count = 1;
	  }
	  else {
	    count++;
	  }
	  
	  if(typeof utiljs_registerWindowOnloadFunction == "function") {
	    utiljs_registerWindowOnloadFunction(function() {
	    	com.hyperwave.wcm.csjs.components.XSLTransformationLoader.static_.init(id, callback);
	    });
	  } 
	  else {
	    if (count <= 10) {  // stop trying after 10 seconds
	      com.hyperwave.wcm.csjs.components.XSLTransformationLoader.static_.registerToOnload.delay(1, id, callback, count);
	    }
	  }
	};
	
	/**
   * Factory method to retrieve the client specific XML wrapper class.
   * Returns wrapper class for either Internet Explorer or Firefox.
   * @param xmlURI: string: the URI specifying the XML file to transform
   * @param decorate: boolean: flag indicating that the plain XMLWrapper should
   *   be decorated with save and undo/redo functionality.
   * @return com.hyperwave.xml.AbstractXMLWrapper: the browser specific
   *   wrapper instance.
   * @pattern FactoryMethod
   */
  class$.getXMLWrapper = function( xmlURI, decorate ){
    var wrapper = null;
    if(typeof ActiveXObject != "undefined"){
      wrapper = com.hyperwave.xml.InternetExplorerXMLWrapper.static_.getInstance( xmlURI );
    }
    else {
      wrapper = com.hyperwave.xml.MozillaXMLWrapper.static_.getInstance( xmlURI );
    }
    if(decorate){
      // add decorator to remove hidden link markup before storing at server
      wrapper = new com.hyperwave.wcm.csjs.decorators.WrapperHiddenLinkDecorator( wrapper );
    }
    return wrapper;
  };
	
	class$.setParametersByAttributes = function() {
		this.setXMLUrl($(this.contentElementId_).readAttribute(this.static_.XML_URL_ATTRIBUTE_NAME));
		this.setXSLUrl($(this.contentElementId_).readAttribute(this.static_.XSL_URL_ATTRIBUTE_NAME));
		this.setCallback($(this.contentElementId_).readAttribute(this.static_.XSL_CALLBACK_ATTRIBUTE_NAME));
	};
	
	class$.reset = function() {
		this.contentString_ = null;
		this.setParametersByAttributes();
		this.display();
	}
	
	class$.loadContent = function() {
		if(this.xmlUrl_ && this.xslUrl_) {
			var wrapper = this.getXMLWrapper(this.xmlUrl_ + "&ts=" + this.currentTimestamp_);
			var str = wrapper.transformToString(this.xslUrl_);
			
			// remove the wrapper div (<div id="wrapper"><ul></ul></div> => <ul></ul>)
			str = str.replace(/(^<[^>]*>|<\/[^>]*>$)/g, "");
			
	    this.contentString_ = str;
		}
  };
  
  class$.display = function() {
  	if(!this.contentString_) {
  		this.loadContent();
  	}
  	$(this.contentElementId_).update(this.contentString_);
  	this.initSortButtons();
  };
  
  class$.initSortButtons = function() {
  	$(this.contentElementId_).select("th").each(function(th){
  		if(th.readAttribute("data-sortby") != "") {
	  		th.select("span").each(function(span){
		  	  span.observe('click', this.sortButtonOnClick.bind(this));
	  		}.bind(this));
  		}
  	}.bind(this));
  };
  
  class$.sortButtonOnClick = function(event) {
  	var element = Event.element(event).up("th");
  	Event.stop(event);
  	
  	if(com.hyperwave.wcm.csjs.components.AbstractComponent) {
  	  extrinsic = element.up('.' + com.hyperwave.wcm.csjs.components.AbstractComponent.static_.HW_EDIT_CLASS);
  	  com.hyperwave.wcm.csjs.components.AbstractComponent.static_.triggerEvent(extrinsic, 'click');
  	}
  	
    sortby = element.readAttribute("data-sortby");
    if(element.hasClassName('sorted')) {
    	if(!element.hasClassName('fixdirection')) {
    		if(element.hasClassName('asc')) {
	        sortby+= ";desc";
	      }
	      else {
	        sortby+= ";asc";
	      }
    	}
    }
    // else -> dont't care about the direction, it's handled on the server
    
    this.changeXMLUrlParameter({sortby: sortby});
    this.reload();
  }
  
  class$.reload = function() {
  	this.setCurrentTimestamp();
  	this.loadContent();
  	this.display();
  };
  
  class$.changeXMLUrlParameter = function(theParameters) {
  	var new_parameter = [];
    var url_array = this.xmlUrl_.split("?");
    if(url_array[1]) {
    	var parameter_array = url_array[1].split("&");
    	for(var i=0; i<parameter_array.length; i++) {
    		var param = parameter_array[i].split("=");
    		if(theParameters[param[0]] || theParameters[param[0]] === "") {
    			new_parameter.push(param[0] + "=" + encodeURIComponent(theParameters[param[0]]));
    		}
    		else {
    			new_parameter.push(parameter_array[i]);
    		}
    	}
    }
    this.xmlUrl_ = url_array[0] + "?" + new_parameter.join("&");
  };
  
  class$.setXMLUrl = function(url) {
  	
  	// encode parameters
  	var new_parameter = [];
  	var url_array = url.split("?");
    if(url_array[1]) {
      var parameter_array = url_array[1].split("&");
      for(var i=0; i<parameter_array.length; i++) {
        var param = parameter_array[i].split("=");
        new_parameter.push(param[0] + "=" + encodeURIComponent(param[1]));
      }
    }
    url = url_array[0] + "?" + new_parameter.join("&");
    
  	this.xmlUrl_ = url;
  };
  
  class$.setXSLUrl = function(url) {
  	this.xslUrl_ = url;
  };
  
  class$.setCallback = function(callback) {
    this.callback_ = callback;
  };
  
  class$.executeCallback = function() {
    if(this.callback_) {
    	eval(this.callback_);
    }
  };
});
// </JSClass>


