var bindAttrName = $.bindAttrName = "ish-bind";
var noop = document.createElement('div');

/**
 * Render a template string with corresponding object data.
 * @name  ish.renderTemplate
 * @function
 * @param  {String}   templateString 	A valid HTML template string.
 * @param  {Object}   dataObject 		An object whose values will be bound to the rendered HTML.
 * @return {Node}         The rendered HTML template `Node` which can be inserted into the DOM.
 * @example
 *
 * var template = '<div><p ish-bind="textContent:text"></p></div>'
 * 
 * ish.renderTemplate(template, {text: 'Text has been rendered.'});
 */
$.renderTemplate = function (templateString, dataObject){
	noop.insertAdjacentHTML('afterbegin', templateString);
	var nodesToBind = $('['+bindAttrName+']',noop);
	nodesToBind.forEach(function(node){
		$.renderBind(node, dataObject);
	});
	var rendered = noop.removeChild(noop.firstChild);
	return rendered;
};

/**
 * Update a template Node with a corresponding object data.
 * @name  ish.updateTemplate
 * @function
 * @param  {Node}     updateNode 	The node to update, all child Node's will be updated.
 * @param  {Object}   updateObject 	An object whose values will be updated in the provided HTML.
 * @return {ish}       
 * @example
 *
 * var template = '<div><p ish-bind="textContent:text"></p></div>';
 * var renderedTemplate = ish.renderTemplate();
 * ish.updateTemplate(renderedTemplate, {});
 */
$.updateTemplate = function (updateNode, updates){
	// TODO refactor, should sit outside of this fn
	var updateTemplateEachFn = function(node){ $.renderBind(node, updates); };
	for(var each in updates) {
		$('['+bindAttrName+'*="'+each+'"]', updateNode).forEach(updateTemplateEachFn);
	}
	return $;
};

/**
 * Render the values given in the dataObject to a single node.
 * @name  ish.renderBind
 * @function
 * @param  {String}   domNode 		An exisiting DOM Node.
 * @param  {Object}   dataObject 	An object whose values will be bound to the rendered HTML.
 * @return {Node}     The rendered HTML template `Node` which can be inserted into the DOM.
 * @example
 *
 * var template = '<p ish-bind="textContent:text"></p>'
 * var node = ish.renderTemplate(template, {text:'text has been rendered'});
 * // you would usualy use ish.updateTemplate, this is just for exmaple
 * ish.renderBind(node, {text: 'text has been updated text'});
 */
$.renderBind = function (domNode, obj) {    
    var binds = domNode.attr(bindAttrName).split(" ");
    for (var i = 0; i < binds.length; i++) {
		var bind = binds[i].split(":");
	    var domAttribute = bind[0].trim(); // the attribute on the DOM element
	    var propertyAttribute = bind[1].trim(); // the attribute the object
	    var targetValue = domNode[0][domAttribute];
	    var resolvedPathValue = $.resolveObjectPath(obj, propertyAttribute);
	    if(resolvedPathValue && targetValue !== resolvedPathValue) domNode[0][domAttribute] =  resolvedPathValue;
    }
};

/**
 * Whilst the ish.renderBind method renders values to the DOM, ish.bindToObject sets the values of the binds DOM attributes in the target object.
 * @name  ish.bindToObject
 * @function
 * @param  {String}   domNode 		An exisiting DOM Node.
 * @param  {Object}   dataObject 	An object whose values will be bound to the rendered HTML.
 * @return {ish}      Chainable with other ish methods.
 * @example
 *
 * var template = '<p ish-bind="textContent:text"></p>'
 * var node = ish.renderTemplate(template, {text:'text has been rendered'});
 * // you would usualy use ish.updateTemplate, this is just for exmaple
 * ish.renderBind(node, {text: 'text has been updated text'});
 */
$.bindToObject = function (domNode, obj){
    var binds = domNode.attr(bindAttrName).split(" ");
	for (var i = 0; i < binds.length; i++) {
		var bind = binds[i].split(":");
	    var domAttribute = bind[0].trim(); // the attribute on the DOM element
	    var propertyAttribute = bind[1].trim(); // the attribute the object
	    var targetValue = domNode[0][domAttribute];
	    if(targetValue) $.setPathByString(obj, propertyAttribute, targetValue);
	}
	return this;
};