if(window.help !== undefined){
	help.prototype.list.push("FimsFormFields 클래스 : FormFields클래스를 상속받은 FIMS프로젝트 내에서 사용하는 FormFields클래스");
	help.prototype.list.push("pageObject 객체 : HTML화면별 스크립트 모음");
	help.prototype.list.push("DoctxFinder 클래스 : DomQuery를 상속받은 클래스. pageObject객체의 내부 요소는 해당 클래스의 인스턴스이다.");
}

/**************************************************************************
* FimsFormFields
**************************************************************************/
class FimsFormFields extends FormFields {
	
	help(){
		FimsFormFields.help();
	}
	
	static help(){
		console.log("FimsFormFields 클래스 : FormFields클래스를 상속받은 FIMS프로젝트 내에서 사용하는 FormFields클래스");
	}
	
    /**
     * form 에 json data set
     * element tag에 data-fmt-type 으로 데이타 format이 지정된 경우 해당 포맷으로 출력
     * @param {object} formObj document.querySelector('form')
     * @param {object} jsonData json type data
     */
    set(ctrl,obj){

        document.querySelectorAll(this.children).forEach(input => {

            let prop = input.getAttribute("data-map")
                || input.name
                || input.id;
            if (!prop) return;

            let dataItem = obj instanceof DataItem,
                value = dataItem ? obj.getValue(prop) : obj[prop];

            if ("radio" == input.type) {
                if (value && value == input.value)
                    input.checked = true;
            } else if("checkbox" == input.type) {
                if (value && value == input.value)
                    input.checked = ("Y" === value);
            } else if(input.tagName == "SELECT") {
                for(let option of input.options) {
                    if(option.value == value){
                        option.selected = true;
                    } else {
                        option.selected = false;
                    }
                }
            } else {
                if(value == null){
                    value = "";
                }
                // element data-fmt-type에 정의된 format 적용
                // dt - yyyy-mm-dd HH:mm:ss, day - yyyy-mm-dd, time - HH:mm:ss, number - #,###
                if(input.dataset.fmtType){
                    const fmtType = input.dataset.fmtType;
                    switch (fmtType) {
                        case 'dt' :
							value = datetimeFormat.parse(value);
							value = datetimeFormat.format(value);
                            break;
                        case 'day' :
							value = dateFormat.parse(value);
							value = dateFormat.format(value);
                            break;
                        case 'time' :
							value = timeFormat.parse(value);
                            value = timeFormat.format(value);
                            break;
                        case 'number' :
							value = numberFormat.parse(value);
                            value = numberFormat.format(value);
                            break;
                        default:
                            break;
                    }
                }
                if(input.name){
					if($(input).hasClass('form-date')){
						$(input).datepicker("setDate", value);
					} else {
						input.value = value;
					}

                    //보안모드 마스킹 항목
                    if(input.tagName === 'INPUT' && input.id && input.classList.contains("privacy")){
                        let maskVal = value.replace(/./g, "*");
                        document.getElementById("mask-"+input.id).value = maskVal;
                    }
                }

            }
        });


    }

    get() {
        let obj = {};
        document.querySelectorAll(this.children).forEach(input => {
			if(input.tagName == "INPUT" || input.tagName == "SELECT" || input.tagName == "TEXTAREA"){
				let property = input.name || input.id;
	            let value = input.value;
	            if("radio" == input.type) {
	                if(input.checked)
	                    obj[property] = value;
	            } else if("checkbox" == input.type) {
					if(input.checked){
						if(obj[property]){
							obj[property] += ","+value;
						} else {
							obj[property] = value;
						}
					}
				} else {
	                if(input.dataset.fmtType){
	                    const fmtType = input.dataset.fmtType;
	                    switch (fmtType) {
	                        case 'dt' :
	                            value = value.replaceAll("-","").replaceAll(":","").replaceAll(" ","");
	                            break;
	                        case 'day' :
	                            value = value.replaceAll("-","");
	                            break;
	                        case 'time' :
	                            value = value.replaceAll(":","");
	                            break;
	                        case 'number' :
	                            value = value.replaceAll(",","");
	                            break;
	                        default:
	                            break;

	                    }
	                }
	                obj[property] = value;
	            }
			}
        });
        return obj;
    }
}

