define(['jquery', 'bootstrap', 'validator'], function ($, undefined, Validator) {
	var Form = {
		config: {
			editor: {
				"full":['source', 'undo', 'redo', 'code', 'quote', 'cut',
					'plainpaste', 'wordpaste', 'justifyleft', 'justifycenter', 'justifyright',
					'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
					'superscript', 'clearhtml', 'quickformat', 'selectall', '/',
					'formatblock', 'fontname', 'fontsize', 'forecolor', 'hilitecolor', 'bold',
					'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', 'image', 'multiimage', 'media', 'insertfile', 'table', 'hr', 'baidumap',
					'anchor', 'link', 'unlink','fullscreen'
				],
				"base":['undo', 'redo', 'quote', 'formatblock', 'fontname', 'fontsize', 'forecolor', 'hilitecolor', 'bold',
					'italic', 'underline', 'strikethrough', 'lineheight', 'image', 'media', 'table'
				],
			},
			fieldlisttpl: '<dd class="form-inline"><input type="text" name="<%=name%>[<%=index%>][key]" class="form-control" value="<%=row.key%>" size="10" /> <input type="text" name="<%=name%>[<%=index%>][value]" class="form-control" value="<%=row.value%>" /> <% if (row.other) { %><input type="text" name="<%=name%>[<%=index%>][other]" class="form-control" value="<%=row.other%>" /><% } %> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>'
		},
		events: {
			validator: function (form, success, error, submit) {
				if (!form.is("form"))
					return;
				//绑定表单事件
				form.validator($.extend({
					validClass: 'has-success',
					invalidClass: 'has-error',
					bindClassTo: '.form-group',
					formClass: 'n-default n-bootstrap',
					msgClass: 'n-right',
					stopOnError: true,
					display: function (elem) {
						return $(elem).closest('.form-group').find(".control-label").text().replace(/\:/, '');
					},
					dataFilter: function (data) {
						if (data.code === 1) {
							return data.msg ? {"ok": data.msg} : '';
						} else {
							return data.msg;
						}
					},
					target: function (input) {
						var target = $(input).data("target");
						if (target && $(target).size() > 0) {
							return $(target);
						}
						var $formitem = $(input).closest('.form-group'),
							$msgbox = $formitem.find('div.help-block');
						if (!$msgbox.length) {
							return [];
						}
						return $msgbox;
					},
					valid: function (ret) {
						var that = this, submitBtn = $("button.btn[type=submit]", form);
						that.holdSubmit(true);
						submitBtn.addClass("disabled").attr('disabled', 'disabled');
						//验证通过提交表单
						var submitResult = Form.api.submit($(ret), function (data, ret) {
							that.holdSubmit(false);
							submitBtn.removeClass("disabled").removeAttr('disabled');
							if (false === $(this).triggerHandler("success.form", [data, ret])) {
								return false;
							}
							if (typeof success === 'function') {
								if (false === success.call($(this), data, ret)) {
									return false;
								}
							}
							//提示及关闭当前窗口
							var msg = ret.hasOwnProperty("msg") && ret.msg !== "" ? ret.msg : __('Operation completed');
							sent.msg(msg, 'success');
							if (ret.url !== '') {
								setTimeout(function(){
									window.location.href = ret.url;
								}, 3000);
							}
							parent.$(".btn-refresh").trigger("click");
							return false;
						}, function (data, ret) {
							that.holdSubmit(false);
							if (false === $(this).triggerHandler("error.form", [data, ret])) {
								return false;
							}
							submitBtn.removeClass("disabled").removeAttr('disabled');
							if (typeof error === 'function') {
								if (false === error.call($(this), data, ret)) {
									return false;
								}
							}
						}, submit);
						//如果提交失败则释放锁定
						if (!submitResult) {
							that.holdSubmit(false);
							submitBtn.removeClass("disabled");
						}
						return false;
					}
				}, form.data("validator-options") || {}));

				//移除提交按钮的disabled类
				$("button.btn[type=submit]", form).removeClass("disabled").removeAttr('disabled');
			},
			editor: function (form) {
				//绑定编辑器元素事件
				if ($(".form-editor", form).size() > 0) {
					var items = $(".form-editor", form).data('items') || 'full';
					require(['NKeditor'], function(){
						KindEditor.create('.form-editor', {
							items: Form.config.editor[items],
							uploadJson: "/"+Config.module+"/upload/editor'",
							fileManagerJson: "/"+Config.module+"/upload/filemanage"
						})
					})
				}
			},
			board: function (form){
				if ($('.boards', form).size() > 0) {
					require(['board'], function(){
						$('.boards', form).boards({
							drop: function(e){
								var group = e.target.closest('.board').find('.board-list').data('group');
								var name = e.target.closest('.board').find('.board-list').data('name');
								e.element.find('input').attr('name',name+'[' + group + '][]')
							}
						})
					})
				}
			},
			tagsinput: function(form){
				if ($('.tagsinput', form).size() > 0) {
					require(['tagsinput'], function(){
						$('.tagsinput', form).tagsinput();
					})
				}
			},
			selectpicker: function (form) {
				//绑定select元素事件
				if ($(".selectpicker", form).size() > 0) {
					require(['select2'], function () {
						$('.selectpicker', form).select2({
							placeholder: "——请选择——"
						});
					});
				}
			},
			iconpicker: function(form){
				if ($(".iconpicker", form).size() > 0) {
					require(['iconpicker'], function () {
						$('.iconpicker', form).iconpicker();
					});
				}
			},
			selectpage: function (form) {
				//绑定selectpage元素事件
				if ($(".selectpage", form).size() > 0) {
					require(['selectpage'], function () {
						$('.selectpage', form).selectPage({
							eAjaxSuccess: function (data) {
								data.list = typeof data.rows !== 'undefined' ? data.rows : (typeof data.list !== 'undefined' ? data.list : []);
								data.totalRow = typeof data.total !== 'undefined' ? data.total : (typeof data.totalRow !== 'undefined' ? data.totalRow : data.list.length);
								return data;
							}
						});
					});
					//给隐藏的元素添加上validate验证触发事件
					$(document).on("change", ".sp_hidden", function () {
						$(this).trigger("validate");
					});
					$(document).on("change", ".sp_input", function () {
						$(this).closest(".sp_container").find(".sp_hidden").trigger("change");
					});
					$(form).on("reset", function () {
						setTimeout(function () {
							$('.selectpage', form).selectPageClear();
						}, 1);
					});
				}
			},
			cxselect: function (form) {
				//绑定cxselect元素事件
				if ($("[data-toggle='cxselect']", form).size() > 0) {
					require(['cxselect'], function () {
						$.cxSelect.defaults.jsonName = 'name';
						$.cxSelect.defaults.jsonValue = 'value';
						$.cxSelect.defaults.jsonSpace = 'data';
						$("[data-toggle='cxselect']", form).cxSelect();
					});
				}
			},
			citypicker: function (form) {
				//绑定城市远程插件
				if ($("[data-toggle='city-picker']", form).size() > 0) {
					require(['citypicker'], function () {
						$(form).on("reset", function () {
							setTimeout(function () {
								$("[data-toggle='city-picker']").citypicker('refresh');
							}, 1);
						});
					});
				}
			},
			datetimepicker: function (form) {
				//绑定日期时间元素事件
				if ($(".datetimepicker", form).size() > 0) {
					require(['bootstrap-datetimepicker'], function () {
						var options = {
							format: 'YYYY-MM-DD HH:mm:ss',
							icons: {
								time: 'fa fa-clock-o',
								date: 'fa fa-calendar',
								up: 'fa fa-chevron-up',
								down: 'fa fa-chevron-down',
								previous: 'fa fa-chevron-left',
								next: 'fa fa-chevron-right',
								today: 'fa fa-history',
								clear: 'fa fa-trash',
								close: 'fa fa-remove'
							},
							showTodayButton: true,
							showClose: true
						};
						$('.datetimepicker', form).parent().css('position', 'relative');
						$('.datetimepicker', form).datetimepicker(options).on('dp.change', function (e) {
							$(this, document).trigger("changed");
						});
					});
				}
			},
			daterangepicker: function (form) {
				//绑定日期时间元素事件
				if ($(".datetimerange", form).size() > 0) {
					require(['bootstrap-daterangepicker'], function () {
						var ranges = {};
						ranges[__('Today')] = [Moment().startOf('day'), Moment().endOf('day')];
						ranges[__('Yesterday')] = [Moment().subtract(1, 'days').startOf('day'), Moment().subtract(1, 'days').endOf('day')];
						ranges[__('Last 7 Days')] = [Moment().subtract(6, 'days').startOf('day'), Moment().endOf('day')];
						ranges[__('Last 30 Days')] = [Moment().subtract(29, 'days').startOf('day'), Moment().endOf('day')];
						ranges[__('This Month')] = [Moment().startOf('month'), Moment().endOf('month')];
						ranges[__('Last Month')] = [Moment().subtract(1, 'month').startOf('month'), Moment().subtract(1, 'month').endOf('month')];
						var options = {
							timePicker: false,
							autoUpdateInput: false,
							timePickerSeconds: true,
							timePicker24Hour: true,
							autoApply: true,
							locale: {
								format: 'YYYY-MM-DD HH:mm:ss',
								customRangeLabel: __("Custom Range"),
								applyLabel: __("Apply"),
								cancelLabel: __("Clear"),
							},
							ranges: ranges,
						};
						var origincallback = function (start, end) {
							$(this.element).val(start.format(this.locale.format) + " - " + end.format(this.locale.format));
							$(this.element).trigger('blur');
						};
						$(".datetimerange", form).each(function () {
							var callback = typeof $(this).data('callback') == 'function' ? $(this).data('callback') : origincallback;
							$(this).on('apply.daterangepicker', function (ev, picker) {
								callback.call(picker, picker.startDate, picker.endDate);
							});
							$(this).on('cancel.daterangepicker', function (ev, picker) {
								$(this).val('').trigger('blur');
							});
							$(this).daterangepicker($.extend(true, options, $(this).data()), callback);
						});
					});
				}
			},
			plupload: function (form) {
				//绑定plupload上传元素事件
				if ($(".picker-box", form).size() > 0) {
					$(".picker-box .picker_button", form).on('click', function(){
						var type = $(this).data('type');
						var limit = $(this).data('limit');
						var name = $(this).siblings('input[type=hidden]').attr('name');
						layer.open({
							type: 2,
							area: ['60%', '410px'],
							title: false,
							closeBtn: false,
							shadeClose: true,
							content: ['/'+Config.module+'/upload/index?name='+name+'&type='+type+'&limit='+limit, 'no'],
						});
					})
					Form.events.imageDel();
					Form.events.fileDel();
				}
			},
			imageDel: function(){
				//绑定图片上传删除按钮
				if($('.picker-box .img-list .close').size() > 0){
					$('.picker-box .img-list .close').on('click', function(){
						var value = $('.picker-box input[type=hidden]').val().split(",");
						value = value.filter(val => val != $(this).parents('.item').data('id'))
						$(this).parents('.item').remove();
						if(value.length > 0){
							$('.picker-box input[type=hidden]').val(value.join(','));
						}else{
							$('.picker-box input[type=hidden]').val('');
						}
					})
				}
			},
			fileDel: function(){
				//绑定文件上传删除按钮
				if($('.picker-box .file-list .close').size() > 0){
					$('.picker-box .file-list .close').on('click', function(){
						var value = $('.picker-box input[type=hidden]').val().split(",");
						value = value.filter(val => val != $(this).parents('.item').data('id'))
						$(this).parents('.item').remove();
						console.log(value)
						if(value.length > 0){
							$('.picker-box input[type=hidden]').val(value.join(','));
						}else{
							$('.picker-box input[type=hidden]').val('');
						}
					})
				}
			},
			fieldlist: function (form) {
				//绑定fieldlist
				if ($(".fieldlist", form).size() > 0) {
					require(['dragsort', 'template'], function (undefined, Template) {
						//刷新隐藏textarea的值
						var refresh = function (name) {
							var data = {};
							var textarea = $("textarea[name='" + name + "']", form);
							var container = $(".fieldlist[data-name='" + name + "']");
							var template = container.data("template");
							$.each($("input,select,textarea", container).serializeArray(), function (i, j) {
								var reg = /\[(\w+)\]\[(\w+)\]$/g;
								var match = reg.exec(j.name);
								if (!match)
									return true;
								match[1] = "x" + parseInt(match[1]);
								if (typeof data[match[1]] == 'undefined') {
									data[match[1]] = {};
								}
								data[match[1]][match[2]] = j.value;
							});
							var result = template ? [] : {};
							$.each(data, function (i, j) {
								if (j) {
									if (!template) {
										if (j.key != '') {
											result[j.key] = j.value;
										}
									} else {
										result.push(j);
									}
								}
							});
							textarea.val(JSON.stringify(result));
						};
						//监听文本框改变事件
						$(document).on('change keyup changed', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () {
							refresh($(this).closest(".fieldlist").data("name"));
						});
						//追加控制
						$(".fieldlist", form).on("click", ".btn-append,.append", function (e, row) {
							var container = $(this).closest(".fieldlist");
							var tagName = container.data("tag") || "dd";
							var index = container.data("index");
							var name = container.data("name");
							var template = container.data("template");
							var data = container.data();
							index = index ? parseInt(index) : 0;
							container.data("index", index + 1);
							row = row ? row : {};
							var vars = {index: index, name: name, data: data, row: row};
							var html = template ? Template(template, vars) : Template.render(Form.config.fieldlisttpl, vars);
							$(html).insertBefore($(tagName + ":last", container));
							$(this).trigger("fa.event.appendfieldlist", $(this).closest(tagName).prev());
						});
						//移除控制
						$(".fieldlist", form).on("click", ".btn-remove", function () {
							var container = $(this).closest(".fieldlist");
							var tagName = container.data("tag") || "dd";
							$(this).closest(tagName).remove();
							refresh(container.data("name"));
						});
						//渲染数据&拖拽排序
						$(".fieldlist", form).each(function () {
							var container = this;
							var tagName = $(this).data("tag") || "dd";
							$(this).dragsort({
								itemSelector: tagName,
								dragSelector: ".btn-dragsort",
								dragEnd: function () {
									refresh($(this).closest(".fieldlist").data("name"));
								},
								placeHolderTemplate: $("<" + tagName + "/>")
							});
							var textarea = $("textarea[name='" + $(this).data("name") + "']", form);
							if (textarea.val() == '') {
								return true;
							}
							var template = $(this).data("template");
							var json = {};
							try {
								json = JSON.parse(textarea.val());
							} catch (e) {
							}
							$.each(json, function (i, j) {
								$(".btn-append,.append", container).trigger('click', template ? j : {
									key: i,
									value: j
								});
							});
						});
					});
				}
			},
			switcher: function (form) {
				form.on("click", "[data-toggle='switcher']", function () {
					if ($(this).hasClass("disabled")) {
						return false;
					}
					var input = $(this).prev("input");
					input = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : input;
					if (input.size() > 0) {
						var yes = $(this).data("yes");
						var no = $(this).data("no");
						if (input.val() == yes) {
							input.val(no);
							$("i", this).addClass("fa-flip-horizontal text-gray");
						} else {
							input.val(yes);
							$("i", this).removeClass("fa-flip-horizontal text-gray");
						}
						input.trigger('change');
					}
					return false;
				});
			},
			bindevent: function (form) {

			},
			slider: function (form) {
				if ($(".slider", form).size() > 0) {
					require(['bootstrap-slider'], function () {
						$('.slider').removeClass('hidden').css('width', function (index, value) {
							return $(this).parents('.form-control').width();
						}).slider().on('slide', function (ev) {
							var data = $(this).data();
							if (typeof data.unit !== 'undefined') {
								$(this).parents('.form-control').siblings('.value').text(ev.value + data.unit);
							}
						});
					});
				}
			}
		},
		api: {
			submit: function (form, success, error, submit) {
				if (form.size() === 0) {
					Toastr.error("表单未初始化完成,无法提交");
					return false;
				}
				if (typeof submit === 'function') {
					if (false === submit.call(form, success, error)) {
						return false;
					}
				}
				var type = form.attr("method") ? form.attr("method").toUpperCase() : 'GET';
				type = type && (type === 'GET' || type === 'POST') ? type : 'GET';
				url = form.attr("action");
				url = url ? url : location.href;
				//修复当存在多选项元素时提交的BUG
				var params = {};
				var multipleList = $("[name$='[]']", form);
				if (multipleList.size() > 0) {
					var postFields = form.serializeArray().map(function (obj) {
						return $(obj).prop("name");
					});
					$.each(multipleList, function (i, j) {
						if (postFields.indexOf($(this).prop("name")) < 0) {
							params[$(this).prop("name")] = '';
						}
					});
				}
				//调用Ajax请求方法
				sent.api.ajax({
					type: type,
					url: url,
					data: form.serialize() + (Object.keys(params).length > 0 ? '&' + $.param(params) : ''),
					dataType: 'json',
					complete: function (xhr) {
						var token = xhr.getResponseHeader('__token__');
						if (token) {
							$("input[name='__token__']").val(token);
						}
					}
				}, function (data, ret) {
					$('.form-group', form).removeClass('has-feedback has-success has-error');
					if (data && typeof data === 'object') {
						//刷新客户端token
						if (typeof data.token !== 'undefined') {
							$("input[name='__token__']").val(data.token);
						}
						//调用客户端事件
						if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') {
							data.callback.call(form, data);
						}
					}
					if (typeof success === 'function') {
						if (false === success.call(form, data, ret)) {
							return false;
						}
					}
				}, function (data, ret) {
					if (data && typeof data === 'object' && typeof data.token !== 'undefined') {
						$("input[name='__token__']").val(data.token);
					}
					if (typeof error === 'function') {
						if (false === error.call(form, data, ret)) {
							return false;
						}
					}
				});
				return true;
			},
			bindevent: function (form, success, error, submit) {
				form = typeof form === 'object' ? form : $(form);
				var events = Form.events;
				events.bindevent(form);
				events.validator(form, success, error, submit);
				events.editor(form);
				events.board(form);
				events.tagsinput(form);
				events.selectpicker(form);
				events.iconpicker(form);
				events.daterangepicker(form);
				events.selectpage(form);
				events.cxselect(form);
				events.citypicker(form);
				events.datetimepicker(form);
				events.plupload(form);
				events.fieldlist(form);
				events.slider(form);
				events.switcher(form);
			},
			custom: {},
			setFile: function(fileList, param){
				var file = $('#fileList_'+param.name);
				var field = $('#field_'+param.name);
				var value = field.val() ? field.val().split(",") : [];

				if(param.limit == 1){
					if(param.type == 'image'){
						var html = '<div class="item"><div class="thumb" data-id="'+fileList[0].id+'"><div class="close"><i class="fa fa-close"></i></div><img src="'+fileList[0].url+'" /></div></div>';
					}else{
						var html = '<div class="item"><div class="attach" data-id="'+fileList[0].id+'"><div class="close"><i class="fa fa-close"></i></div><span>'+fileList[0].name+'</span></div></div>';
					}
					
					file.html(html);
					field.val(fileList[0].id);
				}else{
					for(var i = 0; i < fileList.length; i++){
						if(!value.includes((fileList[i].id).toString())){
							if(param.type == 'image'){
								var html = '<div class="item"><div class="thumb" data-id="'+fileList[i].id+'"><div class="close"><i class="fa fa-close"></i></div><img src="'+fileList[i].url+'" /></div></div>';
							}else{
								var html = '<div class="item"><div class="attach" data-id="'+fileList[i].id+'"><div class="close"><i class="fa fa-close"></i></div><span>'+fileList[i].name+'</span></div></div>';
							}
							value.push(fileList[i].id);
							file.append(html);
						}
					}
					field.val(value.join(','));
				}
				if(param.type == 'image'){
					Form.events.imageDel();
				}else if(param.type == 'file'){
					Form.events.fileDel();
				}
				layer.close(layer.index);
			}
		},
	};

	window.Form = Form;

	return Form;
});