var JsonResultParser = Class.create();
var RemoteAgent = Class.create();
var WidjetUtil = Class.create();
var PostForm = Class.create();

JsonResultParser = Class.create();
JsonResultParser.prototype = {
	initialize:function() {
		this.fileCount = 0;
	},alertError:function(json) {
		if(json.data.result == "false") {
			if(json.data.err.code == 'USER' || json.data.err.code == 'USER_MESSAGE') {
				alert(json.data.err.message);
			}else if(json.data.err.code == 'PARAMETER') {
				alert("Parameter check failed. check the item please. If you doon't know what unchekc item, contact administrator.");
				alert(json.data.err.message);
			}else if(json.data.err.code == 'UNKNOWN') {
				alert("Secure Error occured. Please contact administraotr.");
				alert(json.data.err.message);
			}else {
				alert("unknown error code : "+json.data.err.code);
				alert(json.data.err.message);
			}
		}
	}
}


RemoteAgent.prototype = {
	initialize:function() {
		this.fileCount = 0;
		this.currentFileCount = 0;
	},recieveText:function(url, params, callbackFunc) {
		if(params === undefined || params === null || params === "") {
			params = {};
		}
		new Ajax.Request(url, {
		    parameters: params,
		    requestHeaders: {Accept: 'application/json'},
		    onSuccess: function(transport){
		        var text = transport.responseText;
                callbackFunc(text);
		    }
		});
	},send:function(url, params, callbackFunc, callbackErrorFunc) {
		if(params === undefined || params === null || params === "") {
			params = {};
		}
		new Ajax.Request(url, {
		    parameters: params,
		    method:'POST',
		    requestHeaders: {Accept: 'application/json'},
		    onSuccess: function(transport){
		        var text = transport.responseText;
		        var json = text.evalJSON();
		        if(json.data.result == "true") {
		        	if(callbackFunc) {
			             callbackFunc(json);
			        }
		         }else {
		         	var resultParser = new JsonResultParser();
					resultParser.alertError(json);

					if(callbackErrorFunc) {
						callbackErrorFunc();
					}
		         }
		    }
		});
	},sendAndGo:function(url, params, returnUrl, callbackErrorFunc) {
		if(params == undefined || params == null || params == "") {
			params = {};
		}
		new Ajax.Request(url, {
		    parameters: params,
		    method:'POST',
		    requestHeaders: {Accept: 'application/json'},
		    onSuccess: function(transport){
		        var text = transport.responseText;
		        var json = text.evalJSON();
		        if(json.data.result == "true") {
		        	if(returnUrl) {
			        	document.location = returnUrl;
			        }
		         }else {
					var resultParser = new JsonResultParser();
					resultParser.alertError(json);
					
					if(callbackErrorFunc) {
						callbackErrorFunc();
					}
		         }
		    }
		});
	},sendForm:function(formId, appendParameter, callbackFunc, callbackErrorFunc) {
		if(appendParameter == undefined || appendParameter == null || appendParameter == "") {
			appendParameter = {};
		}
		var form = $(formId);
		form.request({
			method:'POST',
			enctype: "application/json",
			parameters:appendParameter,
			onComplete: function(transport) {
				var text = transport.responseText;
				var json = text.evalJSON();
				if(json.data.result == "true") {
					if(callbackFunc) {
						callbackFunc(json);
					}
				}else {
					var resultParser = new JsonResultParser();
					resultParser.alertError(json);
					
					if(callbackErrorFunc) {
						callbackErrorFunc();
					}
				}
			}
		});
	},
	/**
	 *
	 * @param formId (Require): element id of sending form
	 * @param appendParameter (Require): additional prameter object
	 * @param returnUrl (Require): the url when success
	 * @param fileTarget (Option): the object for file upload. the object have frame id and file input element id.
									the object composite like next. {frameId:'', fileInputId:''}
	 */
	sendFormAndGo:function(formId, appendParameter, returnUrl, fileTarget) {
		if(appendParameter == undefined || appendParameter == null || appendParameter == "") {
			appendParameter = {};
		}
		if(this.uploading == true) {
			alert("now, saving. please wait a miniutes.");
			return false;
		}
		this.uploading = true;
		
		var form = $(formId);
		this.process = function(fileKeys) {
			var onComplete = function(transport) {
				this.uploading = false;
				var text = transport.responseText;
				var json = text.evalJSON();
				if(json.data.result == "true") {
					document.location = returnUrl;
				}else {
					var resultParser = new JsonResultParser();
					resultParser.alertError(json);
				}
			}
			var onCompleteFunction = onComplete.bind(this);
			
			if(this.fileCount > 1) {
				this.currentFileCount += 1;
				if(this.fileCount == this.currentFileCount) {
					form.request({
						method: 'post',
						enctype: "application/json",
						parameters:appendParameter,
						onComplete: onCompleteFunction
					});
				}
			}else {
				form.request({
					method: 'post',
					enctype: "application/json",
					parameters:appendParameter,
					onComplete: onCompleteFunction
				});
			}
		}
		if(fileTarget) {
			if(fileTarget.length != undefined) {
				this.fileCount = fileTarget.length;
				this.currentFileCount = 0;
				
				var targets = $A(fileTarget);
				for(var i = 0; i < targets.size(); i += 1) {
					var uploadFunction = this.uploadFile.bind(this);		
					uploadFunction(targets[i].frameId, targets[i].fileInputId);
				}
			}else {
				var uploadFunction = this.uploadFile.bind(this);		
				uploadFunction(fileTarget.frameId, fileTarget.fileInputId);
			}
		}else {
			this.process();
		}
	},uploadFile:function(frameId, fileInputId) {
		var frame = $(frameId);
		var keys = "";
		var uploadCompleteFunction = this.uploadComplete.bind(this);
		if(Prototype.Browser.Gecko) {
			frame.contentWindow.uploadByParent(uploadCompleteFunction, fileInputId);
		}else if(Prototype.Browser.IE) {
			window.frames[frameId].uploadByParent(uploadCompleteFunction, fileInputId);
		}
	},uploadComplete:function(json, fileInputId) {
		if(json.data.result == "true") {
			var keys ="";
			$A(json.data.files).each(function(item) {
				keys += item.key+";";
			});
			var processFunction = this.process.bind(this);	
			
			$(fileInputId).value = keys;
			
			processFunction(keys);
		}else {
			var resultParser = new JsonResultParser();
			resultParser.alertError(json);
		}
	}
};

