(function($) {
	var defaultConfig = {
		paging: true,
		defaultParams: {}
	};
	$.fn.grid = function(options) {
		var renderTo = this;
		var config = {};
		$.extend(config, defaultConfig, options);
		var current = 1;
		var pageSize = 15;
		var params = {};
		var records;
		params.start = 1;
		params.limit = pageSize;
		$.extend(params, config.defaultParams);
		render();
		return {
			render: renderReset,
			setParam: setParam,
			setUrl: setUrl,
			getData: getData
		};
		function getData() {
			return records;
		}
		function setParam(key, value) {
			params[key] = value;
		}
		function setUrl(url) {
			config.url = url;
		}
		function renderReset() {
			current = 1;
			params.start = (current - 1) * pageSize + 1;
			render();
		}
		function render() {
			if(!config.paging)
				params.limit = 99999;
			$.post(config.url + ".json", params, function(data) {
				var grid = $('<table />');
				grid.addClass('xTable martop');
				records = data[config.root];
				var head = getHead(config.fields);
				grid.append(head);
				var body = getBody(config.fields, data);
				grid.append(body);
				var gridBox = $('<div />').addClass('msgCon').append(grid);
				renderTo.empty();
				renderTo.append(gridBox);
				var total = data.total;
				var pagingBar;
				if(config.paging) {
					pagingBar = generatePagingBar(total);
				} else {
					pagingBar = $('<div />').addClass('page');
				}
				pagingBar.insertAfter(gridBox);
				if(config.buttons) {
					$.each(config.buttons, function(i, button) {
						var link = $('<a href="#" class="bb"/>').css('margin', '0 2px');
						if(button.action)
							link.click(function() {
								return button.action.call(grid, data);
							});
						else
							link.attr('href', button.href);
						if(data.total!=0){
							if(button.hasDelete=='true'){
								if(button.src)
									link.append($('<img />').attr('src', button.src));
								else
									link.append(button.html);
							}
						}
						link.appendTo(pagingBar);
					});
				}
				
			}, 'json');
		}
		function generatePagingBar(total) {
			var pagingBar = $('<div />').addClass('Btn');
			var em = $('<em />');
			var pageCount = Math.ceil(total / pageSize);
			var pagingTool = $('<div />').addClass('pages').appendTo(em);
			em.appendTo(pagingBar);
			var info =i18ns('jQuery.grid.i18ns.bottomBar.part1',[total,current,pageCount])
			pagingTool.append(info);
			function gotoPage() {
				current = parseInt(pageInput.val()) || 1;
				current = current > pageCount ? pageCount : current;
				current = current < 1 ? 1 : current;
				params.start = (current - 1) * pageSize + 1;
				render();
				return false;
			}
			if(pageCount > 1) {
				var start = current - 2 < 1 ? 1 : current - 2;
				var end = current + 2 > pageCount ? pageCount : current + 2;
				if(current > 1) {
					createPageLink(1, i18ns('jQuery.grid.i18ns.bottomBar.part2'), pagingTool);
					createPageLink(current - 1, '&lt;', pagingTool);
				}
				for(var i = start;i <= end;i++) {
					if(i != current) {
						createPageLink(i, i, pagingTool);
					} else {
						var pageLink = $('<a />').html(i).appendTo(pagingTool).attr('index', i).addClass('focus');
					}
				}
				if(current < end) {
					createPageLink(current + 1, '&gt;', pagingTool);
					createPageLink(pageCount, i18ns('jQuery.grid.i18ns.bottomBar.part3'), pagingTool);
				}
				var pageInput = $('<input />').val(current).attr('size', 4).css('width', '20px').keyup(function(e) {
					if(e.keyCode == 13)
						gotoPage();
				});
				var pageOk = $('<a href="#"/>').html(i18ns('jQuery.grid.i18ns.bottomBar.part6')).click(gotoPage);
				pagingTool.append(i18ns('jQuery.grid.i18ns.bottomBar.part4')).append(pageInput).append(i18ns('jQuery.grid.i18ns.bottomBar.part5')).append(pageOk);
			}
			return pagingBar;
		}
		function createPageLink(index, html, pagingTool) {
			var pageLink = $('<a />').html(html).appendTo(pagingTool).attr('index', index);
			pageLink.attr('href', '#').click(function() {
				current = parseInt($(this).attr('index'));
				params.start = (current - 1) * pageSize + 1;
				render();
				return false;
			});
		}
		function getHead(fields) {
			var thead = $('<thead />');
			var rowHead = $('<tr />').appendTo(thead);
			$.each(fields, function(i, field) {
				var th = $('<th />').css('text-align', 'left').appendTo(rowHead);
				if(field.type == 'hidden')
					th.hide();
				if(field.type == 'checkbox') {
					th.append($('<span />').addClass('checkbox').append($('<input />').attr('type', 'checkbox').change(function() {
						thead.parent().find(':checkbox[name=' + field.id + ']').attr('checked', this.checked);
					})));
				} else {
					th.append($('<span />').html(field.name));
				}
			});
			return thead;
		}
		function getBody(fields, data) {
			var tbody = $('<tbody />');
			if(config.sortable)
				tbody.sortable();
			$.each(data[config.root], function(i, d) {
				var row = $('<tr />').appendTo(tbody);
				$.each(config.fields, function(i, field) {
					var value = d[field.id];
					var html = value;
					if($.isFunction(field.render)) {
						html = field.render(d);
					}
					html = html || "";
					var td = $('<td />').css('text-align', 'left').addClass('content-td').appendTo(row);
					if(field.type == 'number')
						td.css('text-align', 'right');
					if(field.type == 'date') {
						html = $.format.formatDate(new Date(html));
						// TODO 增加默认宽度
					}
					if(field.type == 'time') {
						html = $.format.formatTime(new Date(html));
						field.width = field.width || 115;
					}
					if(field.type == 'checkbox') {
						field.width = field.width || 10;
						td.append($('<input />').attr({type: 'checkbox', name: field.id, value: value}).change(function() {
							var grid = tbody.parent();
							if(!this.checked) {
								grid.find('th :checkbox').attr('checked', false);
							} else {
								var allChecked = true;
								grid.find('td :checkbox').each(function(index, elem) {
									if(!elem.checked)
										allChecked = false;
								});
								if(allChecked)
									grid.find('th :checkbox').attr('checked', true);
							}
						}));
					} else if(field.type == 'hidden') {
						td.append($('<input />').attr({type: 'hidden', name: field.id, value: value}));
						td.hide();
					} else if(field.type=='radio'){
						field.width = field.width || 10;
						td.append($('<input type="radio" name='+field.id+' value='+value+' />'));
					}else {
						if(field.maxlength) {
							var shortHtml = $.abbreviate(html, field.maxlength);
							td.html(shortHtml).attr('title', html);
						} else {
							td.html(html);
						}
					}
					if(field.width)
						td.css('width', field.width + 'px');
				});
			});
			tbody.find('tr:even').addClass('bgcolor');
			$('#ui-datepicker-div').hide();
			return tbody;
		}
	};
	$.abbreviate = function(str, length) {
		if($.getLength(str) > length) {
			// ... 只占两个字母的位置左右
			return $.substr(str, 0, length - 2) + '...';
		} else {
			return str;
		}
	};
	$.substr = function(str, start, length) {
		var escapeStr = escape(str);
		var n = 0,current = 0,lastCurrent;
		while(n <= length) {
			lastCurrent = current;
			if(escapeStr.charAt(current) == '%') {
				if(escapeStr.charAt(current + 1) == 'u') {
					current += 6;
					n += 2;
				} else {
					current += 3;
					n++;
				}
			} else {
				current++;
				n++;
			}
		}
		return unescape(escapeStr.substring(0, lastCurrent));
	};
	$.getLength = function(str) {
		if(!str)
			return 0;
		var m = escape(str).match(/%u/g);
		return str.length + (m ? m.length : 0);
	};
	$.fn.template = function(data) {
		return this.clone().removeAttr('id').render(data);
	};
})(jQuery);
