/**
 * @author Arshinov Maxim http://oberegie.ru/contact.aspx#maxim
 */
(function($){
    /* Глобальные переменные для сортировки Шелла, которую кто-то писал через одно место */
    var col = 0;
    var parent = null;
    var items = new Array();
    var N = 0;
	
	var noTextMessage = 'Не заполнено';
	
    var isort = function(m, k, desc){
        for (var j = m + k; j < N; j += k) {
            for (var i = j; i >= k && compare(get(i), get(i - k), desc); i -= k) {
                exchange(i, i - k);
            }
        }
    };
    
    var get = function(i){
		var node = items[i].getElementsByTagName("TD")[col];
		if(!node){
			return "";
		}
        var retval = $(node).text();
		
        if (parseInt(retval) == retval) 
            return parseInt(retval);
        return retval;
    }
    
    var compare = function(val1, val2, desc){
        return (desc) ? val1 > val2 : val1 < val2;
    }
    
    var exchange = function(i, j){
	    if (i == j + 1) {
            parent.insertBefore(items[i], items[j]);
        }
        else {
            if (j == i + 1) {
                parent.insertBefore(items[j], items[i]);
            }
            else {
                var tmpNode = parent.replaceChild(items[i], items[j]);
                if (typeof(items[i]) == "undefined") {
                    parent.appendChild(tmpNode);
                }
                else {
                    parent.insertBefore(tmpNode, items[i]);
                }
            }
        }
    };
    
    var sortTable = function(table, n, desc){
        parent = table
        col = n;
        var k;
		if (parent.nodeName != "TBODY") 
            parent = parent.getElementsByTagName("TBODY")[0];
        if (parent.nodeName != "TBODY") 
            return false;
        
		items = parent.getElementsByTagName("TR");
       	N = items.length; // Опорный элемент
        
		// shell sort
        if ((k = Math.floor(N / 5)) > 7) {
            for (var m = 0; m < k; m++) 
                isort(m, k, desc);
        }
        
        if ((k = Math.floor(N / 7)) > 7) {
            for (var m = 0; m < k; m++) 
                isort(m, k, desc);
        }
        
        for (k = 7; k > 0; k -= 2) {
            for (var m = 0; m < k; m++) {
				isort(m, k, desc);
			}
        }
    };
    
	var shellSort = function(arr){
		var j;
		var step = arr.length / 2;
		while (step > 0) {
			for (var i = 0; i < (arr.length - step); i++) {
				j = i;
				while ((j >= 0) && (arr[j] > arr[j + step])) {
					var tmp = arr[j];
					arr[j] = arr[j + step];
					arr[j + step] = tmp;
					j--;
				}
			}
			step = step / 2;
		}
		return arr;
	}
	
    var createSorter = function(element, col, table){
		var select = $(document.createElement('select'));
		
		select.bind('change', function(){
			//alert('change');
			selectItems(table, select.find('option[selected]').val());
			select.parent().remove();
			delete select;
		});
		
		select.bind('blur', function(){
			//return;
			select.parent().remove();
			delete select;
		});
		
		var res = [];
		var tmp = '';
		table.find('tbody').find('tr').each(function(){
			//alert(col + " " + $(this).find('td').length);
			tmp = $($(this).find('td').get(col)).text() ;
			if(res.indexOf(tmp) == -1){
				res.push(tmp);
			}
		});
		res = shellSort(res);
		select.append($(document.createElement('option')));
		for(var i = 0; i < res.length; i++){
			tmp = $(document.createElement('option')).text(res[i] ? res[i] : noTextMessage);
			select.append(tmp);
		}
		
		element.append($(document.createElement('div')).addClass('sortSelect').
			append(select));
		select.focus();
	};
    
	var selectItems = function(table, val){
		if(val == noTextMessage)val = '';
		
		table.find('td').hide().each(function(){
			var tmp;
			if((tmp = $(this)).text() == val){
				tmp.parent('tr').find('td').show();
			}
		});
	}
	
    $.fn.tableSorter = function(options){
        var opts = $.extend({
            asc: '&uarr;',
            desc: '&darr;',
			thFilter: true,
            ignore: [],
			showAll: 'Показать все'
        }, options);
		var target = $(this);
		var _target = this.find('tbody').get(0);
			
        return $(this).each(function(){
            var me = $(this);
            if (!me.is('table'))return;
            me.addClass('tableSorter');
			
			var processSort = function(col, desc, el){
				target.find('.sortButton').
					removeClass('sortActive');
				el.addClass('sortActive');
				sortTable(_target, col, desc);
			}
			
			var _index = 0;
			me.find('th').each(function(){
                var __index = _index;
				var sortDesc = $(document.createElement('span')).addClass('sortDesc').
					addClass('sortButton').html(opts.desc).attr('title', 'По убыванию');
				var sortAsc = $(document.createElement('span')).addClass('sortAsc').
					addClass('sortButton').html(opts.asc).attr('title', 'По возрастанию');
				
				sortDesc.click(function(){
					processSort(__index, true, $(this));
				});
				
				sortAsc.click(function(){
					processSort(__index, false, $(this));
				});
				var _th = $(this); 
				
                
				if(opts.thFilter){
					var span = $(document.createElement('span')).addClass('sortHeader').
						html(_th.html());
					span.click(function(){
						target.find('th').find('select').parent('div.sortSelect').remove();
						createSorter(_th, __index, target);
					});
					_th.empty().append(span);
				}
				_th.append(sortDesc).append(sortAsc);
				_index++;
            });
			
			if (opts.thFilter) {
				var showAll = $(document.createElement('div')).addClass('sortShowAll').html(opts.showAll);
				showAll.click(function(){
					//alert('!');
					target.find('td').show();
				});
				target.before(showAll);
			}
        });
    };
}
(jQuery));
