/**
 * Utility class holds convenience methods for use across all CG shared
 * libraries
 * 
 * @requires jQuery
 */

require('jQuery', 'CG.Util');

(function($) {

	// ------------------------------------------------
	// Extend jQuery functionality
	// ------------------------------------------------
	
	/**
	 * jQuery plugin to reverse the order of the elements
	 * 
	 * Freaking Prototype...
	 * 
	 * @return jQuery
	 */
	$.fn.reverse = typeof(Prototype) != 'undefined' && Array.prototype._reverse ? []._reverse : [].reverse;

	/**
	 * jQuery plugin to get data from HTML5 data attributes
	 * 
	 * @param String key The name of the data key.  The attribute should 
	 * 						be defined in the attribute using this notation:
	 * 						data-someattribute="somevalue"
	 * @return Object Returns undefined (if the attribute doesn't exist)
	 */
	$.fn.getData = function(key) {
		var att = this.attr('data-' + key), data;
		
		if(att) {
			try {
				data = eval('(' + att + ')');
			} catch (e) {
				data = att;
			};
		}
		
		return data;
	};
	
	/**
	 * jQuery plugin to truncate content for the all matched elements
	 * 
	 * @param Int length The number of characters before content is truncated
	 * @param String elips The string to indicate content has been truncated
	 * @return jQuery The original jQuery object
	 */
	$.fn.truncate = function(length, elips) {
		var length = length || 20,
			elips = elips || '...';

		return this.each(function() {
			var obj = $(this),
				content = obj.text();
			
			if(content.length > length) {
				obj.text(content.substr(0, length) + elips);
			}
		});
	};
	
	$.extend({
		
		/**
		 * JQuery plugin to apply URL Encoding to a String.
		 * 
		 * @param String url The String to URL Encode.
		 * @return String The Encoded URL.
		 * @author matt
		 */
		URLEncode: function(url){
			var encoding = '',
				charStep = 0,
				search = /(^[a-zA-Z0-9_.]*)/;
			
			url = url.toString();
			
			while (charStep < url.length) {
				var result = search.exec(url.substr(charStep));
				
				if(result != null && result.length > 1 && result[1] != '') {
					encoding += result[1];
					charStep += result[1].length;
				}
				else {
					if(url[charStep] == ' ')
						encoding += '+';
					else {
						var stepCharCode = url.charCodeAt(charStep),
							hexCode = stepCharCode.toString(16);
						
						encoding += '%' + (hexCode.length < 2 ? '0' : '') + hexCode.toUpperCase();
					}
					
					charStep++;
				}
			}
			
			return encoding;
		},
		
		/**
		 * JQuery plugin to decode a String that has been URL Encoded.
		 * 
		 * @param String encoding The String to URL Decode.
		 * @return String The Decoded URL.
		 * @author matt
		 */
		URLDecode: function(encoding) {
			var url = encoding,
				search = /(%[^%]{2})/;
			
			while ((result = search.exec(url)) != null && result.length > 1 && result[1] != '') {
				var charCode = parseInt(result[1].substr(1), 16),
					newChar = String.fromCharCode(charCode);
				
				url = url.replace(result[1], newChar);
			}
			
			return url;
		},
	
		/**
		 * A convenience method to turn a full URL into a relative path based on the current window location.
		 * 
		 * @param String url The URL to obtain the relative path from.
		 * @return String The relative path of URL.
		 * @author matt
		 */
		getRelativePath: function(url) {
			return url.replace(window.location.protocol + '//' + window.location.hostname, '');
		},
	
		/**
		 * A convenience method to a single cross-browser version of the current window location hash.
		 * 
		 * @return String The current window location hash.
		 * @author matt
		 */
		getHash: function() {
			return $.URLDecode(window.location.hash.replace('#', ''));
		}
	});
	
	// ------------------------------------------------
	// Extend Function prototype
	// ------------------------------------------------

	/**
	 * A convenience method for Class Inheritance in JavaScript.
	 * 
	 * Usage:
	 * 	function Shape() { this._someVar; };
	 * 	function Circle() { _init() };
	 * 	Circle.Inherits(Shape);
	 * 	Circle.prototype._init = function() { console.log(this._someVar); };
	 * 
	 * @param Object parent The Class to Inherit from.
	 * @return Object The child Class with Inheritance from the parent Class.
	 * @author matt 
	 */
	Function.prototype.Inherits = function( parent )
	{
		this.prototype = new parent();
		this.prototype.constructor = this;
	};
	
	// ------------------------------------------------
	// Extend String prototype
	// ------------------------------------------------
	
	/**
	 * Format a number with grouped thousands
	 * 1,000
	 *
	 * Credit PHP.JS
	 * http://phpjs.org/functions/number_format
	 * License: MIT+GPL
	 *
	 * example 1: number_format(1234.56);
	 * returns 1: '1,235'
	 * example 2: number_format(1234.56, 2, ',', ' ');
	 * returns 2: '1 234,56'
	 * example 3: number_format(1234.5678, 2, '.', '');
	 * returns 3: '1234.57'
	 * example 4: number_format(67, 2, ',', '.');
	 * returns 4: '67,00'
	 * example 5: number_format(1000);
	 * returns 5: '1,000'
	 * example 6: number_format(67.311, 2);
	 * returns 6: '67.31'
	 * example 7: number_format(1000.55, 1);
	 * returns 7: '1,000.6'
	 * example 8: number_format(67000, 5, ',', '.');
	 * returns 8: '67.000,00000'
	 * example 9: number_format(0.9, 0);
	 * returns 9: '1'
	 * example 10: number_format('1.20', 2);
	 * returns 10: '1.20'
	 * example 11: number_format('1.20', 4);
	 * returns 11: '1.2000'
	 * example 12: number_format('1.2000', 3);
	 * returns 12: '1.200'
	 */
	String.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
	    // version: 906.1806
	    var n = parseInt(this, 10), prec = decimals;
	    if(isNaN(n)) {return this;};

	    var toFixedFix = function (n,prec) {
	        var k = Math.pow(10,prec);
	        return (Math.round(n*k)/k).toString();
	    };

	    n = !isFinite(+n) ? 0 : +n;
	    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
	    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
	    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;

	    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec); //fix for IE parseFloat(0.55).toFixed(0) = 0;

	    var abs = toFixedFix(Math.abs(n), prec);
	    var _, i;

	    if (abs >= 1000) {
	        _ = abs.split(/\D/);
	        i = _[0].length % 3 || 3;

	        _[0] = s.slice(0,i + (n < 0)) +
	              _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
	        s = _.join(dec);
	    } else {
	        s = s.replace('.', dec);
	    }

	    var decPos = s.indexOf(dec);
	    if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
	        s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
	    }
	    else if (prec >= 1 && decPos === -1) {
	        s += dec+new Array(prec).join(0)+'0';
	    }
	    return s;
	};
	
})(jQuery);