if(window.help !== undefined){
	help.prototype.list.push("FimsSupport 클래스 : FIMS프로젝트 내에서 공통적으로 사용할 수 있는 기능 지원");
	help.prototype.list.push("FimsPagingSupport 클래스 : 스크롤 페이징 정보 표시 지원");
}

/**************************************************************************
* FimsSupport
**************************************************************************/
class FimsSupport {
	
	static help(){
		console.log("메소드 목록");
		console.log("fnMenualDownload() : 메뉴얼 다운로드");
		console.log("mappingButtonAndMenu(버튼id, 메뉴이름) : 버튼과 메뉴를 매핑한다.");
		console.log("fnDownsizeToggle(th객체) : 테이블 컬럼 축소 여부 변경");
		console.log("fnDownsizeCheck(html테이블객체) : 테이블 렌더링 후 축소 처리할 컬럼 확인");
		console.log("countCrdnByVhrno(차량번호, 업무구분코드, 시군구코드) : 차량번호로 단속 건수 조회");
		console.log("countCvlcptDscsnByVhrno(차량번호, 업무구분코드, 시군구코드) : 차량번호로 민원상담 건수 조회");
		console.log("getVhclInfo(시군구코드, 차량번호, 기준일자) : 시군구코드, 차량번호, 기준일자로 차적 조회");
		console.log("getVhclDisabledParkingInfo(차량번호) : 장애인 차량여부 조회");
		console.log("searchFromGridTitle(키워드영문명, 키워드한글명, 메인옵션, 추가옵션) : 그리드의 특정 열 값을 키워드로 자료 조회");		
		console.log("renderForTask(렌더링영역객체, 업무class속성명) : 업무구분별 화면 렌더링");
		console.log("registShortcutKey() : 단축키 등록");
		console.log("getActiveRootTabArea() : 현재 활성화된 최상위 탭 영역을 반환한다.");
		console.log("fnJsonToFormData(json,배열이름) : son객체 안의 jsonArray를 FormData형식의 키로 치환한다.");
		console.log("fnJsonArrayToFormData(json배열,배열이름) : jsonArray를 FormData형식의 키를 갖는 json으로 치환한다.");
		console.log("getCellDefsForPrivacyCell(TD태그의 제이쿼리 객체) : 엑셀다운로드시 개인정보 포함된 셀의 컬럼명을 추출하는 함수");
		console.log("openPDF(blob객체,새 창 이름) : PDF파일 미리보기 창 열기");
		console.log("fnProgress(sse키, progress팝업화면 내용, progress응답시 처리 메소드) : 프로그레스바 표시");
	}
	
	/**************************************************************************
	* 메뉴얼 다운로드
	**************************************************************************/
	static fnMenualDownload(){
		var filenameInHeader = "";
		
		fetch(wctx.url("/file/downloadMenual.do"))
			.then((response) => {
				var header = response.headers.get('Content-Disposition');
				console.log(header);
				var parts = header.split(';');
				filenameInHeader = parts[1].split('=')[1];
				if(filenameInHeader.startsWith("\"") && filenameInHeader.endsWith("\"")){
					filenameInHeader = filenameInHeader.substring(1,filenameInHeader.length-1);
				}
				filenameInHeader = decodeURIComponent(filenameInHeader);
				return response.blob();
			})
			.then((blob) => {
				
				var URL = window.URL || window.webkitURL;
				var downloadUrl = URL.createObjectURL(blob);
				
				var a = document.createElement("a");
				a.href = downloadUrl;
	            a.download = filenameInHeader;
	            document.body.appendChild(a);
	            a.click();
	            document.body.removeChild(a);
	            
			});
		
	}
	
	/**************************************************************************
	* 버튼과 메뉴를 매핑한다.
	**************************************************************************/
	static mappingButtonAndMenu(buttonId, menuNm){
		$("#"+buttonId).on( "click", function() {
			$("#menus").find("div[data-i18n='"+menuNm+"']").parent("a").trigger("click");
		});
	}
	
	/**************************************************************************
	* 테이블 컬럼 축소 여부 변경
	**************************************************************************/
	static fnDownsizeToggle(thObj) {
		
		$(thObj).toggleClass("downsize");
		
		var thIndex = $(thObj).index();
		
		var setValue = "";
		if($(thObj).hasClass("downsize")){
			setValue = "160px";
		}
		
		var tbody = $(thObj).parent("tr").parent("thead").next("tbody");
		if(tbody.length < 1){
			return;
		}
		
		var trs = tbody.find("tr");
		
		if(trs.length < 1){
			return;
		}
		
		if(trs.length == 1 && trs.find("td").length <= 1){
			return;
		}
		
		trs.each(function(){
			$(this).find("td:eq("+thIndex+")").css("max-width",setValue);
		});	
		
	}
	
