/**
 * 이 파일을 임의로 변경하지마세요.
 * 버그 또는 수정사항 발생시 담당자(netspider)에게 문의 바랍니다.
 */
try { 
	if (typeof(Prototype) == "undefined")
		alert("[ERROR] Prototype library required.");
	if (typeof(NCScriptUtil) != "undefined")
		alert("[ERROR] NCScriptUtil.js is already included.");
} catch(e) { }

/**
 * NCScriptUtil
 * 공용 스크립트 유틸리티 클래스
 * @author netspider
 */
var NCScriptUtil = new Object;
Object.extend(NCScriptUtil, {
	/**
	 * 버전
	 */	
	Version : 1.0,
	/**
	 * 쿠키를 조작할 수 있는 기능을 제공하는 클래스
	 */
	Cookie : {},
	/**
	 * 이벤트를 조작할 수 있는 기능을 제공하는 클래스
	 */	
	Event : {},
	/**
	 * 현재  URL의 파라미터를 반환합니다.
	 * @returns 현재URL의 queryParameter
	 */
	getQueryString : function() {
		var pos = document.URL.indexOf('?');
		if (pos == -1) return "";
		return document.URL.substr(pos+1);
	},
	/**
	 * 현재 URL의 쿼리 파라미터를 Object타입으로 반환합니다.
	 * object.파라미터명으로 접근할 수 있습니다.
	 * @returns Object
	 */
	getQueryParams : function() {
		return this.getQueryString().toQueryParams();
	},
	/**
	 * 현재 페이지의 경로를 반환합니다.
	 * @returns current page path
	 */
	getPath : function() {
		var path = document.location.pathname;
		path = path.substr(0, path.lastIndexOf("/")) + "/";
		return path;
	},
	/**
	 * Object(대개 plain JSON타입)타입을 HTTP querystring 포맷으로 변환합니다.
	 * @param {String} queryObject HTTP querystring형태로 변환할 Object
	 * @returns queryObject를 변환한 HTTP querystring 형식의 문자열
	 */
	JSONToQueryString : function(queryObject) {
		return $H(queryObject).toQueryString();
	}
});

/**
 * Object에 이벤트를 등록하거나 해제합니다.
 * PrototypeJS의 Event를 사용합니다.
 * @author Yu Chi-su
 */
Object.extend(NCScriptUtil.Event, {
	/**
	 * targetObject의 eventName에 eventHandler를 리스너로 등록합니다.
	 * @param {Object | String} html element object 이거나 html element의 ID를 입력합니다.
	 * @param {String} 등록할 이벤트 이름입니다. on을 빼고 소문자로 입력합니다.
	 * @param {Function} 리스너 입니다.
	 */
	addEvent : function(targetObject, eventName, eventHandler) {
		return Event.observe(targetObject, eventName, eventHandler);
	},
	/**
	 * targetObject의 eventName에 등록된  eventHandler리스너를 제거합니다.
	 * @param {Object | String} html element object 이거나 html element의 ID를 입력합니다.
	 * @param {String} 제거할 이벤트 이름입니다. on을 빼고 소문자로 입력합니다.
	 * @param {Function} 제거할 리스너의 레퍼런스 입니다.
	 */
	removeEvent : function(targetObject, eventName, eventHandler) {
		return Event.stopObserve(targetObject, eventName, eventHandler);
	}
});
var EventUtil = NCScriptUtil.Event;

/**
 * 쿠키를 조회, 삭제, 설정 하는 기능을 제공하는 클래스
 * @author Yu Chi-su
 */