function newFimsFormFields(conf){
	return new FimsFormFields(conf);
}

/**************************************************************************
* data-doctx,name 어트리뷰트로 찾기
**************************************************************************/
function newDoctxFinder(doctx){
	let finder = new DoctxFinder(doctx);
	return finder;
}

class DoctxFinder extends DomQuery {
	constructor(doctx) {
		super();
		this.setContainers("[data-doctx='"+doctx+"']");	
		this.doctx = doctx;
	}
	
	help(){
		console.log("현재 doctx = "+this.doctx);
		DoctxFinder.help();
	}
	static help(){
		console.log("클래스명 = DoctxFinder");
		console.log("newDoctxFinder(doctx명)로 인스턴스를 생성할 수 있다.");
		console.log("클래스 메서드 목록");
		console.log("selectorn(요소이름) : 문자열 [data-doctx='설정된doctx'] [name='요소이름'] 을 반환한다.");
		console.log("findn(요소이름) : data-doctx속성이 설정된doctx인 요소 내에서 name속성이 요소이름인 HTML요소를 반환한다.");
		console.log("$findn(요소이름) : data-doctx속성이 설정된doctx인 요소 내에서 name속성이 요소이름인 제이쿼리 객체를 반환한다.");
		console.log("selfElement() : data-doctx속성이 설정된doctx인 HTML요소를 반환한다.");
		console.log("selfDlgId() : data-doctx속성이 설정된doctx인 HTML요소를 갖는 모달창의 id를 반환한다.");
		console.log("refDlgId(모달창이름) : data-ref-doctx속성이 설정된doctx이고 name속성이 모달창이름인 모달창의 id를 반환한다.");
	}
	
	selectorn(name){
		return this.selector("[name='"+name+"']");
	}
	findn(name){
		return this.find("[name='"+name+"']");
	}
	$findn(name){
		return $(document.querySelector("[data-doctx='"+this.doctx+"']")).find("[name='"+name+"']");
	}
	
	selfElement(){
		return document.querySelector("[data-doctx='"+this.doctx+"']");
	}
	selfDlgId(){
		if($(this.selfElement()).parents(".modal").length > 0){
			return $(this.selfElement()).parents(".modal")[0].id;
		} else {
			return "";
		}
	}
	refDlgId(dlgName){
		if($(".modal[data-ref-doctx='"+this.doctx+"'][name='"+dlgName+"']").length > 0){
			return $(".modal[data-ref-doctx='"+this.doctx+"'][name='"+dlgName+"']")[0].id;
		} else {
			return "";
		}
	}
	
}


/**************************************************************************
* jquery.fn 커스텀 - UI요소 값 세팅
**************************************************************************/
$.fn.set = function(value) {
	return this.each(function(){
		if($(this).hasClass('form-date')){
			if(value != null && value.length == 8 && value.indexOf("-") == -1){
				value = value.substring(0,4) + "-" + value.substring(4,6) + "-" + value.substring(6,8);
			}
			$(this).datepicker("setDate", value);
		} else if($(this).hasClass('option-style-select')){
			$(this).val(value);
			this.changeUI();
		} else if(this.type == "checkbox" || this.type == "radio"){
			if(this.value == value){
				$(this).prop("checked", true);
			} else {
				$(this).prop("checked", false);
			}
		} else {
			if(this.dataset.fmtType == "number"){
				$(this).val(numberFormat.format(value));
			} else {
				$(this).val(value);
			}
		}
	});
}

