/* dformSelect
 * --------------------------------------------------------------------- */
$.fn.dformSelect = function() {
	return this.each(function() {
		if ($.browser.msie && $.browser.version == '6.0') {
			return;
		}

		var me = $(this);
		var currentSelected = me.find(':selected');
		var span = $('<span></span>')
			.addClass('dform-select')
			.css('position', 'relative')
			.css('display', 'inline-block')
			.attr('id', 'dform-' + me.attr('id'));
		var inner = $('<span></span>')
			.addClass('dform-select-inner')
			.css('display', 'inline-block')
			.text(currentSelected.text())
			.appendTo(span);
		me
			.after(span)
			.css('position', 'absolute')
			.css('opacity', '0')
			.css('top', '0')
			.css('left', '0')
			.css('fontSize', span.css('font-size'));

		var width = parseInt(me.width());
		if (!$.browser.mozilla) {
			width -=
				parseInt(span.css('padding-left')) +
				parseInt(span.css('padding-right'));
		}
		inner.width(width);

		var height = parseInt(span.height()) +
			parseInt(span.css('padding-top')) +
			parseInt(span.css('padding-bottom'));
		me.height(height).change(function() {
			inner.text(me.find(':selected').text())
				.parent().addClass('changed');
		});
		me.appendTo(span);
	});
};

$(function() {
	$('select').dformSelect();

	$('input[type="text"], input[type="password"]').addClass('text');
	$('input[type="submit"], input[type="button"]').addClass('button');
	$('input[type="radio"]').addClass('radio');
	$('input[type="checkbox"]').addClass('checkbox');
	$('input[type="file"]').addClass('file');
	$('textarea').addClass('textarea');
	$('input, textarea').focus(function() {
		$(this).addClass('focus');
	}).blur(function() {
		$(this).removeClass('focus');
	});
});

/* dformMultifile
 * --------------------------------------------------------------------- */
$.fn.dformMultifile = function(opt) {
	if (this.length == 0)
		return this;

	if (!$.isset(opt))
		opt = {};

	var conf = {
		'replaceSubmit': false,
		'limit': 0,
		'name': 'file',
		'add': '<a>Add File</a>',
		'del': '<a>Delete File</a>'
	};
	$.extend(true, conf, opt);
	conf.obj = this.addClass('dform-multifile');

	/* limit
	 * ----------------------------------------------------------------- */
	this.bind('dform-multifile-limit', function() {
		var sets = conf.obj.find('.dform-multifile-set');
		var btn = conf.obj.find('.dform-multifile-add');
		if (conf.limit == 0 || sets.length < conf.limit) {
			btn.show();
		} else {
			btn.hide();
		}
	});

	/* file ui
	 * ----------------------------------------------------------------- */
	$(conf.add).addClass('dform-multifile-add').click(function() {
		/* file */
		var _file = $('<input type="file" />')
			.addClass('dform-multifile-input')
			.attr('name', conf.name + '[]')
			.dform();

		/* set */
		var _set = $('<div></div>')
			.addClass('dform-multifile-set')
			.append(_file);

		/* delete */
		_set.append($(conf.del).addClass('dform-multifile-del')
			.click(function() {
				$(this).parent().remove();
				conf.obj.trigger('dform-multifile-limit');
				return false;
			})
		);

		$(this).before(_set);
		if (!$.browser.msie && !navigator.userAgent.match(/windows/i))
			_file.click()
//		if ($.browser.msie || navigator.userAgent.match(/windows/i))
//			_file.change();

		/* limit */
		conf.obj.trigger('dform-multifile-limit');

		return false;
	}).appendTo(this);

	return this;
}

/* dform
 * --------------------------------------------------------------------- */
