/**
 * @name Grid
 * @author Rick Hopkins
 * @classDescription
 * Sort table data
 * MIT-style License.
 */

var Grid = new Class({
	/** define some variables */
	table: false, 
	headers: [], 
	data: [], 
	
	/**
	 * Initialize the object
	 */
	initialize: function(table){
		this.table = table;
		this.getHeaders();
		this.getData();
		this.stripe();
		return this;
	}, 
	
	/**
	 * Get the headers
	 */
	getHeaders: function(){
		if (!this.table.getFirst('thead')) return false;
		this.headers = this.table.getFirst('thead').getElements('tr th');
		this.headers.each(function(h, index){
			h.store('asc', false);
			if (h.hasClass('sort')) h.addEvent('click', function(){
				this.headers.each(function(h2){ h2.removeClass('asc').removeClass('desc'); });
				if (h.retrieve('asc')){
					h.store('asc', false);
					h.addClass('desc');
				} else {
					h.store('asc', true);
					h.addClass('asc');
				}
				this.sort(index);
			}.bind(this));
		}, this);
	}, 
	
	/**
	 * Get the table data
	 */
	getData: function(){
		this.data = [];
		rows = this.table.getFirst('tbody').getChildren();
		for (j = 0; j < rows.length; j++){
			if (rows[j + 1] && rows[j + 1].hasClass('row-child')){
				rows[j].store('child', rows[j + 1]);
				this.data.push(rows[j]);
				j++;
			} else this.data.push(rows[j].store('child', false));
		}
	}, 
	
	/**
	 * Sort the data
	 * @param int index
	 */
	sort: function(index){
		data = [];
		sortType = this.headers[index].getProperty('axis');
		asc = this.headers[index].retrieve('asc');
		if (this.data.length > 0) this.data.each(function(row, i){
			cells = row.getElements('td');
			if (cells.length < this.headers.length) return false;
			value = (cells[index].getProperty('axis') ? cells[index].getProperty('axis') : cells[index].get('text'));
			if (sortType == 'int' || sortType == 'float'){
				if (value.contains('$') || value.contains(',')) value = value.replace(/\$/g, '').replace(/,/g, '').toFloat();
				else value = value.toFloat();
			} else if (sortType == 'date'){
				if (value.contains('-')){
					str = value.split('-');
					value = str[1] + '/' + str[2] + '/' + str[0];
				}
				value = Date.parse(value);
			}
			data.push({'index': i, 'value': value, 'row': row});
		}, this);
		
		if (sortType == 'int' || sortType == 'float' || sortType == 'date') data.sort(this.sortNumeric);
		else data.sort(this.sortCaseInsensitive);
		if (!asc) data.reverse();
		
		this.data = [];
		data.each(function(d, i){
			this.data.push(d.row);
		}, this);
		
		/** stripe the rows */
		this.stripe();
	}, 
	
	/**
	 * Sort Numerical Values
	 * @param object a
	 * @param object b
	 */
	sortNumeric: function(a, b){
		if ($type(a.value) != 'number') a.value = 0;
		if ($type(b.value) != 'number') b.value = 0;
		return a.value - b.value;
	}, 
	
	/**
	 * Sort String Values
	 * @param object a
	 * @param object b
	 */
	sortCaseInsensitive: function(a, b){
		a.value = a.value.toLowerCase();
		b.value = b.value.toLowerCase();
		if (a.value == b.value) return 0;
		if (a.value < b.value) return -1;
		return 1;
	}, 
	
	/**
	* Stripe the rows of the passed table elements
	*/
	stripe: function()
	{
		this.data.each(function(row, i){
			row.removeClass('r1').removeClass('r2');
			this.table.getElement('tbody').adopt(row.addClass((i % 2 == 0 ? 'r1' : 'r2')));
			if (row.retrieve('child')) this.table.getElement('tbody').adopt(row.retrieve('child'));
		}, this);
	}
});

/** find all sortable tables */
window.addEvent('domready', function(){
	$$('div.grid').getElement('table').each(function(t){
		new Grid(t);
	});
});