WidjetUtil.prototype = {
	initialize:function() {
	},
	/**
	 * email 폼 필드를 생성한다.
	 * @param id : DOM Element ID
	 * @param name : DOM Element Name
	 * @param required :{true | false} 필수 여부 
	 */
	createEmailField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.ValidationTextBox({
		'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required
				,'maxlength':"50"
				// ,'regExp':'[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]+'
				,'regExp':'([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})'
				,'onchange':"wasChanged('this')"	//< -------------------- PROBLEM No Work
				,'invalidMessage':"Please enter a valiad email address no more than 50 charactors"
						
               }, edit);
		return newField;
	},createNumberField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.NumberTextBox({
		'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required,
		       // 'maxlength':"25",
		       'invalidMessage':"Invalide Number Filed"
						
               }, edit);
        return newField;
	},createTextField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.TextBox({
		'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required,
		       // 'maxlength':"25",
		       'invalidMessage':"Invalide Number Filed"
						
               }, edit);
        return newField;
	},createTextAreaField:function(id, name, required) {
		// todo
		var edit = dojo.byId(id);
        var newField = new dijit.form.Textarea({
		'id':'Widjet_'+id,'class':'','name':name,'required':required
				//,
		       // 'maxlength':"25",
		       //'invalidMessage':"Invalide Number Filed"
						
               }, edit);
		return newField;
	},createDateField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.DateTextBox({
		'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required,
		       // 'maxlength':"25",
		       'invalidMessage':"Invalide Number Filed"
						
               }, edit);
        return newField;
	},createTimeField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.TimeTextBox({
		'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required,
		       // 'maxlength':"25",
		       'invalidMessage':"Invalide Number Filed"
						
               }, edit);
		return newField;
	},createNumberSpinnerField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.NumberSpinner({
		'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required,
		       // 'maxlength':"25",
		       'invalidMessage':"Invalide Number Filed"
						
               }, edit);
		return newField;
	},createSliderField:function(id, name, required) {
		var edit = dojo.byId(id);
        var newField = new dijit.form.NumberSpinner({
			'id':'Widjet_'+id,'class':'medium widjetField','name':name,'required':required,
		       // 'maxlength':"25",
		       'invalidMessage':"Invalide Number Filed"
						
               }, edit);
		return newField;
	},createDepartmentStructField:function(id, name, required) {
		var div = document.createElement("div");
		
		var departmentStructStore = new dojo.data.ItemFileReadStore({id:'departmentStructStore',url:'/proguide/action/member/struct.json?root=DEPARTMENT_STRUCT'});
	    
	    var storeName = 'departmentStructStore';
	    var loadtree = function(storeName, store) {
			if (dijit.byId("tree")) {
				dijit.byId("tree").destroy();
			}
			// var newStore = dojo.getObject(storName);
			var newTree = new AdvancedTree( {
					'store':store
					//, id:"tree"
					//, query:"{type:'ci_type'}" 
					,getIconClass:function(item) {
						if(item != null) {
							return "tree_entry_"+store.getValue(item, "type");
						}
					},onClick:function(item) {
						if(item != undefined) {
							var itemId = store.getValue(item, "id");
							var itemLabel = store.getValue(item, "label");
							if(id != null) {
								$(id).value = itemId;
							}
						}
					}
				}, document.createElement("div"));
			var target = $(id);
			var importTreeLayer = document.createElement('div', {});
			Element.Methods.insert(target, {'after':importTreeLayer});
			importTreeLayer.appendChild(newTree.domNode);
		}
	    loadtree(storeName, departmentStructStore);
	},createGroupStructField:function(id, name, required) {
		var div = document.createElement("div");
		
		var departmentStructStore = new dojo.data.ItemFileReadStore({id:'departmentStructStore',url:'/proguide/action/member/struct.json?root=GROUP_STRUCT'});
	    
	    var storeName = 'departmentStructStore';
	    var loadtree = function(storeName, store) {
			if (dijit.byId("tree")) {
				dijit.byId("tree").destroy();
			}
			// var newStore = dojo.getObject(storName);
			var newTree = new AdvancedTree( {
					'store':store
					//, id:"tree"
					//, query:"{type:'ci_type'}" 
					,getIconClass:function(item) {
						if(item != null) {
							return "tree_entry_"+store.getValue(item, "type");
						}
					},onClick:function(item) {
						if(item != undefined) {
							var itemId = store.getValue(item, "id");
							var itemLabel = store.getValue(item, "label");
							if(id != null) {
								$(id).value = itemId;
							}
						}
					}
				}, document.createElement("div"));
			var target = $(id);
			var importTreeLayer = document.createElement('div', {});
			Element.Methods.insert(target, {'after':importTreeLayer});
			importTreeLayer.appendChild(newTree.domNode);
		}
	    loadtree(storeName, departmentStructStore);
	},createMemberStructField:function(id, name, required) {
		var div = document.createElement("div");
		
		var departmentStructStore = new dojo.data.ItemFileReadStore({id:'departmentStructStore',url:'/proguide/action/member/struct.json'});
	    
	    var storeName = 'departmentStructStore';
	    var loadtree = function(storeName, store) {
			if (dijit.byId("tree")) {
				dijit.byId("tree").destroy();
			}
			// var newStore = dojo.getObject(storName);
			var newTree = new AdvancedTree( {
					'store':store
					//, id:"tree"
					//, query:"{type:'ci_type'}" 
					,getIconClass:function(item) {
						if(item != null) {
							return "tree_entry_"+store.getValue(item, "type");
						}
					},onClick:function(item) {
						if(item != undefined) {
							var itemId = store.getValue(item, "id");
							var itemLabel = store.getValue(item, "label");
							if(id != null) {
								$(id).value = itemId;
							}
						}
					}
				}, document.createElement("div"));
			var target = $(id);
			var importTreeLayer = document.createElement('div', {});
			Element.Methods.insert(target, {'after':importTreeLayer});
			importTreeLayer.appendChild(newTree.domNode);
		}
	    loadtree(storeName, departmentStructStore);
	}
}