	/**************************************************************************
	* 테이블 렌더링 후 축소 처리할 컬럼 확인
	**************************************************************************/
	static fnDownsizeCheck(tableObj) {
		$(tableObj).find("thead tr th").each(function(){
			var thIndex = $(this).index();
			if($(this).hasClass("downsize")){
				var trs = $(this).parent("tr").parent("thead").next("tbody").find("tr");
				trs.each(function(){
					$(this).find("td:eq("+thIndex+")").css("max-width","160px");
				});
			}
		});
	}
	
	/**************************************************************************
	* 차량번호로 단속 건수 조회
	**************************************************************************/
	static async countCrdnByVhrno(vhrno, taskSeCd, sggCd){
	    return new Promise((resolve, reject) => {
	        json.get({
	            url: wctx.url("/crdn/crdn06/010/nocs.do"),
	            data: {
	                vhrno : vhrno,
	                taskSeCd : taskSeCd,
	                sggCd : sggCd
	            },
	            success: function(resp, textStatus, jqXHR) {
	                resolve(resp);
	            },
	            error: function(jqXHR, textStatus, error) {
	            }
	        });
	    });
	}
	
	/**************************************************************************
	* 차량번호로 민원상담 건수 조회
	**************************************************************************/
	static async countCvlcptDscsnByVhrno(vhrno, taskSeCd, sggCd){
	    return new Promise((resolve, reject) => {
	        json.get({
	            url: wctx.url("/sprt/sprt04/010/nocs.do"),
	            data: {
	                vhrno : vhrno,
	                taskSeCd : taskSeCd,
	                sggCd : sggCd
	            },
	            success: function(resp, textStatus, jqXHR) {
	                resolve(resp);
	            },
	            error: function(jqXHR, textStatus, error) {
	            }
	        });
	    });
	}
	
	/**************************************************************************
	* 시군구코드, 차량번호, 기준일자로 차적 조회
	**************************************************************************/
	static async getVhclInfo(sggCd, vhrno, levy_stdde){
		return new Promise((resolve, reject) => {
			json.post({
				url: wctx.url("/payer/vehicle.do"),
				data: {
					sggCd : sggCd,
					vhrno : vhrno,
					levy_stdde : levy_stdde
				},
				success: function(resp, textStatus, jqXHR) {
					resolve(resp);
				},
				error: function(jqXHR, textStatus, error) {
				}
			});
		});
	};
	
	/**************************************************************************
	* 장애인 차량여부 조회
	**************************************************************************/
	static async getVhclDisabledParkingInfo(vhrno){
	    return new Promise((resolve, reject) => {
	        json.get({
	            url: wctx.url("/intf/disabledParking/parkingInfo"),
	            data: {
	                vehicleNo : vhrno
	            },
	            success: function(resp, textStatus, jqXHR) {
	                resolve(resp);
	            },
	            error: function(jqXHR, textStatus, error) {
	            }
	        });
	    });
	}
	
	/**************************************************************************
	* 그리드의 특정 열 값을 키워드로 자료 조회
	**************************************************************************/
	static searchFromGridTitle(byValue, byOutputValue, mainOption, subOption){
		var tr = event.target.parentElement;

		if($(tr).attr("data-search-target") == null || $(tr).attr("data-search-target") == ""){
			
			var trDataset = tr.dataset;

			var byElementId = trDataset.by;
			var byOutputElementId = trDataset.byOutput;
			var mainOptionElementId = trDataset.mainOption;
			var subOptionElementId = trDataset.subOption;

			document.getElementById(byElementId).value = StringSupport.snakeToCamel(byValue);
			document.getElementById(byOutputElementId).value = byOutputValue;

			document.getElementById(mainOptionElementId).value = mainOption;
			document.getElementById(subOptionElementId).value = subOption;
		} else {

			let byEl = $($(tr).attr("data-search-target")).find("[name='by']")[0];
			let byOutputEl = $($(tr).attr("data-search-target")).find("[name='byOutput']")[0];
			let mainOptionEl = $($(tr).attr("data-search-target")).find("[name='mainOption']")[0];
			let subOptionEl = $($(tr).attr("data-search-target")).find("[name='subOption']")[0];
			
			byEl.value = StringSupport.snakeToCamel(byValue);
			byOutputEl.value = byOutputValue;
			mainOptionEl.value = mainOption;
			subOptionEl.value = subOption;
		}
		
	}
	
