
/**
 * The Electric Pulp global namespace
 * Create functions as Methods under this Object
 * @constructor
 */
var EP = window.EP || {};

EP.Element = {
	/**
	 * Surrounds a node with a new node with optional class and id 
	 *
	 * EP.Element.surround(myElement); Defaults to creating a div
	 * EP.Element.surround(myElement, {tagName: 'div', tagClass: 'newClass', tagID: 'newID'});
	 *
	 * @param  {String || Object} element ID or HTML node
	 * @param  {Object}			  options for tagName, tagClass and tagID
	 *			|| @prop tagName
	 *			|| @prop tagClass
	 *			|| @prop tagID
	 * @return {Object}    				  new (surrounding) HTML node
	 */
	surround: function(element) {
		var element = $(element);
		var options = Object.extend({
      		  tagName: 'DIV'
    	}, arguments[1] || {});
	
		var surround 		= document.createElement(options.tagName);
		surround.className 	= (options.tagClass) ? options.tagClass : null;
		surround.id			= (options.tagID) ? options.tagID : null;
		
		surround.appendChild(element.cloneNode(true));
		var newNode = element.parentNode.insertBefore(surround,element);
		element.remove();
		return newNode;
	},
	/**
	 * Returns an anscestor object by TagName of an element
	 *
	 * EP.Element.findElement('myNodeID','TABLE');
	 * EP.Element.findElement(myNode,'TABLE');
	 *
	 * Either of the above returns an HTML ancestor node
	 *
	 * @param  {String || Object} element ID or HTML node
	 * @param  {String}			  	tagName ancestor HTML nodeName
	 * @return {Object}    			HTML node
	 */
	findElement: function(element, tagName) {
		var element = $(element);
	
		while (element.parentNode && (!element.tagName || 
			(element.tagName.toUpperCase() != tagName.toUpperCase())))
			element = element.parentNode;
			
			return $(element);
	},
	
	/**
	 * Returns an integer of where the element is in a node list
	 *
	 * EP.Element.getDOMPosition('myNodeID');
	 * EP.Element.getDOMPosition(myNode);
	 *
	 * Either of the above would return an integer showing where
	 * the element is in a nodeList (0 based)
	 *
	 * @param  {String || Object} 	element ID or HTML node
	 * @return {Integer}            0 based position of node
	 */
	getDOMPosition: function(element) {
		element = $(element);
		var parent   = element.parentNode;
		var siblings = parent.getElementsByTagName(element.tagName);
		for(var i=0; i<siblings.length; i++) {
			if(element == siblings[i]) break;
		}
		return i;
	}
};

// Give EP.Element all the properties of Element
Object.extend(EP.Element, Element);

EP.document = {
	/**
	 * Finds all elements containing a certain attribute
	 *
	 * document.getElementsByAttribute('href');
	 * document.getElementsByAttribute('href','footer');
	 *
	 * Either of the above would return an array of element
	 * which contain the attribute 'href'
	 *
	 * @param  {String}					attribute name		
	 * @param  {String || Object} 		element ID or HTML node, within which to search
	 * @return {Array}					elements containing the attribute
	 */
	getElementsByAttribute: function(attribute, parentElement) {
		var children = ($(parentElement) || document.body).getElementsByTagName('*');
		//in inject function, elements refers to the empty array that is the first
		// argument in the inject function. child is the value of each index in the
		// original children array.
		return $A(children).inject([], function(elements, child) {
			if (child.getAttribute(attribute))
			elements.push(Element.extend(child));
			return elements;
		});
	}
};

// Extend pluck method to try to return an attribute value first
// if not just return a property value.
Object.extend(Enumerable, {
  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value.getAttribute ? value.getAttribute(property) || value[property] : value[property]);
    });
    return results;
  }
});

// Extend the Array object with our new pluck method
Object.extend(Array.prototype, Enumerable);

// Convenience function get all the values of anything matching the attribute
EP.$P = function(attribute) {
	return EP.document.getElementsByAttribute(attribute).pluck(attribute);
};