$.fn.dform = function(opt) {
	if (this.length == 0)
		return this;

	if (!$.isset(opt))
		opt = {};

	opt.debug = false;
	opt.obj = this;
	this.addClass('dform');

	/* detect type */
	switch (this.get(0).tagName) {
	case 'INPUT':
		opt.type = this.attr('type');
		break;
	default:
		opt.type = this.get(0).tagName.toLowerCase();
		break;
	}

	switch (opt.type) {
	case 'form':
		this.dformInit({
			'breakError': true,
			'autoPositionErrorBox': true,
			'action': '',
			'submit': function(me) {
				if (opt.debug)
					alert(opt.obj.serialize());
				return true;
			}
		}, opt)
		.submit(function() {
			if ($(this).data('ignoresubmit'))
				return false;

			var conf = $(this).data('dform-conf');

			$(this).data('dform-error', false);
			$(this).find('.hasDatepicker').each(function() {
				$(this).datepicker('disable');
			});
			$(this).find('input, textarea, select').each(function() {
				if (conf.breakError == true &&
					conf.obj.data('dform-error') == true) {
					return;
				}
				$(this).data('dform-on-submit', true);
				if (!$(this).data('dform-pattern-skip'))
					$(this).focus().change();//.blur();
				$(this).data('dform-on-submit', false);
			});
			$(this).find('.hasDatepicker').each(function() {
				$(this).datepicker('enable');
			});
			if ($(this).data('dform-error')) {
				$($(this).find('input.dform-error,' +
					' textarea.dform-error, select.dform-error')
					.get(0)).focus();
				return false;
			}

			$(this).find('input, textarea').each(function() {
				$(this).trigger('unsetLabel');
			});

			var disabled = $(this).find(':disabled')
				.removeAttr('disabled');
			var ret = $.isempty(conf.submit) ?
				true : conf.submit($(this));
			if (ret == false) {
				disabled.attr('disabled', 'disabled');
				$(this).find('input, textarea').each(function() {
					$(this).trigger('setLabel');
				});
			}

			return ret;
		});
		break;

	case 'hidden':
		this.dformInit({
			'pattern': '',
			'valid': {
				'is': function() { return true; },
				'msg': '잘못된 형식입니다.'
			},
			'required': { 'is': true, 'msg': '필수 입력사항입니다.' },
			'change': function() {
				if (opt.debug)
					alert($(this).attr('name') + ':' + $(this).val());
				return true;
			}
		}, opt)
		.dformConf('required')
		.dformConf('pattern')
		.dformConf('valid')
		.dformConf('change');
		break;

	case 'text':
	case 'password':
	case 'textarea':
		this.dformInit({
			'label': '',
			'autotab': 0,
			'pattern': '',
			'valid': {
				'is': function() { return true; },
				'msg': '잘못된 형식입니다.'
			},
			'required': { 'is': true, 'msg': '필수입력 사항입니다.' },
			'change': function() {
				if (opt.debug)
					alert($(this).attr('name') + ':' + $(this).val());
				return true;
			}
		}, opt)
		.dformConf('label')
		.dformConf('autotab')
		.dformConf('required')
		.dformConf('pattern')
		.dformConf('valid')
		.dformConf('change');
		break;

	case 'select':
		this.dformInit({
			'required': { 'is': true, 'msg': '필수입력 사항입니다.' },
			'change': function() {
				if (opt.debug)
					alert($(this).attr('name') + ':' + $(this).val());
				return true;
			}
		}, opt)
		.dformConf('required')
		.dformConf('change');
		break;

	case 'checkbox':
		this.dformInit({
			'required': { 'is': false, 'msg': '' }
		}, opt)
		.dformConf('required');
		break;

	case 'file':
		this.dformInit({}, opt);
		break;

	case 'radio':
		this.dformInit({}, opt);
		break;
	}

	/* ignoresubmit */
	var conf = this.data('dform-conf');
	if ($.isset(conf) && conf.ignoresubmit) {
		this.focus(function() {
			$(this).parents('form').data('ignoresubmit', true);
		});
		this.blur(function() {
			$(this).parents('form').data('ignoresubmit', false);
		});
	}

	return this;
}

/* init
 * --------------------------------------------------------------------- */