	/**************************************************************************
	* 업무구분별 화면 렌더링
	**************************************************************************/
	static renderForTask(areaId, taskClass){
		var slotAreas;
		if(typeof areaId == "string"){
			slotAreas = $("#"+areaId).find("[slot]");
		} else {
			slotAreas = $(areaId).find("[slot]");
		}
		
		slotAreas.each(function(){
			if($(this).hasClass("if-empty-col0")){
				if(!isEmpty($(this).attr("data-original-col-size"))){
					let colSize = $(this).attr("data-original-col-size");
					$(this).removeClass("col-0");
					$(this).addClass(colSize);
					$(this).attr("data-original-col-size","");
				}
			}
		});
		
		slotAreas.each(function(){
			var tempHtml = "";
			$(this).find("template").each(function(){
				tempHtml += this.cloneNode(true).outerHTML;
			});

			var taskTemplate = $(this).find("template."+taskClass);
			if(taskTemplate.length < 1){
				this.innerHTML = tempHtml;
				return;
			}

			var inHtml = $(taskTemplate[0].content).find("slot")[0].innerHTML;
			this.innerHTML = tempHtml + inHtml;
			
		});
		
		slotAreas.each(function(){
			if($(this).hasClass("if-empty-col0")){
				if($(this).children().not("template").length == 0){
					let colSize = "";
					for(let col of BOOTSTRAP_COLS){
						if($(this).hasClass(col)){
							colSize = col;
							break;
						}
					}
					
					$(this).attr("data-original-col-size", colSize);
					$(this).removeClass(colSize);
					$(this).addClass("col-0");
				}
			}
		});
	}
	
	/**************************************************************************
	* 단축키 등록
	**************************************************************************/
	static registShortcutKey(){
		document.addEventListener('keydown', (event) => {

			var RESERVED_FUNCTION_KEYS = ["F1","F2","F3","F4","F6","F7","F8","F9","F10","F11","PageDown","PageUp"];
			var KEYS_FOR_GLOBAL = ["F9","F10","F11"];
			
			if(RESERVED_FUNCTION_KEYS.includes(event.key)){
				
				event.preventDefault();
				
				var activeBasckdropYn = FimsSupport.isActiveBackdrop();
				
				var curArea = FimsSupport.getCurrentAreaForShortcutKey();
				
				if(KEYS_FOR_GLOBAL.includes(event.key)){ //전역 기능
				
					if(event.key == "F9"){
						if($("#securityMode--top").is(":checked")){
							$("#securityMode--top").prop("checked", false);
							fn_securityModeToggle(false);
						} else {
							$("#securityMode--top").prop("checked", true);
							fn_securityModeToggle(true);
						}
						
					}
					
					if(event.key == "F10"){
						if($("#photoMask--top").is(":checked")){
							$("#photoMask--top").prop("checked", false);
							fn_photoMask(false);
						} else {
							$("#photoMask--top").prop("checked", true);
							fn_photoMask(true);
						}
						
					}
					
					if(!activeBasckdropYn){
						//TODO : do something
					}
					
				} else { //페이지별,다이얼로그별 버튼

					if(curArea != null){

						var targetButton = $(curArea).find("button.btn-"+event.key);
						
						if(targetButton.length == 1){
							targetButton.click();
						} else {
							if(targetButton.length > 1){
								debug('단축키 버튼 중복 : ' + targetButton.length + "개");
							}
						}
						
					}
					
				}
				
				return false;
			}
		});
	}
	
	//단축키 기능이 사용될 영역을 반환한다. 
	static getCurrentAreaForShortcutKey(){
		
		if(FimsSupport.isActiveBackdrop()){
			return AppSupport.getLastOpenDialog();
		} else {
			return FimsSupport.getActiveRootTabArea();
		}

		return null;
	}
	
	//현재 활성화된 최상위 탭 영역을 반환한다.
	static getActiveRootTabArea(){
		return $("#main-tab-content").children(".active")[0];
	}


	//백드롭 영역 활성화 여부를 반환한다.
	static isActiveBackdrop(){
		
		if($("div.modal-backdrop").length < 1){
			return false;
		}
		
		var isActiveYn = false;
		$("div.modal-backdrop").each(function(){
			if($(this).hasClass("show")){
				isActiveYn = true;
			};
		});
		
		return isActiveYn;
	}

	
	/**
	 * json객체 안의 jsonArray를 FormData형식의 키로 치환한다.
	 * @return FormData형식의 키를 갖는 json
	 */
	static fnJsonToFormData(originalJson, arrayName){
		if(originalJson[arrayName] == undefined){
			return originalJson;
		} else {
			var newObj = {};
		
			var array = originalJson[arrayName];
			for(var i=0; i<array.length; i++){
				var json = array[i];
				
				var keys = Object.keys(json);
				for(var j=0; j<keys.length; j++){
					var key = keys[j];
					newObj[arrayName+"["+i+"]."+key] = json[key];
				}
			}
			
			delete originalJson[arrayName];
			
			return {...originalJson, ...newObj};
		}
	}
	
