/**
* RemoteView5 Extensions
* 
* @author firejune(to@firejune.com)
* @copyright © 2009 RSUPPORT. All rights Reserved.
* 
* #reversion 900
*/

// for console debugging
if (window['console'] === undefined || console.log === undefined) console = {
	log: function() {}, info: function() {}, warn: function() {}, error: function() {}
};


(function($) {

	// JavaScript standard Array indexOf prototype implementation.
	if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
			i || (i = 0);
			var length = this.length;
			if (i < 0) i = length + i;
			for (; i < length; i++) if (this[i] === item) return i;
			return -1;
		};

	// Wraps the function in another, locking its execution scope to an object specified by argument.
	Function.prototype.scope = function() {
		var fn = this,
		args = Array.prototype.slice.call(arguments),
		object = args.shift();
		return function() {
			return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)));
		};
	};
	Array.prototype.shuffle = function() {
		return this.concat().sort(
				function() { return Math.random() - Math.random(); }
			);
	}

	// Allows only valid characters (i.e. numbers) to be typed into a text box.
	$.fn.numeric = function(opt) {
		opt || (opt = []);
		return this.each(function() {
			$(this).keydown(function(e) {
				var key = e.charCode || e.keyCode || 0;
				return ((key >= 48 && key <= 57) || (key >= 96 && key <= 105) || key == 9 || key == 8 || opt.indexOf(key) >= 0);
			});
		});
	};

	/**
	 * unnecessary pngFix
	 */
	if (!$.fn.pngFix) $.fn.pngFix = function() {
			return $(this);
		};

	/**
	 * formatDate (date Object, format)
	 * 
	 * Returns a date in the output format specified.
	 * The format string uses the same abbreviations as in getDateFromFormat()
	 * 
	 * Field	      | Full Form       | Short Form
	 * -------------+-----------------+-----------------------
	 * Year         | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits)
	 * Month        | MM (2 digits)   | M (1 or 2 digits)
	 * Day of Month | dd (2 digits)   | d (1 or 2 digits)
	 * Hour (1-12)  | hh (2 digits)   | h (1 or 2 digits)
	 * Hour (0-23)  | HH (2 digits)   | H (1 or 2 digits)
	 * Minute       | mm (2 digits)   | m (1 or 2 digits)
	 * Second       | ss (2 digits)   | s (1 or 2 digits)
	 * AM/PM        | a               |
	 * 
	 */

	$.fn.date = $.date = function(date, format) {
		//console.log('$.date', arguments);

		if (!date) date = new Date();
		if (!format) format = 'yyyy-MM-dd HH:mm:ss';
		var result = '', i_format = 0, c = '', token = '', y = date.getYear() + '',
		M = date.getMonth() + 1, d = date.getDate(), E = date.getDay(), H = date.getHours(),
		m = date.getMinutes(), s = date.getSeconds(), value = {}, LZ = function(x) {
			return (x < 0 || x > 9 ? '' : '0') + x;
		};

		// Convert real date parts into formatted versions
		if (y.length < 4) y = '' + (y - 0 + 1900);
		value['y'] = '' + y;
		value['yyyy'] = y;
		value['yy'] = y.substring(2, 4);
		value['M'] = M;
		value['MM'] = LZ(M);
		value['d'] = d;
		value['dd'] = LZ(d);
		value['H'] = H;
		value['HH'] = LZ(H);
		value['h'] = H == 0 ? 12 : H > 12 ? H - 12 : H;
		value["hh"] = LZ(value["h"]);
		value['a'] = H > 11 ? 'PM' : 'AM';
		value['m'] = m;
		value['mm'] = LZ(m);
		value['s'] = s;
		value['ss'] = LZ(s);

		while (i_format < format.length) {
			c = format.charAt(i_format);
			token = '';
			while ((format.charAt(i_format) == c) && (i_format < format.length)) {
				token += format.charAt(i_format++);
			}
			if (value[token] != null) result = result + value[token];
			else result = result + token;
		}

		return this[0] ? this.each(function() {
			$(this).html(result);
		}) : result;
	}


	/**
	 * dinamic file include
	 * 
	 * @param {Object} files array
	 * @param {Function} callback function
	 * 
	 * TODO: 중복파일 여부를 DOM에서 검색하지 않고 캐시에서 찾게 하기
	 * 
	 */
	$.fn.include = $.include = function(files, callback) {
		files.length && $.each(files, function(i, file) {
			console.log('$.include', file);

			if (file.tagName
				&& file.tagName.match(/SCRIPT|LINK/)
				&& !($(file.tagName + '[src=' + $(file).attr('src') + ']').length
				|| $(file.tagName + '[href=' + $(file).attr('href') + ']').length)) {

				var fire = function() {
					i + 1 == files.length && callback && callback();
					//file.type == 'text/javascript' && $(file).remove();
				}, head = document.getElementsByTagName('head')[0];

				if ($.browser.safari && navigator.userAgent.match(/Chrome/)) {
					$(head).append($(file));
					fire();
				} else {
					head.insertBefore(file = $.extend(document.createElement(file.tagName), {
						'SCRIPT': { type: file.type, src: file.src },
						'LINK': { type: file.type, href: file.href, rel: file.rel }
					}[file.tagName]), head.firstChild);

					if ($.browser.msie) file.onreadystatechange = function() {
							/loaded|complete/.test(file.readyState) && fire();
						};
					else {
						if (file.href) {
							if ($.browser.opera) file.onload = fire;
							else (function() {
								//FF, Safari, Chrome
								try {
									file.sheet.cssRule;
								} catch (e) {
									return setTimeout(fire, 20);
								};
								fire();
							})();
						} else file.onload = fire; //FF, Safari, Opera
					}
				}
			}
		});
	}

	/**
	 * display error message to around of element
	 * 
	 * @param {Object} jQuery Object
	 * @param {String} error message
	 * @param {String} 'right' or 'bottom' position
	 * 
	 */
	function $displayError(el, msg, pos) {
		console.log('$displayError', arguments);

		if (el.hasClass('error')) return;

		var containerOffset = $('#container').offset();
		var label = el.next('label[for=' + el.attr('id') + ']');
		if (label.get(0)) el = label;

		var elementOffset = el.addClass('error').offset();
		elementOffset = {
			'bottom': {
				top: elementOffset.top + el.height() + 8,
				left: elementOffset.left - containerOffset.left + 190
			},
			'right': {
				top: elementOffset.top + 2,
				left: elementOffset.left + el.width() - containerOffset.left + 200
			}
		}[pos];

		var isOverlab = false;
		$('p.error').each(function() {
			var PTY = elementOffset.top - this.offsetTop;
			if (PTY <= 0 && PTY >= 0 - this.offsetHeight) isOverlab = true;
		});

		!isOverlab && $('<p class="error">' + msg + '</p>').css(elementOffset).appendTo('#container');
	}

	/**
	 * validate
	 * 
	 * @param {String} validation type
	 * @param {Object} Input element
	 * @param {Object|RegEx|String} term
	 * @return {Boolean} isInvalid
	 * 
	 */
	$.fn.validate = $.validate = function(type, input, term, pos) {
		console.log('$.validate', arguments);

		input = $(input).removeClass('error');
		var invalidMsg = null, value = input.val(), _takeMsg = function(text, src, val) {
			invalidMsg = text.replace(src, val);
		};

		if (type != 'required' && $.trim(value).length == 0 && !(type == 'length' && term.min == undefined))
			_takeMsg("Please enter this information.");
		else ({
			'length': function() {
				value.length > term.max
					&& _takeMsg("This characters is too long. Please enter a shorter.", 'ｎ', term.max);
				value.length < term.min
					&& _takeMsg("This characters is too short. Please enter a loonger.", 'ｎ', term.min);
			},
			'limit': function() {
				value * 1 > term.max
					&& _takeMsg("This number is too big. Please enter a smaller.", 'ｎ', term.max);
				value * 1 < term.min
					&& _takeMsg("This number is too small. Please enter a bigger.", 'ｎ', term.min);
			},
			'date': function() {
				!/^[0-9]{4}-\d{2}-\d{2}$/.test(value)
					&& _takeMsg("Is not correct the date format.");
			},
			'url': function() {
				!/(www.)?.+?\..+(\s|$)/g.test(value)
					&& _takeMsg("Is not correct the URL format.");
			},
			'email': function() {
				!/^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/.test(value)
					&& _takeMsg("Is not correct the e-mail format.");
			},
			'duplicate': function() {
				term.filter(function() {return value == this.value && input[0] != this;}).length
					&& _takeMsg("Duplicate ID exists.");
			},
			'match': function() {
				value != term
					&& _takeMsg("These characters don't match the characters in the current information.");
			},
			'not': function() {
				term == 'number' && !isNaN(value * 1)
					&& _takeMsg("연속된 숫자로 지정할 수 없습니다.");
				value == term
					&& _takeMsg("중복된 문자가 있습니다.");
			},
			'required': function() {
				$.trim(value).length == 0
					&& _takeMsg("Required information is missing.");
			},
			'search': function() {
				!term.test(value)
					&& _takeMsg("Is not correct the characters format.");
			},
			'by': function() {
				!$.trim(term)
					&& _takeMsg("Required e-mail is missing.");
			}
		})[type]();

		if (!invalidMsg) return null;
		if (pos.match(/bottom|right/)) $displayError(input, invalidMsg, pos);
		//else alert(invalidMsg);
		else $.message(pos || invalidMsg, 'error');

		input.addClass('error').focus();
		return invalidMsg;
	}


	/**
	 * Simple Thickbox
	 */
	$.fn.thickbox = $.thickbox = function(elements) {
		console.log('$.thickbox', arguments);

		elements.click(function(event) {
			if ($(event.target).parent().attr('class').match(/dim/)) {
				event.preventDefault();
				event.stopPropagation();
				return false;
			}

			$.ajax({
				url: this.href || this.alt,
				type: 'get', success: function(req) {
					var overlay = $("#overlay");
					if (!overlay.length) overlay = $('<div id="overlay"></div>').appendTo(document.body);
					overlay.show();

					var dialog = $("#dialog");
					if (!dialog.length) dialog = $([
					'<div id="dialog">',
						'<div class="corner top-left"></div>',
						'<div class="corner top-right"></div>',
						'<div class="corner bottom-left"></div>',
						'<div class="corner bottom-right"></div>',
						'<div class="container"></div>',
					'</div>'
				].join('')).appendTo(document.body);
					dialog.css({ opacity: 0 }).children('.container').html($.template(req), $.i18n).end().show();
					dialog.find('input').filter(function() { if ($(this).is(':visible') && !$(this).attr('readonly')) return this; }).eq(0).focus()
					$.thickbox.center();
				}
			});

			event.preventDefault();
			event.stopPropagation();
			return false;
		});
	}

	$.thickbox.center = function() {
		console.log('$.thickbox.center', arguments);

		var dialog = $("#dialog");
		return dialog.css({
			opacity: 1,
			left: ($(window).width() - dialog.width()) / 2,
			top: ($(window).height() - dialog.height()) / 2
		});
	}

	$.thickbox.close = function() {
		console.log('$.thickbox.close', arguments);

		$("#dialog").hide();
		$("#overlay").hide();
	}

	/**
	 * Message Box
	 */
	var $messageTimeout;
	$.fn.message = $.message = function (text, type, times) {
		console.log('$.message', arguments);

		var el = $('#message');
		if (!el.length) el = $('<div id="message"><p class="left"></p><span></span><p class="right"></p></div>').appendTo('#header');
		$messageTimeout && clearTimeout($messageTimeout);
		$messageTimeout = setTimeout(function() {
			el.slideUp('fast');
		}, times || 5000);
		return el.attr('class', '').addClass(type).children('span').html(text)
		.end().show().css('left', ($(window).width() - el.width()) / 2).hide().slideDown('fast');
	}

})(jQuery);