$.fn.dformInit = function(conf, opt) {
	var target = $('<div></div>').addClass('dform-error').hide();

	if (this.parent().length > 0 &&
		this.parent().get(0).tagName == 'TD')
		this.wrap($('<div></div>').addClass('dform-wrap'));

	$.extend(true, conf, opt);
	switch (conf.type) {
	case 'form':
		this.data('ignoresubmit', false);
		var _btns = this.find(/*'input[type="image"], ' + */
			'input[type="submit"], input[type="button"]');
		_btns.each(function() {
			var _btn = $(this);
			_btn.addClass('button');
			if (conf.replaceSubmit) {
				_btn
				.after(target)
				.after($('<div></div>').addClass('button-box')
					.append($('<div></div>').addClass('button'))
					.append($('<a></a>')
						.focus(function() { $(this).blur(); })
						.click(function() {
							if (_btn.attr('type') == 'submit')
								conf.obj.trigger('submit');
							else
								_btn.trigger('click');
							return false;
						})
						.html(_btn.attr('value'))
					)
				)
				.wrap($('<div></div>')
					.width(1)
					.height(1)
					.css('overflow', 'hidden')
					.css('opacity', 0)
					.css('filter','alpha(opacity=0)')
				);
			}
		});
		break;
	case 'select':
		/* TODO: some skin */
	case 'hidden':
	case 'text':
	case 'password':
	case 'textarea':
		this.after(target);
		break;
	case 'checkbox':
		this.data('dform-other-self', $('<input type="hidden" />')
			.attr('name', '_' + this.attr('name'))
			.val(this.attr('checked') ? 'on' : 'off')
		);
		this.after(target)
			.after(this.data('dform-other-self')).change(function () {
			$(this).data('dform-other-self')
				.val($(this).attr('checked') ? 'Y' : 'N');
		});
		break;
	case 'file':
		break;
	case 'radio':
		break;
	}

	target.wrap($('<div></div>').addClass('dform-error-box').hide());
	target.after($('<div></div>').addClass('dform-error-tail').hide());
	this.data('dform-error-target', target);
	return this.data('dform-conf', conf).addClass(conf.type);
}

/* error
 * --------------------------------------------------------------------- */
$.fn.dformError = function(key, msg) {
	var target = this.data('dform-error-target');
	var box = target.parent();
	var tail = box.find('.dform-error-tail');
	var form = this.parents('form');
	var conf = form.data('dform-conf');

	if (conf && conf.autoPositionErrorBox == true) {
		box
			.css('top',
				(this.offset().top -
				 this.parent().offset().top +
				 this.outerHeight()) + 'px')
			.css('left',
				(this.offset().left -
				 this.parent().offset().left) + 'px')
		;
	}

	this.focus(function() {
		if ($(this).hasClass('dform-error'))
			box.hide();
	}).blur(function() {
		if ($(this).hasClass('dform-error'))
			box.show()
	});

	if (msg && msg != '') {
		this.data('dform-error-' + key, true);
		/* add error */
		form.data('dform-error', true);
		this.addClass('dform-error');
		target.html(msg).show();
		if (form.hasClass('dform-tail')) {
			var pos = tail.parent().parent().css('position');
			if (pos == 'static')
				tail.parent().parent().css('position', 'relative');
			tail.show();
		}
		box.show();
	} else {
		/* remove error */
		if (this.data('dform-error-' + key)) {
			this.data('dform-error-' + key, false);
			this.removeClass('dform-error');
			target.hide();
			tail.hide();
			box.hide();
		}
	}
	return this;
}

/* conf
 * --------------------------------------------------------------------- */
$.fn.dformConf = function(key) {
	var conf = this.data('dform-conf');

	switch (key) {
	case 'change':
		if (!$.isempty(conf.change))
			this.change(conf.change);
		break;
	case 'label':
		if (!$.isempty(conf.label) && $.isempty(conf.value)) {
			if ($.isempty(this.val()) ||
					$.trim($(this).val()) == conf.label)
				this.val(conf.label).addClass('dform-label');
			this
				.bind('unsetLabel', function() {
					if ($.trim($(this).val()) == conf.label &&
						$(this).hasClass('dform-label'))
						$(this).val('').removeClass('dform-label');
				})
				.bind('setLabel', function() {
					if ($.trim($(this).val()) == '')
						$(this).val(conf.label).addClass('dform-label');
				})
				.focus(function() {
					$(this).trigger('unsetLabel');
				})
				.blur(function() {
					$(this).trigger('setLabel');
				});
		}
		break;
	case 'autotab':
		if (conf.autotab > 0) {
			this.keyup(function(e) {
				if (e.keyCode >= 49 && e.keyCode <= 221) {
					var me = $(this);
					if (me.val().length >= conf.autotab) {
						me.parents('.dform-wrap').next()
							.find('input.text').select();
					}
				}
			});
		}
		break;
	case 'pattern':
		this.change(function() {
			if (!$(this).is(':visible') ||
				$(this).is(':disabled'))
				return true;

			if ($.isempty(conf.pattern.is))
				return true;

			if ($.isempty($(this).val()) ||
				$(this).val().match(conf.pattern.is)) {
				$(this).dformError(key);
				return true;
			}

			$(this).dformError(key, conf.pattern.msg);
			return false;
		});
		break;
	case 'valid':
		this.change(function() {
			if (!$(this).is(':visible') ||
				$(this).is(':disabled'))
				return true;

			if ($.isempty(conf.valid.is))
				return true;

			if ($.isempty($(this).val()) ||
				conf.valid.is($(this))) {
				$(this).dformError(key);
				return true;
			}

			$(this).dformError(key, conf.valid.msg);
			return false;
		});
		break;
	case 'required':
		if (conf.required.is) {
			this.addClass('dform-required');
			$('label[for="' + this.attr('id') + '"]')
				.addClass('dform-required');
		}

		this.change(function() {
			if (!$(this).is(':visible') ||
				$(this).is(':disabled'))
				return true;

			if (!conf.required.is)
				return true;

			var valid = false;
			switch (conf.type) {
			case 'checkbox':
				if ($(this).is(':checked'))
					valid = true;
				break;
			default:
				if (!$.isempty($(this).val()))
					valid = true;
				break;
			}
			if (valid) {
				$(this).dformError(key);
				return true;
			}

			$(this).dformError(key, conf.required.msg);
			return false;
		});
		break;
	}

	return this;
}