	/**
	 * jsonArray를 FormData형식의 키를 갖는 json으로 치환한다.
	 * @return FormData형식의 키를 갖는 json
	 */
	static fnJsonArrayToFormData(array, arrayName){
		var newObj = {};
		
		for(var i=0; i<array.length; i++){
			var json = array[i];
			
			var keys = Object.keys(json);
			for(var j=0; j<keys.length; j++){
				var key = keys[j];
				newObj[arrayName+"["+i+"]."+key] = json[key];
			}
		}
		
		return newObj;
	}
	
	/**************************************************************************
	* 엑셀다운로드시 개인정보 포함된 셀의 이름 정보를 추출하는 함수
	**************************************************************************/
	static getCellDefsForPrivacyCell($td_i){
		if($td_i.hasClass("privacy-cell")){
			return $td_i.find("span:eq(0)").text();
		} else {
			return $td_i.text();	
		}
	}
	
	/**************************************************************************
	* 프로그레스바 표시
	**************************************************************************/
	static fnProgress(sseKey, progressContent, progressEvent){
		var eventSource = new EventSource(SSE_SUBSCRIBE_URL+"?sseKey="+sseKey);

	    eventSource.onopen = function(e) {
	    	$.blockUI({
				message : "<span id='progress-"+sseKey+"' >"+progressContent+"</span>",
				css: { backgroundColor: "lightgrey", padding : "10px" }
			});
	    };

	    eventSource.onerror = function(e) {
	    	$.unblockUI();
	    };

	    eventSource.onmessage = function(e) {
	        if (e.data == 'FIN'){
				eventSource.close();
				$.unblockUI();
	        } else {
	        	progressEvent(e.data);
	        }
	    };
	}
}

const SSE_SUBSCRIBE_URL = wctx.url("/subscribe.do");

const BOOTSTRAP_COLS = [
	"col-1","col-2","col-3","col-4","col-5","col-6","col-7","col-8","col-9","col-10","col-11","col-12",
	"col-sm-1","col-sm-2","col-sm-3","col-sm-4","col-sm-5","col-sm-6","col-sm-7","col-sm-8","col-sm-9","col-sm-10","col-sm-11","col-sm-12",
	"col-md-1","col-md-2","col-md-3","col-md-4","col-md-5","col-md-6","col-md-7","col-md-8","col-md-9","col-md-10","col-md-11","col-md-12",
	"col-lg-1","col-lg-2","col-lg-3","col-lg-4","col-lg-5","col-lg-6","col-lg-7","col-lg-8","col-lg-9","col-lg-10","col-lg-11","col-lg-12",
	"col-xl-1","col-xl-2","col-xl-3","col-xl-4","col-xl-5","col-xl-6","col-xl-7","col-xl-8","col-xl-9","col-xl-10","col-xl-11","col-xl-12",
	"col-xxl-1","col-xxl-2","col-xxl-3","col-xxl-4","col-xxl-5","col-xxl-6","col-xxl-7","col-xxl-8","col-xxl-9","col-xxl-10","col-xxl-11","col-xxl-12"
];


/**************************************************************************
* FimsPagingSupport
**************************************************************************/
class FimsPagingSupport extends PagingSupport {
	constructor(conf) {
		let constructByCtrl = true;
		if(conf.ctrl == null){
			constructByCtrl = false;
			conf.ctrl = new DatasetControl({});
		}
		super(conf);
		
		if(constructByCtrl){
			if(conf.ignoreCtrlPrefix){
				this.prefix = null;
			}
		};
		
		if(conf.doq != null){
			this._doq = conf.doq;
		}
	}
	
	setPagingInfo(option) {
		
		let pagination = {};
		let List;
		let Paging;
		if(this.prefix == null || this.prefix == ""){
			let c = this.linkContainer;
			pagination.prefix = c.substr(7, c.length-15);
			List = "List";
			Paging = "Paging";
		} else {
			pagination.prefix = this.prefix;
			List = pagination.prefix+"List";
			Paging = pagination.prefix+"Paging";
		}
		
		let dl = 0;
		if(option && option[List]) {
			dl = option[List].length;
		}
		
		let s = 0;
		let ts = 0;
		if(option && option[Paging] && option[Paging].start) {
			s = option[Paging].start;
		}
		if(option && option[Paging] && option[Paging].totalSize) {
			ts = option[Paging].totalSize;
		}
		pagination.totalSize = ts;
		pagination.dataLength = s + dl;
		pagination.containers = this.doq.containers;
		$(this.doq.selector(this.linkContainer)).setPagingInfo(pagination);
	}
}

function newFimsPagingSupport(conf){
	return new FimsPagingSupport(conf);
}