EP.WindowProperties = {
	/**
	 * Returns an integer of amount the page has been scrolled horizontally
	 *
	 * EP.WindowProperties.getHorizontalScroll();
	 *
	 * @param  NONE
	 * @return {Integer}				Number of pixels scrolled 
	 *									(remember to append 'px' if you're using this number to set position)
	 */
	getHorizontalScroll: function() {
		return window.pageXOffset 
			|| document.documentElement.scrollLeft 
			|| document.body.scrollLeft 
			|| 0;
	},
	
	/**
	 * Returns an integer of amount the page has been scrolled vertically
	 *
	 * EP.WindowProperties.getVerticalScroll();
	 *
	 * @param  NONE
	 * @return {Integer}				Number of pixels scrolled 
	 *									(remember to append 'px' if you're using this number to set position)
	 */
	getVerticalScroll: function() {
		return window.pageYOffset 
			|| document.documentElement.scrollTop 
			|| document.body.scrollTop 
			|| 0;
	},
	
	/**
	 * Returns an object containing the dimensions of a page in pixels, 
	 * including padding but not the horizontal scrollbar height, border, margin
	 * or any content that is scrolled off the page.
	 *
	 * var bSize = EP.WindowProperties.getBrowserSize();
	 * console.log(bSize.width);
	 * console.log(bSize.height);
	 *
	 * @param  NONE
	 * @return {Object}                  Object containing dimensions of a page
	 *			|| @prop width
	 *			|| @prop height
	 */
	getBrowserSize: function() {
		var bWidth;
		var bHeight;
		if(document.documentElement && document.documentElement.clientHeight) {
			bWidth = document.documentElement.clientWidth - 8;
			bHeight = document.documentElement.clientHeight;
		} else {
			// I wonder if we can get rid of this (IE and FF support documentElement (opera? safari?))
			bWidth = document.body.clientWidth;
			bHeight = document.body.clientHeight;
		}
		return {width: bWidth, height: bHeight};
	},
	
	/**
	 * Returns an object containing the dimensions of a page in pixels, 
	 * including the element borders, the element horizontal padding 
	 * the element vertical scrollbar (if present, if rendered) and 
	 * any content scrolled off the screen
	 *
	 * var bSize = EP.WindowProperties.getContentSize();
	 * 
	 * Don't use ignore yet, I'm changing it to make it more clear
	 * var bSize = EP.WindowProperties.getContentSize('footer');
	 * console.log(bSize.width);
	 * console.log(bSize.height);
	 *
	 * @param  {String || Object}		ID or Element object that should be ignored 
	 *									when calculating dimensions			
	 * @return {Object}					Object containing dimensions of a page
	 *			|| @prop width
	 *			|| @prop height
	 */
	getContentSize: function(ignore) {
	    if(ignore) {
	        $(ignore).hide();
	    }
		var bodyHeight;
		var bodyWidth;
		if (window.innerHeight && window.scrollMaxY) {
			bodyHeight = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){
			bodyHeight = document.body.scrollHeight;
		} else {
			bodyHeight = document.body.offsetHeight;
		} 
		if (window.innerWidth && window.scrollMaxX) {
			bodyWidth = document.body.scrollWidth + window.scrollMaxX;
		} else if (document.body.scrollWidth > document.body.offsetWidth){
			bodyWidth = document.body.scrollWidth;
		} else {
			bodyWidth = document.body.offsetWidth;
		}
		var browserSize = Simpltry.WindowProperties.getBrowserSize();
		if(ignore) {
		    ignore.show();
		}
		var calculatedHeight = browserSize.height;
		var calculatedWidth = browserSize.width;
		
		if(bodyWidth > calculatedWidth) calculatedWidth = bodyWidth;
		if(bodyHeight > calculatedHeight) calculatedHeight = bodyHeight;
		return {height: calculatedHeight, width: calculatedWidth};
	}
};