/* disabled
 * --------------------------------------------------------------------- */
$.fn.dformDisabled = function(disabled) {
	if (disabled == true) {
		$(this).attr('disabled', 'disabled').addClass('disabled');
	} else {
		$(this).removeAttr('disabled').removeClass('disabled');
	}
};

/* extend
 * --------------------------------------------------------------------- */
$.extend({
	regxpat: function(type) {
		switch (type) {
		case 'email':
			return /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
		case 'name':
			return /^[-,\.\ A-Za-z가-힝0-9]+$/;
		case 'nameEnglish':
			return /^[-,\.\ A-Za-z0-9]+$/;
		case 'userid':
			return /^[A-Za-z]{1}[A-Za-z0-9]{2,31}$/;
		case 'passwd':
			return /^.{6,255}$/;
		case 'rn':
			return /^[0-9]{6}-[0-9]{7}$/;
		case 'crn':
			return /^[0-9]{3}-[0-9]{2}-[0-9]{5}$/;
		case 'phone':
			return /^[0-9-+~, ]+$/;
		case 'phoneStrict':
			return /^[0-9]{2,4}-[0-9]{3,4}-[0-9]{4}$/;
		case 'card':
			return /^[0-9-]+$/;
		case 'zipcode':
			return /^[0-9]{3}-[0-9]{3}$/;
		case 'digit':
			return /^[-]{0,1}[0-9]+$/;
		case 'digitUnsigned':
			return /^[0-9]+$/;
		case 'hex':
			return /^[-]{0,1}[0-9A-Fa-f]+$/;
		case 'hexUnsigned':
			return /^[-]{0,1}[0-9A-Fa-f]+$/;
		case 'currency':
			return /^[0-9,]+$/;
		case 'float':
			return /^[-]{0,1}[0-9]+[\.]{0,1}[0-9]*$/;
		case 'floatUnsigned':
			return /^[0-9]+[\.]{0,1}[0-9]*$/;
		case 'date':
			return /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
		case 'datetime':
			return /^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$/;
		case 'ipaddr':
			return /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
		case 'hostname':
			return /^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$/;
		}

		return /.*/;
	},
	validpackage: function(type) {
		switch (type) {
		case 'ipv4':
			return function(me) {
				var val = me.val();
				if (!val.match($.regxpat('ipaddr')))
					return false;
				return true;
			};
		case 'ipv4.part':
			return function(me) {
				var val = me.val();
				if (!val.match($.regxpat('digitUnsigned')))
					return false;
				val = parseInt(val);
				return (val >= 0 && val <= 255);
			};
		case 'hwaddr':
			return function(me) {
				/* TODO */
				return true;
			};
		case 'hwaddr.part':
			return function(me) {
				var val = me.val();
				if (val.length != 2 ||
					!val.match($.regxpat('hexUnsigned')))
					return false;
				return true;
			};
		case 'port':
			return function(me) {
				var val = me.val();
				if (!val.match($.regxpat('digitUnsigned')))
					return false;
				val = parseInt(val);
				return (val >= 0 && val <= 65535);
			};
		case 'ssid':
			return function(me) {
				var val = me.val();
				if (!val.match(/^[a-zA-Z0-9가-힝\-_\ ]{1,32}$/))
					return false;
				return true;
			};
		}
	},
	dformPreset: function(type, extra) {
		switch (type) {
		case 'ipv4':
		case 'hwaddr':
		case 'port':
		case 'ssid':
			return {
				'valid': $.dformValid(type)
			};
		case 'ipv4.part':
			return {
				'valid': $.dformValid(type),
				'autotab': 3
			};
		case 'hwaddr.part':
			return {
				'valid': $.dformValid(type),
				'autotab': 2
			};
		case 'submit.ajax':
			return {
				'submit': function(me) {
					if (typeof(extra) == 'object' &&
						typeof(extra.valid) == 'function' &&
						!extra.valid(me))
						return false;

					var btn = me.find('input[type="submit"],' +
						' input[type="image"]').parent().find('*');
					btn.css('visibility', 'hidden');
					btn.parent().addClass('loading');
					$.post(me.attr('action'), me.serialize(),
							function(data) {
						btn.css('visibility', 'visible');
						btn.parent().removeClass('loading');
						if ($.trim(data) != '__OK__') {
							alert(data);
							return;
						}

						if (typeof(extra) == 'string') {
							alert(extra);
						} else if (typeof(extra) == 'object' &&
							typeof(extra.msg) == 'string') {
							alert(extra.msg);
						} else {
							alert('설정되었습니다.');
						}
					}, 'text');
					return false;
				}
			}
		}
	},
	ferrmsg: function(type, lang) {
		switch (type) {
		case 'email':
			switch (lang) {
			case 'english':
				return 'Invalid email format.';
			default:
				return '올바른 전자우편 형식이 아닙니다.';
			}
		case 'name':
			switch (lang) {
			case 'english':
				return 'Invalid name format.';
			default:
				return '올바른 이름의 형식이 아닙니다.';
			}
		case 'userid':
			switch (lang) {
			case 'english':
				return 'Invalid ID format.';
			default:
				return '올바른 ID 형식이 아닙니다.';
			}
		case 'passwd':
			switch (lang) {
			case 'english':
				return 'Invalid password format.';
			default:
				return '올바른 비밀번호 형식이 아닙니다.';
			}
		case 'rn':
		case 'crn':
			switch (lang) {
			case 'english':
				return 'Invalid registration number format.';
			default:
				return '올바른 등록번호 형식이 아닙니다.';
			}
		case 'phone':
			switch (lang) {
			case 'english':
				return 'Invalid phone number format.';
			default:
				return '올바른 전화번호 형식이 아닙니다.';
			}
		case 'zipcode':
			switch (lang) {
			case 'english':
				return 'Invalid zipcode format.';
			default:
				return '올바른 우편번호 형식이 아닙니다.';
			}
		case 'ipv4.part':
			switch (lang) {
			case 'english':
				return 'Invalid ip address format.';
			default:
				return '올바른 IP 주소 형식이 아닙니다.';
			}
		case 'hwaddr.part':
			switch (lang) {
			case 'english':
				return 'Invalid hardware address format.';
			default:
				return '올바른 MAC 주소 형식이 아닙니다.';
			}
		}

		switch (lang) {
		case 'english':
			return 'Invalid format.';
		default:
			return '올바른 형식이 아닙니다.';
		}
	},
	dformPattern: function(type, lang) {
		return {
			'is': $.regxpat(type),
			'msg': $.ferrmsg(type, lang)
		};
	},
	dformValid: function(type, lang) {
		return {
			'is': $.validpackage(type),
			'msg': $.ferrmsg(type, lang)
		};
	},
	datepicker_english: {
		'showMonthAfterYear': true,
		'dateFormat': 'yy-mm-dd'
	},
	datepicker_korean: {
		'currentText': '오늘',
		'showMonthAfterYear': true,
		'yearSuffix': '년',
		'dayNamesMin': ['일', '월', '화', '수', '목', '금', '토'],
		'monthNames': ['1월', '2월', '3월', '4월', '5월',
			'6월', '7월', '8월', '9월', '10월', '11월', '12월'],
		'monthNamesShort': ['1월', '2월', '3월', '4월', '5월',
			'6월', '7월', '8월', '9월', '10월', '11월', '12월'],
		'dateFormat': 'yy-mm-dd'
	}
});

/* dformLoading
 * --------------------------------------------------------------------- */
$.fn.dformLoading = function() {
	this.addClass('dform-loading').attr('disabled', 'disabled');
}

$.fn.dformLoaded = function() {
	this.removeClass('dform-loading').removeAttr('disabled');
}

$.fn.dformIsLoading = function() {
	return this.hasClass('dform-loading');
}