Object.extend(NCScriptUtil.Cookie, {
	/**
	 * name으로 저장된 쿠키값을 반환합니다.
	 * @param {String} name 쿠키이름
	 * @returns 조회된 쿠키 값.
	 */
	getCookie : function (name) {
		var first;
		var str = name + "=";
		if (document.cookie.length > 0) {
			find = document.cookie.indexOf(str);
			if (find == -1) return null;
			first = find + str.length;
			end = document.cookie.indexOf(";", first);
			if (end == -1) end = document.cookie.length;
			return unescape(document.cookie.substring(first, end));
		}
	},
	/**
	 * 쿠키를 설정합니다.
	 * @param {String} name 쿠키 이름
	 * @param {String} value 쿠키 값
	 * @param {Date} expireDate 쿠키 만료일
	 * @param {Boolean} 도메인 쿠키로 구우려면 true를 입력합니다.
	 * @returns Nothing
	 */
	setCookie : function(name, value, expireDate, isDomainCookie, path) {
		var isDomain = isDomainCookie | false;
		var domain = "plaync.co.kr";
		var cookieStr = name + "=" + escape(value);
		var path = path |  "/";
		cookieStr += ((expireDate == null) ? "" : (";expires=" + expireDate.toGMTString()));
		cookieStr += ((isDomainCookie) ? ";domain=" + domain : "");
		cookieStr += ";path=" + path; 
		document.cookie = cookieStr;
	},
	/**
	 * 쿠키를 설정합니다.
	 * @param {String} name 쿠키 이름
	 * @param {String} value 쿠키 값
	 * @param {Date} expireDate 쿠키 만료일
	 * @returns Nothing
	 */	
	removeCookie : function(name) {
		var exp = new Date();
		exp.setTime(exp.getTime()-1);
		document.cookie = name + "=" + ";expires=" + exp.toGMTString() + "; path=/";
	}
});
var CookieUtil = NCScriptUtil.Cookie;

/**
 * JS Aspect를 지원하는 클래스 입니다.
 */
var Aspect = {
	/**
	 * 함수가 실행되기 전에 Advice함수가 무조건 실행되도록 선언합니다.
	 * @param {Object} 일반 함수에 advice를 추가하려면 this를 객체의 메소드에 추가하려면 개체 레퍼런스 입니다.
	 * @param {String} fname
	 * @param {Function} beforeAdvice
	 * @returns Nothing
	 * @sample
	 *		function beforeAdvice(args, obj) {
	 *			alert("[beforeAdvise] i=" + args[0] + ", j=" + args[1]);
	 *			args[0] = "modified";
	 *		}
	 *		Aspect.addBeforeAdvice(this, "myfunction1", beforeAdvice);
	 */
	addBeforeAdvice : function(obj, fname, beforeAdvice) {
		var oldFunc = obj[fname];
		obj[fname] = function() {
			beforeAdvice(arguments, obj);
			return oldFunc.apply(this,arguments);
		};
	},
	/**
	 * 함수가 실행되기 전에 Advice함수를 추가해 함수 수행을 인터셉트 할 수 있습니다.
	 * @param {Object} obj
	 * @param {String} fname
	 * @param {Function} around
	 * @returns Nothing
	 * @sample 
	 *		function aroundAdvice1(args, obj, proceed) {
	 *			alert("[aroundAdvice] i=" + args[0] + ", j=" + args[1]);
	 *			return proceed();
	 *		}
	 *		Aspect.addAroundAdvice(this, "myfunction3", aroundAdvice1);
	 */
	addAroundAdvice : function(obj, fname, around) {
		var oldFunc = obj[fname];
		obj[fname] = function(args) {
			return around(arguments, obj, 
					function(){
						return oldFunc.apply(this, obj[fname].arguments);
					} 
			);
		};
	}
	/*
	,addAfterAdvice : function(obj, fname, afterAdvice) {
		var oldFunc = obj[fname];
		obj[fname] = function() {
			result = oldFunc.apply(this, arguments);
			try{
				return result;
			} finally {
				afterAdvice(result, arguments, obj);
			}
		};
	},
	*/
};

/**
 * String builder
 */
