/**
 *
 * xModify is an extension of the jQuery library that processes requests
 * and update the HTML DOM using the xModify syntax.  Included in xModify is
 * a series of instructions that can be used to update html.
 *
 * insert-after, insert-before, append, set-attribute, set-style
 * set-innerhtml, replace-children, remove-element, remove-attribute
 * replace
 *
 *
 */

/**
 * We need to add the swoosh object to jQuery. This allows developers to 
 * use the jQuery.swoosh object to execute the swoosh functionality.
 * 
 * Developers can also use var swoosh = new Swoosh();
 * 
 */
jQuery.swoosh = new Swoosh();

jQuery.extend(jQuery.swoosh, {
    
   /**
     * Main function to kick off an xModify request.
     * The results of the request will be automatically
     * processed.
     *
     * Look at the documenation for the jQuery.ajax function
     * for information on the parameters.
     *
     * http://docs.jquery.com/Ajax
     *
     */
    xModify: function(ajaxProperties){
        var complete = ajaxProperties.complete, swoosh = this;
        ajaxProperties.complete = function(result, request){
            if (result.responseXML == null){
                ajaxProperties.error.call(this, result, request);
            }else{
                swoosh._processDoc(result.responseXML);
                if (complete){
                    complete.call(this, result, request);
                }
            }
        }
        return jQuery.ajax(ajaxProperties);
    },
	
	/**
	 * This method provides a shortcut for blending html into the 
	 * current html application. Check the jQuery documentation 
	 * specifics on the format and functionality of jQuery's selectors
	 * 
	 * 
	 * Mode can be any of the following append, replace, replace-children
	 * insert-after, insert-before
	 * 
	 * @param {Object} ajaxProperties
	 * @param {Object} select
	 * @param {Object} blendMode
	 */
	blend: function(ajaxProperties, select, blendMode){
        var complete = ajaxProperties.complete;
        var variables = {};
        ajaxProperties.complete = function(result, request){
            if (result.responseText == null){
                ajaxProperties.error.call(this, result, request);
            }else{
				var node = document.createElement(blendMode);
				node.setAttribute("select", select);
				node.appendChild(document.createTextNode(result.responseText));
                jQuery.swoosh._xModifyProcessElement(node, variables);
                if (complete){
                    complete.call(this, result, request);
                }
            }
        }
        return jQuery.ajax(ajaxProperties);
	},
        
	
	//PRIVATE METHODS AND VARIABLES
    /**
     * Will return the modification element.
     */
    _xModifyProcessDoc: function(modElement, variables){
		var variables = {},
			arry = modElement.childNodes, 
			len = arry.length;
	    for (var i = 0; i < len; i++)
			if (arry[i].nodeType == 1)
				this._xModifyProcessElement(arry[i], variables);           
    },

    /**
     * Will return the modification element.
     *
     * Assumes the modifications elements are under XAL
     *
     * MAIN ELEMENT NAMES     
     * insert-after         //This one is roughed out.
     * insert-before        //This one is roughed out.
     * append               //This one is roughed out.
     * set-attribute        //This one is roughed out.
     * set-style            //This one is roughed out.
     * add-class            //This one is roughed out.
     * remove-class         //This one is roughed out.
     * set-innerhtml        //This one is roughed out.
     * replace-children     //This one is roughed out.
     * remove-element       //This one is roughed out.
     * remove-attribute     //This one is roughed out.
     * replace              //This one is roughed out. 
     * 
     * insert-at            //This one is roughed out.  
     *   
     * clone                //This one is roughed out.  
     * create-document      //NOT IMPLEMENTED
     * 
     * variable             //This one is roughed out.
     * attribute            //This one is roughed out.       
     * value-of             //This one is roughed out.
     *
     * TODOs
     *
     * Look into events and styles. Events and styles work
     * as long as the programmer types them in correctly
     *
     * Need to add the must exist attribute
     * Need to add events.
     */
    _xModifyProcessElement: function(modElement, variables){
       var nodeName = jQuery.swoosh._getNodeName(modElement.nodeName), 
	   	   select = modElement.getAttribute("select");
       if (nodeName == "append"){
            jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){    
                jQuery.swoosh._xSelect(select).append(nodeValue);        
			}, variables);
        }else if (nodeName == "set-attribute"){
            jQuery.each(modElement.childNodes, function(){
            	if (this.nodeType == 1){
                    jQuery.swoosh._xSelect(select).attr(this.getAttribute("name"), this.getAttribute("value"));
    			}
            });
        }else if (nodeName == "set-style"){
            jQuery.each(modElement.childNodes, function(){
            	if (this.nodeType == 1){
                    jQuery.swoosh._xSelect(select).css(this.getAttribute("name"), this.getAttribute("value"));
    			}
            });
        }else if (nodeName == "add-class"){
            jQuery.swoosh._xSelect(select).each(function(){
	            jQuery.className.add(this, modElement.getAttribute("name"));
			});
        }else if (nodeName == "remove-class"){
            jQuery.swoosh._xSelect(select).each(function(){
	            jQuery.className.remove(this, modElement.getAttribute("name"));
			});
        }else if (nodeName == "insert-before"){
            jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){
                jQuery.swoosh._xSelect(select).before(nodeValue);        
            }, variables);
        }else if (nodeName == "insert-after"){
            jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){
                jQuery.swoosh._xSelect(select).after(nodeValue);        
            }, variables);
        }else if (nodeName == "replace-children" ||
            nodeName == "set-innerhtml"){
            jQuery.swoosh._xSelect(select).empty();        
            jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){
                jQuery.swoosh._xSelect(select).append(nodeValue);        
            }, variables);
        }else if (nodeName == "remove-element"){
            jQuery.swoosh._xSelect(select).remove();        
        }else if (nodeName == "remove-attribute"){
            jQuery.each(modElement.childNodes, function(){
            		if (this.nodeType == 1){
    				    jQuery.swoosh._xSelect(select).removeAttr(this.getAttribute("name"));
    				}
                });
        }else if (nodeName == "replace"){
            jQuery.swoosh._xSelect(select).each(function(){
                    //if the next sibling doesn't exist then place it at the end
                    //other wise place it before the next sibling.
                    if (this.nextSibling){
                        var node = this.nextSibling;
                        jQuery(this).remove();
                        jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){
                            jQuery(node).before(nodeValue);        
                        }, variables);
                    }else{
                        var node = this.parentNode;
                        jQuery(this).remove();
                        jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){
                            jQuery(node).append(nodeValue);        
                        }, variables);
                    }
                });       
        }else if (nodeName == "insert-at"){
            var index = modElement.getAttribute("index");
            jQuery.swoosh._xSelect(select).each(function(){
                    var beforeNode = null;
                    var node = this;
                    
                    //if the index is more than the number
                    //of children nodes append it.
                    if (this.childNodes.length > index){
                        beforeNode = this.childNodes[index];
                    }
                    
                    jQuery.swoosh._xProcIn(modElement.childNodes, function(nodeValue){
                            if (beforeNode){
                                jQuery(beforeNode).before(nodeValue); 
                            }else{
                                jQuery(node).append(nodeValue); 
                            }       
                        }, variables);
            	});	
        }else if (nodeName == "variable"){
            var name = modElement.getAttribute("name");
            var deep = modElement.getAttribute("deep");
            variables[name] = jQuery.swoosh._xSelect(select).clone(deep);
        }
    },     
    
    /**
     * Called to process the an instruction will loop over each of the
     * instruction's children and fire a callback
     */
    _xProcIn: function(nodes, callback, variables){
        jQuery(nodes).each(function(){
            //make sure there is a nodeValue and this isn't an empty string
            if ((this.nodeType == 3 || this.nodeType == 4) && jQuery.trim(this.nodeValue) != ""){
                callback.call(this, this.nodeValue);
    		}else if (this.nodeType == 1 && jQuery.swoosh._getNodeName(this.nodeName) == "value-of"){
                callback.call(this, variables[this.getAttribute("name")]);
            }else if (this.nodeType == 1 && jQuery.swoosh._getNodeName(this.nodeName) == "clone"){
                var select = this.getAttribute("select");
                var deep = this.getAttribute("deep");
                callback.call(this, jQuery.swoosh._xSelect(select).clone(deep));
    		}else if (this.nodeType == 1){
    		    //got an XML node need to convert it into an HTML node
                callback.call(this, jQuery.swoosh._convertToString(this));
     		}
		});
    }, 
       	
	_xSelect: function(select){
		var obj = jQuery(select);
		return jQuery(jQuery.makeArray(obj));
	}
});

/**
 * Add the processor for the "modifications" elements in the document.
 * This is a necessary becuase the swoosh client just process the document
 */
jQuery.swoosh._modules["modifications"] = jQuery.swoosh._xModifyProcessDoc;





