( function($)
{

	$.fn.dataTable = function(options)
	{

		return this.each( function()
		{

			var config = $.extend( {}, $.fn.dataTable.defaults, options);

			var location = $(this);
			var table = null;
			var orderBy = config.orderBy;
			var pageNumber = 0;
			var rowsPerPage = config.rowsPerPage;
			var numberOfRows = 0;
			var parent = this;

			location.empty();
			table = createTable();
			location.append(table);
			internalLoadPage(0);

			function createTable()
			{
				var table = $("<table class=\"" + config.styleClass + "\">");
				table.append(createHeader());
				table.append($("<tbody class=\"dataContent\">"));
				table.append(createFooter());
				return table;
				// location.append(table);
			}
			;

			function createHeader()
			{
				var header = $("<thead>");
				var row = $("<tr>");
				$.each(config.columns, function()
				{
					var classes = (config.headerClass || "") + (this.sort ? ' sortable' : '');
					var th = $("<th class=\"header " + classes + " " + this.prop + "Header\">" + this.label + "</th>");
					th.column = this;
					th.sortable = this.sort;
					th.direction = config.defaultOrder;
					if (th.sortable)
					{
						th.click( function(event)
						{
							table.find('th').removeClass(config.css_desc).removeClass(config.css_asc);
							orderBy = th.column.prop + " " + th.direction;
							th.direction = (th.direction == 'asc') ? 'desc' : 'asc';
							th.addClass(th.direction == 'asc' ? config.css_asc : config.css_desc);
							parent.loadPage(0);
						});
					}
					row.append(th);
				});
				header.append(row);
				return header;
			}
			;

			function createTd(name, page)
			{
				var td = $("<td>").addClass("table_" + name).click( function()
				{
					internalLoadPage(page);
				}).html(config[name]);
				return td;
			}
			;

			function createFooter()
			{
				var footer = $("<tfoot>");
				footer
						.append('<tr class="table_footer"><td colspan="' + config.columns.length + '"><div align="center"><table class="table_footer"><tbody><tr>');
				var row = footer.find("table tr").append(createTd('first', 0)).append(createTd('prev', pageNumber - 1));
				var numPages = (numberOfRows == 0) ? 0 : (numberOfRows - 1) / rowsPerPage;
				for ( var i = 0; i <= numPages; i++)
				{
					row.append(createTd('number', i).html("" + (i + 1)).addClass((i == pageNumber) ? 'table_active' : ''));
				}
				row.append(createTd('next', pageNumber + 1)).append(createTd('last', 1000000));
				return footer;
			}
			;

			function addRowValues(rows)
			{
				jQuery(table)
						.find("tbody")
						.each( function()
						{
							var body = jQuery(this);
							body.empty();
							jQuery.each(rows, function(x, rowData)
									{
										var row = jQuery("<tr>");
										jQuery.each(config.columns, function()
												{
													var classes = (this.styleClass && this.styleClass.length > 0) ? ' class="' + this.styleClass + '"' : '';
													var td = jQuery("<td" + classes + ">")
															.attr('id', (config.pk && config.tableName) ? config.tableName + ':' + rowData[config.pk] + ':' + this.prop : '');
													if (config.renderer && config.renderer[this.prop])
														row.append(td.html(config.renderer[this.prop]
																(rowData[this.prop], rowData, td)));
													else
														row.append(td.html(rowData[this.prop]));
												});
										body.append(row);
									});
							return false; // only do the first tbody
						});
				jQuery(table).find("tfoot").replaceWith(createFooter());
				// trigger the callbacks, internal first, then user defined.
				oncomplete(parent);
				config.oncomplete(parent);
			}
			;

			function internalLoadPage(page)
			{
				//console.log("loadPage(" + page + ")");
				var numberOfPages = (numberOfRows == 0) ? 0 : (numberOfRows - 1) / rowsPerPage;
				page = page || 0;
				page = page >= 0 ? page : 0;
				page = page > numberOfPages ? numberOfPages : page;
				pageNumber = Math.floor(page);
				//console.log("pageNumber = " + pageNumber);
				jQuery.post(config.url,
					{
					'page' : pageNumber,
					'per_page' : rowsPerPage,
					'order_by' : orderBy
					}, function(data, status)
				{
					numberOfRows = data.count;
					addRowValues(data.out);
				}, "json");
			}
			;

			this.setOrderBy = function(newOrderBy)
			{
				orderBy = newOrderBy;
			};

			this.setRowsPerPage = function(perPage)
			{
				rowsPerPage = perPage;
			};

			this.loadPage = function(page)
			{
				internalLoadPage(page);
			};

			this.refreshTable = function()
			{
				internalLoadPage(pageNumber);
			};

			function oncomplete()
			{
			}
			;
		});

	};

	jQuery.fn.dataTable.defaults =
		{
		styleClass : 'datagrid',
		headerClass : '',
		first : '<<',
		prev : '<',
		number : '',
		next : '>',
		last : '>>',
		columns : {},
		css_asc : 'headerSortUp',
		css_desc : 'headerSortDown',
		rowsPerPage : 20,
		pk : 'id',
		orderBy : '',
		defaultOrder : 'asc',
		oncomplete : function(parent)	{},
		url : 'ajax.php'
		};

})(jQuery);