/**************************************************************************
* Dataset 관련 적용 기능
**************************************************************************/
const Apply = {
	fromDatasetControl : {
		load : async function(control, pageNum){
			return new Promise((resolve, reject) => {
				control.query.pageNum = pageNum;
				if (!control.query.pageNum){
					control.query.pageNum = 1;
				}
				ajax.get({
					url:control.urls.load,
					data:control.query,
					success:(resp) => {
						resolve(resp);
					}
				});
			});
		},
		reload : async function(control){
			return new Promise((resolve, reject) => {
				var orgnQuery = Object.assign({}, control.query);
				control.query.fetchSize = control.defaultFetchSize * control.query.pageNum;
				control.query.pageNum = 1;
				
				ajax.get({
					url:control.urls.load,
					data:control.query,
					success:(resp) => {
						control.query.pageNum = orgnQuery.pageNum;
						control.query.fetchSize = orgnQuery.fetchSize;
						resolve(resp);
					}
				});
			});
		}
	},
	fromDataset : {
		gridCheckbox : function(dataset, tbody, colIndex, checkedArr){
			
			var keys = checkedArr.map(item => dataset.getKey(item));
	
			$(tbody).find("tr").each(function() {
				var cb = $(this).find("td").eq(colIndex).find(":checkbox");
				cb.prop("checked", keys.includes(cb.val()));
			});
			
		},
		gridButton : function(dataset, button, checkedArr){
			var keys = checkedArr.map(item => dataset.getKey(item));
			$(button).prop("disabled", keys.length < 1);
		},
		currentRow : function(dataset, dataItem, tbody){
			if(!dataItem){
				return;
			}
			$(tbody).setCurrentRow(dataset.getKey(dataItem));
		},
		paging : function(dataset, resp, navUl, navSpan){
			
			let id = navSpan.id;
			let pf = id.substr(0,id.indexOf("PagingInfo"));
			
			$(navUl).setPagingInfo({
		        list      : dataset,
		        prefix    : pf,
		        totalSize : resp["Total"]
		    });
		    
		},
		getTbody : function(dataset, found, notFound, replacer){
			var empty = dataset.empty;
			var trs = empty ? notFound : dataset.inStrings(found, replacer);
			return trs.join();
		},
		getTodoCurrent : function(dataset, beforeCurrent, columnName){

			let di = null;
			if(beforeCurrent == null){
				return null;
			}
			if(dataset.empty){
				return null;
			}
			
			let filtered = dataset.getDataset("item").filter(item => item.data[columnName] == beforeCurrent.primaryKey);
			if(filtered.length > 0){
				di = filtered[0];
				return di;
			}
			
			let otherInfo;
			if(beforeCurrent.arrayIndex > (dataset.length - 1)){
				di = dataset.getDataset("item")[dataset.length - 1];
			} else {
				di = dataset.getDataset("item")[beforeCurrent.arrayIndex];
			}
			
			return di;
		}
	},
	toDataset : {
		current : function(dataset, dataKey){
			dataset.setCurrent(dataKey, false);
		},
		selection : function(dataset, checkbox, bool){
	
			var parentEl = $(checkbox).parent()[0];
			var isTH = parentEl.tagName == "TH" ? true : false;
		
			if(isTH) {
				var dataItems = dataset.getDataset("item");
				
				for(var i=0; i < dataItems.length; i++){
					dataItems[i].select(bool);
				}
			} else {
				var dataItem = dataset.getData(checkbox.value, "item");
				dataItem.select(bool);
			}
		},
		set : function(dataset, resp){
			dataset._byKeys = {};
			dataset._current = null;
			resp = resp || {};
			var data = dataset._getDataItems(resp,{});
			
			dataset._items = data.items;
			dataset._byKeys = data.byKeys;
		},
		add : function(dataset, resp){
			if (dataset.empty){
				this.set(dataset, resp);
				return;
			}
			var state = dataset.state;
			resp = resp || {};
			var data = dataset._getDataItems(resp,{});
			dataset._items = this._items.concat(data.items);
			dataset._byKeys = {
				...this._byKeys,
				...data.byKeys
			};
		}
	}
	
};