var StringBuilder = Class.create();
StringBuilder.prototype = {
	/** 
	 * @constructor
	 */
	initialize : function() {
		this._initialText = arguments[0];
		this._parts = [];
		
		if ((typeof(this._initialText) == 'string') && (this._initialText.length != 0)) {
		    _parts.push(this._initialText);
		}		
	},
	/**
	 * 버퍼에 text를 추가합니다.
	 * @param {String} text 버퍼에 추가할 문자열
	 * @return Nothing
	 */
	append : function(text) {
        if ((text == null) || (typeof(text) == 'undefined')) {
            return;
        }
        if ((typeof(text) == 'string') && (text.length==0)) {
            return;
        }
        this._parts.push(text);
    },
	/**
	 * 버퍼에 text를 추가 후 캐리지 리턴을 추가합니다.
	 * @param {String} text 버퍼에 추가할 문자열
	 * @return Nothing
	 */    
    appendLine : function(text) {
        this.append(text);
        this._parts.push('\r\n');
    },
    /**
	 * 버퍼를 비웁니다.
	 */
    clear : function() {
        this._parts.clear();
    },
	/**
	 * 버퍼에 데이터가 들어있는지 확인합니다.
	 * @return 버퍼에 데이터가 들어있으면 true 그렇지 않으면 false를 리턴합니다.
	 */
    isEmpty : function() {
        return (this._parts.length == 0);
    },
	/**
	 * 버퍼의 내용을 하나의 문자열로 반환합니다.
	 * delimeter가 지정된 경우 각 아이템을 delimeter로 구분해 하나의 문자열로 반환합니다.
	 * @param {String} delimeter 구분자
	 * @return {String} 버퍼의 내용을 하나의 문자열로 반환
	 */
    toString : function(delimiter) {
        return this._parts.join(delimiter||'');
    }
}

/**
 * 자바스크립트 문자열을 확장합니다.
 * @author Yu Chi-su
 */
Object.extend(String.prototype, {
	/**
	 * 현재 문자열이 올바른 HTML 인지 확인합니다.<b>
	 * @returns 문자열이 정상적인 HTML이면 true를 그렇지 않으면 false를 반환합니다.
	 * @example "<html></html>".isValidHTML();
	 */
	isValidHTML : function () {
		var h = this.stripTags().stripScripts();
		return (h.indexOf(">") == -1) && (h.indexOf("<") == -1);
	},
	/**
	 * 현재 문자열을 클립보드로 복사합니다.
	 * @returns Nothing
	 * @example "copy to clipboard this".copyToClipboard();
	 */
	copyToClipboard : function() {
		try {
			window.clipboardData.setData("Text", this);
		} catch(e) { }
	},
	/**
	 * 현재 문자열이 올바른 Email주소인지 확인합니다.
	 * @returns 문자열이 Email주소이면 true를 그렇지 않으면 false를 반환합니다.
	 * @sample "netspider@ncsoft".isEmail();
	 */
	isEmail : function() {
		var reg = /^[A-Za-z0-9_\-]+([.][A-Za-z0-9_\-]+)*[@][A-Za-z0-9_\-]+([.][A-Za-z0-9_\-]+)+$/;
		try {
			if (reg.test(this) == false) {
				return false;
			}
		} catch(e) { return false; }
		return true;
	}
});

/**
 * 문자열 포맷팅을 지원하는 함수 
 * @params {String} format 포매팅 문자열
 * @params {String} 매개변수1, 2, 3.....n
 * @returns 포매팅 문자열에 지정된 {0}, {1}, ... {n}을 매개변수1, 매개변수2 로 치환해 리턴합니다. 괄호 안의 숫자는 입력된 매개변수의 인덱스 입니다.
 * @sample String.format("{0} {1} {2} {1} {0} {1}", 1, 2, 3);  => 1 2 3 2 1 2로 변환됨.  
 */