var ScreenDirector = {
	/**
	 * 화면 전체에 특정 화면을 출력한다.
	 * 출력 내용 외에는 disabled 상태가 된다.
	 * 화면을 닫기 위해선, ScreenDirector.closeFullScreen 을 호출해야한다.
	 * @param url(필수) 내용을 출력할 page URL
	 * @param parameters(옵션) 파라미터 HashSet
	 * @param duration(옵션) 화면이 완전히 로드되는 시간. 단위 1초. 기본값 = 0.3
	 * @return container
	 */
	viewFullScreen:function(url, parameters, duration) {
		duration = (duration || 0.3);
		
		var cover = new Element('div', {id:'_full_popup_bg', className:'full_popup_bg'});
		var contentLayer = new Element('div', {id:'_full_popup_box', className:'full_popup_box'});
		var content = new Element('div', {id:'_full_popup_content', className:'full_popoup_content'});
		
		
		cover.show();
		contentLayer.show();
		cover.setOpacity(0);
		var toHeight = $$('body')[0].getStyle('height');
		cover.setStyle({width:'100%',height:'1000%'}); // ie don't support abobe than 1000%
		contentLayer.setStyle({width:'100%',height:'100%'});
		
		$$('html')[0].setStyle({overflow:"hidden"});
		$$('body')[0].setStyle({overflow:"hidden"});

		document.body.appendChild(cover);
		document.body.appendChild(contentLayer);
		
		if(Prototype.Browser.IE) {
			contentLayer.appendChild(content);
		}else {
			var td = Builder.node('td', {align:'center', height:'100%'});
			var table = Builder.node('table', {border:'0', width:'100%', height:'100%'}, [
					Builder.node('tr', {}, [
							td
						])
				]);
			contentLayer.appendChild(table);
			td.appendChild(content);
		}
		
	    cover.morph({
			width: '100%', 
			backgroundColor: '#000',
			borderWidth: '1em', borderColor: '#009',
			opacity: '0.75'
	    }, { 'duration': duration });
	    
	    contentLayer.morph({
			width: '100%',
			opacity: '1'
	    }, { 'duration': duration });
	    
	    
	    // 중앙 정렬 시작
	    var navi = contentLayer;
	    if(navi.viewportOffset().top < 0) {
		    navi.setStyle({'top':'0px'});
			var top = navi.getStyle('top').replace("px", '');
			top = new Number(top);
			    
			var toTop = navi.viewportOffset().top;
			if(toTop < 0) {
		        toTop = top + toTop * -1;
		    }else if(toTop > 0) {
		        toTop = top - toTop;
		        
		    }else {
		        toTop = top;
		    }
	
		    if(toTop < 0) {
				toTop += (0 - toTop);
		    }
		    new Effect.Move(navi, {y: toTop, mode: 'absolute',duration:'0.1' });
		}
	    // 중앙 정렬 끝
	    
	    new Ajax.Updater(content, url, {method:'get', 'parameters':parameters.toQueryString(), evalScripts:true});
	    return content;
	    
	},
	/**
	 * FullScreen 된 화면을 닫는다
	 */
	closeFullScreen:function() {
		$$('html')[0].setStyle({"overflow":""});
		$$('body')[0].setStyle({"overflow":""});
		$$('.full_popup_bg').invoke('remove');
		$$('.full_popup_box').invoke('remove');
		/*
		var cover = $('cover');
		var contentLayer = $('cover_content_layer');
		cover.update();
		cover.setStyle({
			width: '0px', height: '0px',
			backgroundColor: '#fff',
			opacity : 0.5
		});
		cover.hide();
		contentLayer.hide();
		*/
	},
	/**
	 * 화면 일부에 스크린을 띄운다.
	 * 드래그 가능하며, 띄워진 스크린 외의 내용도 사용 가능하다.
	 * ScreenDirector.closePopup 을 호출하여 띄워진 화면을 닫을 수 있다.
	 * @param url(필수) 내용을 출력할 page URL
	 * @parameters(옵션) 파라미터 HashSet
	 * @options(옵션) 옵션 Obejct
	 *     .x 팝업이 띄워질 가로 좌표. 기본값 20
	 *     .y 팝업이 띄워질 세로 좌표. 기본값 20
	 *     .direction (dir팝업 위치. x, y 좌표 우선이며, 좌표값이 없을 경우 direction 값을 기준으로 위치한다
	 *                아직 지원하지 않음.
	 *     .duration 화면이 완전히 로드되는 시간. 단위 1초. 기본값 = 0.3
	 * @callbackFunc CallBack Function. 팝업의 결과를 반영할 함수. 인자로 결과값을 넣는다.
	 * @author 편현장
	 */
	openPopup:function(url, parameters, options, callbackFunc) {
		if(!options) options = {};
		var duration = (options.duration || 0.3);
		var x = (options.x || 20);
		var y = (options.y || 20);
		x = new Number(x) + 20;
		y = new Number(y) + 20;
		var cover = new Element('div');
		//var header = new Element('div', {});
		// var btClose = new Element('span').update("[close]");
		// header.appendChild(btClose);
		//header.addClassName("dragHandle");
		// btClose.observe('click', ScreenDirector.closePopup.bindAsEventListener(this, cover));
		var content = new Element('div');
		//cover.appendChild(header);
		cover.appendChild(content);
		$$('body')[0].appendChild(cover);
		
	    cover.morph({
			borderWidth: '1em', borderColor: '#009',
			opacity: '1'
	    }, { 'duration': duration });
	    
	    new Ajax.Updater(content, url, {
	    	method:'post', 
	    	'parameters':parameters.toQueryString(), 
	    	evalScripts:true, 
	    	onComplete:function() {
	    		document.popupTemporaryCallBackFunction = callbackFunc;
	    		}
	    	});
	    
	    cover.absolutize();
	    cover.setStyle({left:x+'px', top:y+'px'});
	    return cover;
	},
	/**
	 * 띄워진 팝업을 닫는다.
	 * @param element (필수) 띄워진 팝업의 최상위 엘리먼트
	 * @param rmoeve (옵션, default:false) 내용 삭제 여부
	 * @author 편현장
	 */
	closePopup:function(element, remove) {
		remove = ( false || remove);
		if(remove) {
			element.remove();	
		}else {
			element.hide();
		}
	}
}