/**************************************************************************
* 그리드 관련 기능
**************************************************************************/
const GRID = {
	fromResp : {
		setPagingInfo : function(respList, respPaging, navUl, navSpan){
			let pagination = {};

			let id = navSpan.id;
			pagination.prefix = id.substr(0,id.indexOf("PagingInfo"));
			
			let dl = 0;
			if(respList != null) {
				dl = respList.length;
			}
			
			let s = 0;
			let ts = 0;
			if(respPaging && respPaging.start) {
				s = respPaging.start;
			}
			if(respPaging && respPaging.totalSize) {
				ts = respPaging.totalSize;
			}
			pagination.totalSize = ts;
			pagination.dataLength = s + dl;
			
			$(navUl).setPagingInfo(pagination);
		}
	},
	setCurrentRow : function(evTarget){
		if(evTarget instanceof HTMLTableCellElement){
			let tr = evTarget.parentElement;
			let tbody = tr.parentElement;
						
			for (let sibling of tdElement.parentNode.children) {
				sibling.classList.remove('current-row');
			}
			tr.classList.add('current-row');
		} else if(evTarget instanceof HTMLTableRowElement){
			let tr = evTarget;
			let tbody = tr.parentElement;
						
			for (let sibling of tdElement.parentNode.children) {
				sibling.classList.remove('current-row');
			}
			tr.classList.add('current-row');
		}
	},
	checkbox : {
		sync : function(checkboxElement, bool){
			var parentEl = $(checkboxElement).parent()[0];
			var isTH = parentEl.tagName == "TH" ? true : false;
			var tr = $(checkboxElement).parents("tr");
			var siblingTag = isTH ? "TH" : "TD";
			var siblings = tr.find(siblingTag);
			var checkboxColIndex = siblings.index(parentEl);
			
			var table = $(checkboxElement).parents("table");
			var thead = table.find("thead");
			var tbody = table.find("tbody");
			var trs = tbody.find("tr");
				
			if(isTH) {
				
				trs.each(function(){
					$(this).find("td").eq(checkboxColIndex).find(":checkbox").prop("checked", bool);
				});
				
			} else {
				var allChecked = false;
				var cbLength = 0;
				var checkedLength = 0;
	
				trs.each(function(){
					var cb = $(this).find("td").eq(checkboxColIndex).find(":checkbox");
					if(cb.length > 0){
						cbLength++;
						if(cb.is(":checked")){
							checkedLength++;
						};
					}
				});
				
				if(cbLength == checkedLength){
					allChecked = true;
				}
				
				if(allChecked){
					thead.find(":checkbox").prop("checked", true);
				} else {
					thead.find(":checkbox").prop("checked", false);
				}
				
			}
		},
		countChecked : function(checkboxElement){
			
			var parentEl = $(checkboxElement).parent()[0];
			var tr = $(checkboxElement).parents("tr").eq(0);
			var table = $(checkboxElement).parents("table").eq(0);
			
			var checkboxColIndex = null;
			if(parentEl.tagName == "TH"){
				var siblings = tr.find("TH");
				checkboxColIndex = siblings.index(parentEl);
			} else if(parentEl.tagName == "TD"){
				var siblings = tr.find("TD");
				checkboxColIndex = siblings.index(parentEl);
			} else {
				return null;
			}
			
			var tbody = table.find("tbody");	
			var trs = tbody.find("tr");
			
			var count = 0;
			trs.each(function(){
				var cb = $(this).find("td").eq(checkboxColIndex).find(":checkbox");
				if(cb.length > 0){
					if(cb.is(":checked")) {
						count++;
					}
				}
			});
			return count;
		}
	}
};