String.format = function(format) {
    var result = new StringBuilder();
    for (var i=0; ; ) {
        var next = format.indexOf("{",i);
        if (next < 0) {
            result.append(format.slice(i));
            break;
        }
        result.append(format.slice(i,next));
        i = next + 1;
        
        if (format.charAt(i)=='{') {
            result.append('{');
            i++;
            continue;
        }
        var next = format.indexOf("}",i);
        var brace = format.slice(i,next).split(':');
        var argNumber = Number.parse(brace[0])+1;
        var arg = arguments[argNumber];
        if (arg == null) {
            arg = '';
        }
        if (arg.toFormattedString)
            result.append(arg.toFormattedString(brace[1]?brace[1]:''));
        else
            result.append(arg.toString());i=next+1;
    }
    return result.toString();
}

Number.parse = function(value) {
    if (!value||(value.length==0)) {
        return 0;
    }
    return parseFloat(value);
}

/**
 * Validation Manager
 */
var ValidationManager = Class.create();
ValidationManager.prototype = {
	initialize : function() {
		this.validators = new Array();
	},
	add : function(validator) {
		this.validators.push(validator);
	},
	isValid : function() {
		for (var i = 0; i < this.validators.length; i++) {
			if (!this.validators[i].doValidate())
				return false;
		}
		return true;
	}
}

/**
 * Value validator
 */
var ValueValidator = Class.create();
ValueValidator.prototype = {
	/*
		@controlName : html form control name
		@conditions :
			minLength : minium value length
			maxLength : maximum value length
			errorMessage : error message prefix
			doFocus : focus on control
	*/
	initialize : function(controlName, conditions) {
		this.controlName = controlName; 
		this.conditions = conditions;
		try {
			if (typeof(conditions.maxLength) != "undefined")
				$(this.controlName).maxLength = conditions.maxLength;
		} catch(e) { }
	},
	doValidate : function() {
		//try {
			var c = this.conditions;
			var control = $(this.controlName);
						
			if (control == null) {
				alert(String.format("[ERROR VALUE VALIDATOR] invalid control name '{0}'", this.controlName));
				return false;
			}
			if (typeof control.value == "undefined") {
				alert(Strinf.format("[ERROR VALUE VALIDATOR] control '{0}' have not value property.", this.controlName));
				return false;		
			}
			if (typeof c.minLength != "undefined" && control.value.strip().length < c.minLength) {
				if (c.errorMessage != null) {
					if (control.value.strip().length > 0) {
						alert(String.format("{0} {1}자 이상 입력해 주세요.", c.errorMessage, c.minLength));
					} else {
						if ((control.tagName == "INPUT" && control.type != "radio") || control.tagName == "TEXTAREA") {
							alert(String.format("{0} 입력해 주세요.", c.errorMessage));
						} else if ((control.tagName == "INPUT" && control.type == "radio") || control.tagName == "SELECT") {
							alert(String.format("{0} 선택해 주세요.", c.errorMessage));
						} else {}			
					}
				}
				if (c.doFocus != false) {
					control.focus();
				}
				return false;
			}
			if (typeof c.maxLength != "undefined" && control.value.strip().length > c.maxLength) {
				if (c.errorMessage != null)
					alert(String.format("{0} {1}자 이하로 입력해 주세요.", c.errorMessage, c.maxLength));
				if (c.doFocus != false) control.focus();
				return false;
			}
			return true;
		//} catch(e) {
		//	alert(e.description);
		//	return false;
		//}
	}
}

/**
 * custom function support validator
 */
var CustomValidator = Class.create();
CustomValidator.prototype = {
	initialize : function(func) {
		if (typeof func == "undefined")
			alert("function is not defined."); 
		this.validationFunction = func;
	}
	,doValidate : function() {
		if (null != this.validationFunction)
			return this.validationFunction();
		else
			return false;
	}
}


/**
 * prototype js extension
 */
Object.extend(Element.Methods, {
	/*
	 * set text autocompletion of inputbox.
	 * usage : Element.setAutoComplete(element, false);
	 *         $("elementName").setAutoComplete(false);
	 */
	setAutoComplete : function(element, autoComplete) {
		try {
			element.autocomplete = (autoComplete) ? "on" : "off";
		} catch(e) { }
	}
});
