//
// new SortingTable( 'my_table', {
//   zebra: true,                        // Stripe the table, also on initialize
//   details: false,                     // Has details every other row
//   paginator: false,                   // Pass a paginator object
//   onSorted: function(){},             // Callback to run after sort
//   dont_sort_class: 'nosort',          // Class name on th's that don't sort
//   forward_sort_class: 'forward_sort', // Class applied to forward sort th's
//   reverse_sort_class: 'reverse_sort'  // Class applied to reverse sort th's
// });
//
// The above were the defaults.  The regexes in load_conversions test a cell
// begin sorted for a match, then use that conversion for all elements on that
// column.
//
// Requires mootools Class, Array, Function, Element, Element.Selectors,
// Element.Event, and you should probably get Window.DomReady if you're smart.
//
var SortingTable = new Class({

	Implements: Options,

	options: {
		zebra: true,
		details: false,
		paginator: false,
		onSorted: $empty,
		dont_sort_class: 'nosort',
		forward_sort_class: 'forward_sort',
		reverse_sort_class: 'reverse_sort'
	},

	initialize: function(table, options) {
		this.table = $(table);
		this.setOptions(options);

		this.tbody = this.table.getElement('tbody');
		if (this.options.zebra) {
			SortingTable.stripe_table(this.tbody.getChildren());
		}

		this.headers = this.table.getElement('thead').getElements('th');
		this.headers.each(function(header, index) {
			if (header.hasClass(this.options.dont_sort_class) || !header.get('rel')) {
				return
			}
			header.store('column', index)
			header.addEvent('mousedown', function(evt) {
				this.sort_by_header(evt.target);
				if (this.options.paginator) this.options.paginator.to_page(1);
			}.bind(this));
		},
		this);

		this.load_conversions();
	},

	sort_by_header: function(header) {

        var rows = [];

		var before = this.tbody.getPrevious();
		this.tbody.dispose();

		var trs = this.tbody.getChildren();
		while (row = trs.shift()) {
			row = {
				row: row.dispose()
			};
			if (this.options.details) {
				row.detail = trs.shift().dispose();
			}
			rows.unshift(row);
		}

		if (this.sort_column >= 0 && this.sort_column == header.retrieve('column')) {
			// They were pulled off in reverse
			if (header.hasClass(this.options.reverse_sort_class)) {
				header.removeClass(this.options.reverse_sort_class);
				header.addClass(this.options.forward_sort_class);
			} else {
				header.removeClass(this.options.forward_sort_class);
				header.addClass(this.options.reverse_sort_class);
			}
		} else {
			this.headers.each(function(h) {
				h.removeClass(this.options.forward_sort_class);
				h.removeClass(this.options.reverse_sort_class);
			},
			this);
			this.sort_column = header.retrieve('column');

			if (header.retrieve('conversion_function')) {

				this.conversion_matcher = header.retrieve('conversion_matcher');
				this.conversion_function = header.retrieve('conversion_function');

			} else {

				this.conversion_function = false;

				var type = header.get('rel');

				if (type != '') {

					this.conversions.some(function(conversion) {

						if (conversion.type == type) {
							this.conversion_matcher = conversion.matcher;
							this.conversion_function = conversion.conversion_function;
							return true;
						}

						return false;
					},
					this);

					if (this.conversion_function) {

						header.store('conversion_function', this.conversion_function);
						header.store('conversion_matcher', this.conversion_matcher);
					} else {

                        return;
                    }
				}
			}

			header.addClass(this.options.forward_sort_class);
			rows.each(function(row) {
				var compare_value = this.conversion_function(row);
				row.toString = function() {
					return compare_value;
				};
			},
			this);
			rows.sort();
		}

		var index = 0;
		while (row = rows.shift()) {
			this.tbody.appendChild(row.row);
			if (row.detail) this.tbody.appendChild(row.detail);
			if (this.options.zebra) {
				row.row.className = row.row.className.replace(this.removeAltClassRe, '$1').clean();
				if (row.detail) row.detail.className = row.detail.className.replace(this.removeAltClassRe, '$1').clean();
				if (index % 2) {
					row.row.addClass('alt');
					if (row.detail) row.detail.addClass('alt');
				}
			}
			index++;
		}
		this.tbody.inject(before, 'after');
		//this.fireEvent('sorted', this);
	},

	load_conversions: function() {
		this.conversions = $A([
		// 1.75 MB, 301 GB, 34 KB, 8 TB
		{
			type: 'bytes',
			matcher: /([0-9.]{1,8}).*([KMGT]{1})B/,
			conversion_function: function(row) {
				var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
				cell = this.conversion_matcher.exec(cell);
				if (!cell) {
					return '0'
				}
				if (cell[2] == 'M') {
					sort_val = '1';
				} else if (cell[2] == 'G') {
					sort_val = '2';
				} else if (cell[2] == 'T') {
					sort_val = '3';
				} else {
					sort_val = '0';
				}
				var i = cell[1].indexOf('.')
				if (i == - 1) {
					post = '00'
				} else {
					var dec = cell[1].split('.');
					cell[1] = dec[0];
					post = dec[1].concat('00'.substr(0, 2 - dec[1].length));
				}
				return sort_val.concat('00000000'.substr(0, 2 - cell[1].length).concat(cell[1])).concat(post);
			}
		},
		// Currency
		{
			type: 'currency',
            matcher: /((\d{1}\.\d{2}|\d{2}\.\d{2}|\d{3}\.\d{2}|\d{4}\.\d{2}|\d{5}\.\d{2}|\d{6}\.\d{2}))/,
            conversion_function: function(row) {
				var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
				cell = cell.replace(/[^\d]/g, "");
				return '00000000000000000000000000000000'.substr(0, 32 - cell.length).concat(cell);
			}
		},
		// YYYY-MM-DD, YYYY-m-d
		{
			type: 'en_date',
			matcher: /(\d{4})-(\d{1,2})-(\d{1,2})/,
            conversion_function: function(row) {
				var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
				cell = this.conversion_matcher.exec(cell);
				return cell[1] + '00'.substr(0, 2 - cell[2].length).concat(cell[2]) + '00'.substr(0, 2 - cell[3].length).concat(cell[3]);
			}
		},
		// DD.MM.YYYY
		{
			type: 'date',
            matcher: /^(\d{1,2}).(\d{1,2}).(\d{4})$/,
			conversion_function: function(row) {
				var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
				cell = this.conversion_matcher.exec(cell);
                if ( !cell ) return 0;
                if ( cell[1].length == 1 ) { cell[1] = "0" + cell[1]; }
		        if ( cell[2].length == 1 ) { cell[2] = "0" + cell[2]; }
                var val = cell[3].concat(cell[2]).concat(cell[1]);
                return val;
			}
		},
		// Datum Uhrzeit
		{
			type: 'epoch',
			conversion_function: function(row) {
				var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('title');
				return cell || 0;
			}
		},
		// Numbers
		{
			type: 'number',
			conversion_function: function(row) {
				var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
				cell = cell.replace(/[\D]/,"");
                return '00000000000000000000000000000000'.substr(0, 32 - cell.length).concat(cell);
			}
		},
		// Fallback 
		{
			type: 'fallback',
			conversion_function: function(row) {
				return $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
			}
		},
    	// 
		{
			type: 'structuralunitparent',
			conversion_function: function(row) {
				return $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
			}
		},
        {
			type: 'structuralunit',
			conversion_function: function(row) {
				return $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');
			}
		}]);
	}

});

SortingTable.removeAltClassRe = new RegExp('(^|\\s)alt(?:\\s|$)');
SortingTable.implement({
	removeAltClassRe: SortingTable.removeAltClassRe
});

SortingTable.stripe_table = function(tr_elements) {
	var counter = 0;
	tr_elements.each(function(tr) {
		if (!tr.hasClass('collapsed')) counter++;
		tr.className = tr.className.replace(this.removeAltClassRe, '$1').clean();
		if (counter % 2) tr.addClass('alt');
	});
}