var FormUtils = {
	/**
	 * name 을 가진 checkbox 로 부터 체크된 값을 가져온다
	 * 값이 없을 경우 null을 반환한다
	 */
	getCheckedValue:function(name) {
		var returnValue = null;
		$$('input[name="'+name+'"]').each(function(inputElement) {
			if(inputElement.checked) {
				returnValue = inputElement.value;
			}
		});
		return returnValue;
	},getCheckedElement:function(name) {
		var returnElement = null;
		$$('input[name="'+name+'"]').each(function(inputElement) {
			if(inputElement.checked) {
				returnElement = inputElement;
			}
		});
		return returnElement;
	},
	/**
	 * name 을 가진 element 중에서 value 값을 가진 element 를 체크한다
	 */
	check:function(name, value) {
		var returnElement = null;
		$$('input[name="'+name+'"]').each(function(inputElement) {
			if(inputElement.value == value) {
				inputElement.checked = "checked";
			}
		});
	},
	/**
	 * name 을 가진 checkbox element 를 모두 토글시킨다
	 * 한개라도 선택되어있다면, 모두 선택한다.
	 * 즉, 모두 선택되어있는 상태여만 모두 해제한다
	 */
	toggleCheckboxs:function(name) {
		var allChecked = true;
		$$('input[name="'+name+'"]').each(function(inputElement) {
			if(!inputElement.checked) {
				allChecked = false;
				throw $break;
			}
		});
		
		var turn = !(allChecked);
		$$('input[name="'+name+'"]').each(function(inputElement) {
			inputElement.checked = turn;
		});
	}
}

var CommonUtils = {
	generateRandomString : function() {
		var rand_no = Math.random();
		rand_no = rand_no * 10000;
		return rand_no;
	}
}

PostForm.prototype = {
	initialize:function(action) {
		this.id = CommonUtils.generateRandomString();
		this.form = Builder.node('form', {'id':this.id, 'name':this.id, 'method':'post', enctype:'application/x-www-form-urlencoded', 'action':action});
	},set:function(name, value) {
		var element = new Element('input', {type:'hidden', name:name, value:value});
		this.form.appendChild(element);
	},equip2Document:function() {
		$$('body')[0].appendChild(this.form);
	},getId:function() {
		return this.id;
	},getForm:function() {
		return this.form;
	}
}