if (typeof Goingup == 'undefined'){
	var Goingup = {};
}
Goingup.Table = function(){
	var Table = {
		rows:[],
		rowsViewPort:{start:0,count:10},
		pager:{i:1,rows:10,buttons:10},
		/**
		 * 
		 * @config {
		 * 		mainId:'tableId',
		 * 		thead:{
		 * 				selector:'#headTableId>thead>tr>td',
		 * 				selectedClass:'selected'
		 * 				},
		 * 		tbody:{
		 * 				selector:'#bodyTableId>tbody',
		 * 				evenClass:'even',
		 * 				oddClass:'odd',
		 * 				sortBy:colnumber, 
		 * 				sortType:'asc',
		 * 				items:[
		 * 						]
		 * 				},
		 * 		tfoot:{
		 * 				selector:'#footTableId>tfoot'
		 * 				},
		 * 		cols:[
		 * 			  {valueIn:'div>span',theadNumber:0},
		 * 			  {valueIn:'div>span',theadNumber:1},
		 * 			  {valueIn:'div>span',theadNumber:2}
		 * 			 	],
		 * 		onSelect:fucntion(){ //do other needed actions },
		 * 		onBefore:function(){ //doactions before starting ordering},
		 * 		onAfter:function(){ // do action after ordering },
		 * 		
		 * } 
		 */
		
		config:{
			
		},
		/**
		 * options = {
		 * 		rows:[], - list of table rows
		 * 		rowsViewPort:{start:0,count:10}, - visible rows, this needed for pages usually
		 * 		config:{} - config, look above
		 * }
		 */
		Init:function(options){
			Table.rows = options.rows;	
			Table.rowsViewPort = options.rowsViewPort?options.rowsViewPort:Table.rowsViewPort;
			Table.config = options.config;
			
			Table.pager.rows = Table.rowsViewPort.count;
			
			objTbody = jQuery('#'+Table.config.mainId+'>tbody');
			
			Table.Fill(objTbody,Table.rows,Table.config);
			if (Table.config.pager && Table.config.pager.parent){
				//if (Table.rows.length>Table.pager.rows){
					// print pager here
					Table.PrintPager();
				//}
				jQuery(Table.config.pager.parent).click(function(e){
					var clicked = $(e.target);  
					Table.Pager(clicked.attr('rel'));									   
				});
			}
			Table.InitOrdering();
			if (Table.config.onAfter instanceof Function){
				Table.config.onAfter();
			}
		},
		UpdateRows:function(rows){
			Table.rows = typeof rows == 'undefined'?[]:rows;
			Table.rowsViewPort.start = 0;
			Table.pager.i = 1;
			Table.reFill();
		},
		Debug:function(){
			
		},
		reFill:function(){
			var objTbody = jQuery('#'+Table.config.mainId+'>tbody');
			
			
			Table.Fill(objTbody,Table.rows,Table.config);
			//if (Table.rows.length>Table.pager.rows){
				// print pager here
				Table.PrintPager();
			//}
		},
		Fill:function(objTbody,rows,params){
			objTbody.empty();
			if (!rows || !rows.length) return false;
			var max = rows.length>Table.rowsViewPort.count+Table.rowsViewPort.start?Table.rowsViewPort.count+Table.rowsViewPort.start:rows.length;
			var start = Table.rowsViewPort.start;
			for (var i=start; i<max; i++){
				var objTr = jQuery('<tr></tr>');
				for (var j=0; j<params['cols'].length; j++){
					var value = rows[i][params['cols'][j]['key']];
					var id = rows[i][params['cols'][j]['id']];
					value = typeof value != 'undefined'?value:'&nbsp;';
					var classname = '';
					if (j==0){
						classname = 'first';
					}else if(j==params['cols'].length-1){
						classname = 'last';
					}
					var value_orig = params['cols'][j]['wraphtml'].replace(/\[content\]/g,value);
					if (id){
						value_orig = value_orig.replace(/\[id\]/,id);
					}
					if (params['cols'][j]['truncate']){
						var value_truncated = Table.truncate(value,params['cols'][j]['truncate']);
						value_orig = value_orig.replace(/\[truncated\]/g,value_truncated);
					}
					objTr.append(jQuery('<td></td>').addClass(classname).html(value_orig));
				}
				
				if (params && params.tbody.evenClass != null && i%2==0){
					objTr.addClass(params.tbody.evenClass);
				}
				if (params && params.tbody.oddClass != null && i%2!=0){
					objTr.addClass(params.tbody.oddClass);
				}
				objTbody.append(objTr);
			}
			
			Goingup.doTooltips(objTbody,0, 0);
		},
		InitOrdering:function(){
			var objHeadOrderLinks = jQuery('a.ordering',Table.config.thead.selector);
			objHeadOrderLinks.click(function(){
				var jThis = jQuery(this);
				var orderDirection = jThis.hasClass('asc')?'asc':'desc'; 
				objHeadOrderLinks.removeClass('desc').removeClass('asc');
				if (orderDirection=='asc'){
					jThis.addClass('desc');
				}else{
					jThis.addClass('asc');
				}
				
				Table.Order2(this.rel,orderDirection);
				Table.reFill();
			});
			
		},
		Order2:function(sortByColNumber,sortByType){
			var key = Table.config['cols'][sortByColNumber]['key'];
			for (var i=0; i<Table.rows.length; i++){
				for (var j=0; j<Table.rows.length; j++){
					
					var val1 = Table.rows[i][key];
					var val2 = Table.rows[j][key];
					if (Goingup.IsNumeric(val1)){
						
						val1 = parseInt(val1);
					}
					if (Goingup.IsNumeric(val2)){
						val2 = parseInt(val2);
					}
					// if row value is empty than not change position
					
					if (val2==='' || val1==='') continue;
					
					switch (sortByType){
						case 'asc':
							if (val1<val2){
								var tmp = Table.rows[i]; 
								Table.rows[i] = Table.rows[j];
								Table.rows[j] = tmp;
							}
						break;
						case 'desc':
							if (val1>val2){
								var tmp = Table.rows[i]; 
								Table.rows[i] = Table.rows[j];
								Table.rows[j] = tmp;
							}
						break;
						default:
						break;
					}
				}
			}
		},
		/**
		 * 
		 * @param {
		 * 		thead:{
		 * 				selector:'#headTableId>thead>tr>td',
		 * 				selectedClass:'selected'
		 * 				},
		 * 		tbody:{
		 * 				selector:'#bodyTableId>tbody',
		 * 				evenClass:'even',
		 * 				oddClass:'odd',
		 * 				sortBy:colnumber, 
		 * 				sortType:'asc'
		 * 				},
		 * 		tfoot:{
		 * 				selector:'#footTableId>tfoot'
		 * 				},
		 * 		cols:[
		 * 			  {valueIn:'div>span',theadNumber:0},
		 * 			  {valueIn:'div>span',theadNumber:1},
		 * 			  {valueIn:'div>span',theadNumber:2}
		 * 			 	],
		 * 		onSelect:fucntion(){ //do other needed actions },
		 * 		onBefore:function(){ //doactions before starting ordering},
		 * 		onAfter:function(){ // do action after ordering },
		 * 		
		 * } 
		 */
		Order:function (sortByColNumber,sortByType){
			if (typeof sortByColNumber == 'undefined'){
				return false;
			}
			// tbody instance
			var objTbody = jQuery(Table.config.tbody.selector);
			
			// { take all data from table
			var allRows = jQuery(Table.config.tbody.selector+'>tr');
			
			var sortByType = typeof sortByType!= 'undefined'?sortByType:'asc';
			
			// make thead col selected
			jQuery(
					jQuery(Table.config.thead.selector)
					.removeClass(Table.config.thead.selectedClass) 
					.get(Table.config.cols[sortByColNumber].theadNumber)
				  ).addClass(Table.config.thead.selectedClass); 
			
			// sort all	
			var cache = {};
			var ar = [];
			for (var i=0; i<allRows.length; i++){
				if (Table.config.tbody.evenClass != null){
					jQuery(allRows[i]).removeClass(Table.config.tbody.evenClass);
				}
				if (Table.config.tbody.oddClass){
					jQuery(allRows[i]).removeClass(Table.config.tbody.oddClass);
				}
				
				var val = jQuery(allRows[i].cells[sortByColNumber]).find(Table.config.cols[sortByColNumber].valueIn).html();
				if (val!=null){
					val = val.replace('&nbsp;','').replace(',','');
					if (Goingup.IsNumeric(val)){
						val = parseInt(val);
					}
				}else{
					val = '';
				}
				ar[ar.length] = val;
			}
			
			
			//quick_sort(ar);
			
			var allRowsValuesForSorting = ar;
			for (var i=0; i<allRowsValuesForSorting.length; i++){
				
				for (var j=0; j<allRowsValuesForSorting.length; j++){
					if (j==i) continue;
					

					var val1 = allRowsValuesForSorting[i];
					var val2 = allRowsValuesForSorting[j];
					
					// if row value is empty than not change position
					
					if (val2==='' || val1==='') continue;
					
					
					switch (sortByType){
						case 'asc':
							
							if (val1<val2){
								
								var tmp = allRows[i]; 
								allRows[i] = allRows[j];
								allRows[j] = tmp;
								
								var tmp = allRowsValuesForSorting[i]; 
								allRowsValuesForSorting[i] = allRowsValuesForSorting[j];
								allRowsValuesForSorting[j] = tmp;
							}
						break;
						case 'desc':
							if (val1>val2){
								var tmp = allRows[i]; 
								allRows[i] = allRows[j];
								allRows[j] = tmp;
								
								var tmp = allRowsValuesForSorting[i]; 
								allRowsValuesForSorting[i] = allRowsValuesForSorting[j];
								allRowsValuesForSorting[j] = tmp;
							}
						break;
						default:
						break;
					}
				}
			}
			
			objTbody.empty();
			for (var i=0; i<allRows.length; i++){
				if (Table.config.tbody.evenClass != null && i%2==0){
					jQuery(allRows[i]).addClass(Table.config.tbody.evenClass);
				}
				if (Table.config.tbody.oddClass != null && i%2!=0){
					jQuery(allRows[i]).addClass(Table.config.tbody.oddClass);
				}
				objTbody.append(allRows[i]);
			}
			
			// } 
			
		},
		Pager:function(pageNum){
			if (!Table.rows || !Table.rows.length){
				var totalPages = 0;
			}else{
				var totalPages = Math.ceil(Table.rows.length/Table.pager.rows);
			}
			if (pageNum>=1 && pageNum<=totalPages){
				Table.pager.i = pageNum;
				Table.rowsViewPort = {start:(pageNum*Table.pager.rows-Table.pager.rows),count:Table.pager.rows}
				Table.reFill();
			}
		},
		PrintPager:function(){
			//if (Table.rows.length<=Table.pager.rows) return;
			var currentPage = parseInt(Table.pager.i);
			var html = '';
			
			html = '<ul class="pager">';
			
			// prev prev button
			if (currentPage>Table.pager.buttons){
				html += '<li><a href="#page'+(currentPage-Table.pager.buttons)+'" rel="'+(currentPage-Table.pager.buttons)+'">&laquo;&laquo;</a></li>'
			}
			
			// prev button
			if (currentPage>1){
				html += '<li><a href="#page'+(currentPage-1)+'" rel="'+(currentPage-1)+'">&laquo;</a></li>'
			}
			
			if (!Table.rows || !Table.rows.length){
				var totalPages = 0;
			}else{
				var totalPages = Math.ceil(Table.rows.length/Table.pager.rows);
			}
			var centerButton = Math.round(Table.pager.buttons/2);
			var start = currentPage>centerButton?currentPage-centerButton:1;
			var end = start+Table.pager.buttons-1;
			if (end>totalPages){
				end = totalPages;
				start = end - Table.pager.buttons+1;
				start = start<1?1:start;
			}
			
			for (var i=start; i<=end; i++){
				if (i==currentPage){
					html += '<li><span>'+i+'</span></li>';
				}else{
					html += '<li><a href="#page'+i+'" rel="'+i+'">'+i+'</a></li>';
				}
			}
			
			// next button
			if (currentPage<totalPages){
				html += '<li><a href="#page'+(currentPage+1)+'" rel="'+(currentPage+1)+'">&raquo;</a></li>'
			}
			
			// next next button
			if (currentPage<=(totalPages-Table.pager.buttons)){
				html += '<li><a href="#page'+(currentPage+Table.pager.buttons)+'" rel="'+(currentPage+Table.pager.buttons)+'">&raquo;&raquo;</a></li>'
			}
			
			html += '</ul>';
			
			jQuery(Table.config.pager.parent).html(html);
			
		},
		truncate:function(text,chars,dots){
			return Goingup.truncate(text,chars,dots);
		}
		
	}
	return Table;
};
