var CoolTable = new Class ({
	/**
	 *	Konstruktor, inicjalizacja klasy, zmiennych
	 *	@param string el
	 *	@param object opt
	 *	@return void
	 */
	initialize : function(el, opt) {
		this.element = $(el);
		this.headers = [];
		this.rows = [];
		
		this.currentPage = 1;
		this.pagesAll = 1;
		this.rowsFrom = null;
		this.rowsTo = null;
		
		this.lang = Object.extend({
			quickSearchText: 'Szybkie wyszukiwanie',
			firstText: '‹‹ Pier',
			prevText: '‹ Poprz',
			nextText: 'Nast ›',
			lastText: 'Ost ››',
			ofText: 'z'
		});
		
	//	this.sorts = Object.extend({
	//		sortD: 'asc'
	//	});
		
		//Kolejnosc liter alfabetu (sortowanie) (UTF-8!)
		this.sortOrder = " !\"#$%&'()*+,-./0123456789:;<=>?@AaĄąBbCcĆćDdEeĘęFfGgHhIiJjKkLlŁłMmNnŃńOoÓóPpQqRrSsŚśTtUuVvWwXxYyZzŹźŻż[\\]^_`{|}~";
		
		//Opcje
		this.options = Object.extend({
			useQuickSearch: true,
			quickSearchId: 'ct-quicksearch_field',
			usePaging: true,
			rowsPerPages: 20,
			tableWidth: '500',
			useAjax: false,
			ajaxFile: null
		}, opt || {});
		
		this._makeTableFromTable(el);
		
		//przypisanie zdarzenia dla pola szybkiego wyszukiwania
		if (this.options.useQuickSearch) this._bindQuickSearch();
		
		this._makePages();
	},
	
	/**
	 *	Funkcja testujaca wystepowanie zmiennych
	 *	@return void
	 */
	_ShowVariables : function() {
		alert(this.element);
		alert(this.headers);
		alert(this.rows);
	},
	
	/**
	 *	Funkcja zapisujaca tabele do zmiennej tablicowej
	 *	@param object t
	 *	@return void
	 */
	_makeTableFromTable: function(t) {
		var rows = t.getElements('tr');
		this.rows = rows;
		var count = 0;
		while(count < rows.length){
			var tr = rows[count];
			var cells = {};
			var rcount = 0;
			this.rows[count] = [];
			this.rows[rcount] = {};	//!
			
			tr.getElements('td').each(function(td){
				if ($chk(td.innerHTML)) {
					if (count==0) {
						this._addHeader(td/*,rcount*/);
					}
					this.rows[count][rcount] = td.innerHTML;
					rcount++;
				}
			}, this);
			this.rows[count]['visible'] = true;
			count++;
		}
	},
	
	/**
	 *	Dodanie pola tabeli jako pole naglowka
	 *	@param object td
	 *	@return void
	 */
	_addHeader: function(td) {
		var TOptions = Object.extend({
			'index': 0,
			'sortType': 'asc',
			'sortable': true,
			'hname': null,
			initialize: function() {	//defaultowe ustawienia
				this.sortType = 'asc';
			}
		});
		
		
		var Index = this.headers.length;
		var options = new TOptions.initialize();
		
		options.index = Index;
		options.hname = td.innerHTML;
		options.sortable = td.hasClass('ct-sortable') ? true : false;
	//	options.sortType = td.hasClass('ct-sortable') ? 'asc' : false;
		
		this.headers[Index] = options;
	//	alert(this.headers[Index].sortType);
		
		if (td.hasClass('ct-sortable')) {
			td.addEvent('mouseover', function() {
				this.addClass('ct-mouseover');
			});
			td.addEvent('mouseleave', function() {
				this.removeClass('ct-mouseover');
			});
			var kolumna = Index;
			var obj = this;
			td.addEvent('click', function(ev) {
				obj._sort(Index);
			//	obj._sort(kolumna, 'asc');
			});
		}
	},
	
	/**
	 *	Sortowanie tabeli
	 *	@param int kolumna
	 *	@return void
	 */
	_sort: function(kolumna) {
		this.quicksort(this.rows, 1, this.rows.length-1, kolumna);
		
		//zmiana typu sortowania
		this.headers[kolumna].sortType = (this.headers[kolumna].sortType == 'asc') ? 'desc' : 'asc';
		
		this._rebuild();
	},
	
	/**
	 *	Algorytm sortujacy (porwnujacy) dwa ciagi znakow uwzgledniajac polskie literki oraz ustawiajace
	 *	je wg okreslonego wzorca
	 *	@param string a
	 *	@param string b
	 *	@return int
	 */
	cmp: function(a, b) {
		if (a == b) return 0;
		a = a+" "; b = b+" ";
		ile = (a.length >= b.length) ? b.length : a.length;
		for (numer=0;numer<ile;numer++) {
			if (this.sortOrder.indexOf(a.charAt(numer)) < this.sortOrder.indexOf(b.charAt(numer))) return -1;
			if (this.sortOrder.indexOf(a.charAt(numer)) > this.sortOrder.indexOf(b.charAt(numer))) return 1;
		}
	},

	
	/**
	 *	Algorytm rekurencyjny szybkiego sortowania 'Quicksort'
	 *	@param array tab
	 *	@param int left
	 *	@param int kolumna
	 *	@return void
	 */
	quicksort: function(tab, left, right, kolumna) {
		var i = left;
		var j = right;
		var Index = parseInt((left+right)/2);
		var x = tab[Index][kolumna];
		do {
			if (this.headers[kolumna].sortType == 'asc') {
				while (this.cmp(tab[i][kolumna], x) == -1) i++;
				while (this.cmp(tab[j][kolumna], x) == 1) j--;
			//	while (tab[i][kolumna] < x) i++;
			//	while (tab[j][kolumna] > x) j--;
			} else if (this.headers[kolumna].sortType == 'desc') {
				while (this.cmp(tab[i][kolumna], x) == 1) i++;
				while (this.cmp(tab[j][kolumna], x) == -1) j--;
			//	while (tab[i][kolumna] > x) i++;
			//	while (tab[j][kolumna] < x) j--;
			}
			if (i <= j) {
				var tmp = [];
				tmp = tab[i];
				tab[i++] = tab[j];
				tab[j--] = tmp;
			}
		} while (i <= j);
		
		if (left < j) this.quicksort(tab, left, j, kolumna);
		if (i < right) this.quicksort(tab, i, right, kolumna);
	}, 
	
	/**
	 *	Aktualizacja tabeli zrodlowej na podstawie danych z tablicy this.rows
	 *	@return void
	 */
	_rebuild: function() {
		count = 0;
		var shows = 0;
		
		if (this.options.usePaging) {
			this.rowsFrom = (this.options.rowsPerPages * this.currentPage) - this.options.rowsPerPages+1;
			this.rowsTo = this.rowsFrom + this.options.rowsPerPages-1;
		}
		
		var rows = this.element.getElements('tr');
		while(count < rows.length){
			var tr = rows[count];
			var rcount = 0;
			
			tr.getElements('td').each(function(td){
				if ($chk(td.innerHTML)) {
					if (count > 0) {
						td.innerHTML = this.rows[count][rcount];
						
					}
					rcount++;
				}
			}, this);
			if (!this.rows[count].visible) {
				//element powinien byc niewidoczny (np z powodu filtru lub dzielenia na strony)
				if (count > 0) tr.addClass('hidden');
			} else {
	//			alert(shows+' >= '+this.rowsFrom+' && '+shows+' < '+this.rowsTo);
				if (shows >= this.rowsFrom-1 && shows < this.rowsTo) {
					tr.removeClass('hidden');
					shows++;
				} else {
					tr.addClass('hidden');
					shows++;
				}
			}
			count++;
		}
		
		//pokazanie lub schowanie linkow do nawigacji
			//ustawienie od ktorego do ktorego rekordu maja byc wyswietlone wyniki
			
		//ustawienie od ktorego do ktorego rekordu maja byc wyswietlone wyniki
		if (this.options.usePaging) {
			this.pagesAll = parseInt(shows / this.options.rowsPerPages);
			if (shows % this.options.rowsPerPages > 0) this.pagesAll++;
		}
		$('ct-quicksearch_field').getParent().getPrevious().getFirst().setStyle('display', (this.currentPage <= 2 || !this.options.usePaging) ? 'none' : 'inline');												//first
		$('ct-quicksearch_field').getParent().getPrevious().getFirst().getNext().setStyle('display', (this.currentPage <= 1 || !this.options.usePaging) ? 'none' : 'inline');												//prev
		$('ct-quicksearch_field').getParent().getPrevious().getFirst().getNext().getNext().getNext().setStyle('display', (this.currentPage >= this.pagesAll || !this.options.usePaging) ? 'none' : 'inline');				//next
		$('ct-quicksearch_field').getParent().getPrevious().getFirst().getNext().getNext().getNext().getNext().setStyle('display', (this.currentPage >= this.pagesAll-1 || !this.options.usePaging) ? 'none' : 'inline');		//last
		$('ct-quicksearch_field').getParent().getPrevious().getFirst().getNext().getNext().setHTML(this.rowsFrom+'-'+((this.rowsTo < shows) ? this.rowsTo : shows)+' '+this.lang.ofText+' '+shows);
	},
	
	/**
	 *	Filtrowanie danych w tablicy na podstawie klucza (wyrazu)
	 *	@params array tab
	 *	@params string string
	 *	@return void
	 */
	_filtruj: function(tab, string) {
		for (i=0; i<tab.length; i++) {
			var znaleziono = false;
			for (j=0; j<tab[i].length; j++) {
				if (this.headers[j].sortable) {
					if (tab[i][j].toLowerCase().match(string.toLowerCase())) {
						znaleziono = true;
					}
				}
			}
			if (znaleziono) {
				tab[i]['visible'] = true;
			} else {
				tab[i]['visible'] = false;
			}
		}
	},
	
	/**
	 *	Dodanie pola quicksearch
	 *	Dodanie zdarzenia na puszczenie klawisza w polu quick-search
	 *	@return void
	 */
	_bindQuickSearch: function() {
		//dodanie pola quicksearch
		var obj = this;
		var el = new Element('div', {
			'styles': {
				'width': parseInt(this.options.tableWidth)+'px'
			},
			'class': 'ct-quicksearch_area'
		});
		el.injectBefore(this.element);
		
		var span = new Element('span', {
			'class': 'ct-quicksearch-listview'/*,
			'id': 'ct-quicksearch-listview'*/
		});
		span.injectInside(el);
		
		var l = new Element('a', {
			'href': 'javascript:;',
			'events': {
				'click': function() {
					$(obj.options.quickSearchId).value = '';
					this.setStyle('display', 'none');
					obj._filtruj(obj.rows, $(obj.options.quickSearchId).value);	//nowa funkcja wykorzystujaca tylko JavaScript
					obj.currentPage = 1;
					
					obj._blurQuickSearch();
					obj._rebuild();
				},
				'focus': function() {
					this.blur();
				}
			}
		});
		l.injectInside(span);
		
		var span2 = new Element('span');
		span2.injectInside(l);
		
		var field = new Element('input', {
			'type': 'text',
			'id': this.options.quickSearchId,
			'class': this.options.quickSearchId+' ct-gray',
			'value': this.lang.quickSearchText,
			'events': {
				'focus': function() {
					obj._focusQuickSearch();
				},
				'blur': function() {
					obj._blurQuickSearch();
				},
				'keyup': function() {
					if (this.getValue().length > 0) {
						this.getPrevious().setStyle('display', 'block');
					} else {
						this.getPrevious().setStyle('display', 'none');
					}
				//	$E('a', 'ct-quicksearch-listview').setStyle('display', 'block');
					last_search = new Date;
					(function() {
						current_search = new Date();
						if (current_search.getTime() - 250 > last_search.getTime()) {
							obj._filtruj(obj.rows, $(obj.options.quickSearchId).value);	//nowa funkcja wykorzystujaca tylko JavaScript
							obj.currentPage = 1;
							last_search = new Date();
						}
						obj._rebuild();
					}).delay(500);
				}
			}
		});
		field.injectInside(span);
	},
	
	/**
	 *	Zdarzenie wywolane po aktywacji pola input
	 *	@return void
	 */
	_focusQuickSearch: function() {
		if ($(this.options.quickSearchId).getValue() == this.lang.quickSearchText) {
			$(this.options.quickSearchId).setProperty('value', '');
			$(this.options.quickSearchId).removeClass('ct-gray');
		}
	},
	
	/**
	 *	Zdarzenie wywolane po deaktywacji pola input
	 *	@return void
	 */
	_blurQuickSearch: function() {
		if ($(this.options.quickSearchId).getValue() != this.lang.quickSearchText && $(this.options.quickSearchId).getValue() == '') {
			$(this.options.quickSearchId).addClass('ct-gray');
			$(this.options.quickSearchId).setProperty('value', this.lang.quickSearchText);
		}
	},
	
	/**
	 *	Dzielenie tabelki na strony
	 *	@return void
	 */
	_makePages: function() {
		var obj = this;
		var wierszy = this.rows.length-1;
		var pages = parseInt(wierszy / this.options.rowsPerPages);
		if (wierszy % this.options.rowsPerPages > 0) pages++;

		//ustawienie od ktorego do ktorego rekordu maja byc wyswietlone wyniki
		if (this.options.usePaging) {
			this.rowsFrom = (this.options.rowsPerPages * this.currentPage) - this.options.rowsPerPages+1;
			this.rowsTo = this.rowsFrom + this.options.rowsPerPages-1;
			this.pagesAll = pages;
		} else {
			this.rowsFrom = 1;
			this.rowsTo = wierszy;
			this.pagesAll = 1;
		}
		
		//pokazanie linkow ze stronami
		var div = new Element('div', {
			'class': 'ct-quicksearch-listview_nav'
		});
		div.injectBefore($(this.options.quickSearchId).getParent());
		
		var span = new Element('span');
		span.injectInside(div);
		span.setHTML(this.rowsFrom+'-'+this.rowsTo+' z '+wierszy);
		
		var linkNext = new Element('a', {
			'href': 'javascript:;',
			'class': 'pages next',
			'events': {
				'click': function() {
					obj._nextPage();
				}
			}
		});
		linkNext.injectAfter(span);
		linkNext.setHTML(this.lang.nextText);
		
		var linkPrev = new Element('a', {
			'href': 'javascript:;',
			'class': 'pages prev',
			'events': {
				'click': function() {
					obj._prevPage();
				}
			}
		});
		linkPrev.injectBefore(span);
		linkPrev.setHTML(this.lang.prevText);
		
		var linkFirst = new Element('a', {
			'href': 'javascript:;',
			'class': 'pages first',
			'events': {
				'click': function() {
					obj._firstPage();
				}
			}
		});
		linkFirst.injectBefore(linkPrev);
		linkFirst.setHTML(this.lang.firstText);
		
		var linkLast = new Element('a', {
			'href': 'javascript:;',
			'class': 'pages last',
			'events': {
				'click': function() {
					obj._lastPage();
				}
			}
		});
		linkLast.injectAfter(linkNext);
		linkLast.setHTML(this.lang.lastText);
		
		
		this._rebuild();
	}, 
	
	/**
	 *	Przejscie do nastepnej strony
	 *	@return void
	 */
	_nextPage: function() {
		this.currentPage++;
		this._rebuild();
	},
	
	/**
	 *	Przejscie do poprzedniej strony
	 *	@return void
	 */
	_prevPage: function() {
		this.currentPage--;
		this._rebuild();
	},
	
	/**
	 *	Przejscie do ostatniej strony
	 *	@return void
	 */
	_lastPage: function() {
		this.currentPage = this.pagesAll;
		this._rebuild();
	},
	
	/**
	 *	Przejscie do pierwszej strony
	 *	@return void
	 */
	_firstPage: function() {
		this.currentPage = 1;
		this._rebuild();
	}
});
