////////////////////////////////////////////////////////////////////////////////////////
//Page 전역 변수
////////////////////////////////////////////////////////////////////////////////////////
var selectId; // 제품 아이디
var selectName; // 제품 이름
var selectedIndex; // 데이터테이블 선택한 인덱스
var selectedPage; // 데이터테이블 선택한 인덱스
var selectVersion; // 선택한 버전 아이디
var dataTableRef; // 데이터테이블 참조 변수
var scheduleList;

////////////////////////////////////////////////////////////////////////////////////////
//Document Ready
////////////////////////////////////////////////////////////////////////////////////////
function execDocReady() {
	var pluginGroups = [
		[
			"../reference/light-blue/lib/vendor/jquery.ui.widget.js",
			"../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Templates_js_tmpl.js",
			"../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Load-Image_js_load-image.js",
			"../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Canvas-to-Blob_js_canvas-to-blob.js",
			"../reference/light-blue/lib/jquery.iframe-transport.js",
			"../reference/light-blue/lib/jquery.fileupload.js",
			"../reference/light-blue/lib/jquery.fileupload-fp.js",
			"../reference/light-blue/lib/jquery.fileupload-ui.js",
			"../reference/light-blue/lib/icheck.js/jquery.icheck.js",
			"../reference/jquery-plugins/unityping-0.1.0/dist/jquery.unityping.min.js",
			"../reference/jquery-plugins/cron-editor-master/css/jquery-ui_arms.css",
			"../reference/jquery-plugins/cron-editor-master/js/jquery-ui.js",
			"../reference/jquery-plugins/cron-editor-master/js/jquery.croneditor_arms.js"
		],

		[
			"../reference/jquery-plugins/select2-4.0.2/dist/css/select2_lightblue4.css",
			"../reference/jquery-plugins/select2-4.0.2/dist/js/select2.min.js",
			"../reference/jquery-plugins/lou-multi-select-0.9.12/css/multiselect-lightblue4.css",
			"../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.quicksearch.js",
			"../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.multi-select.js",
			"../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select-bluelight.css",
			"../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select.min.js",
			//highlight
			"../reference/jquery-plugins/highlight.js-11.10.0/highlight.js.lib/src/styles/base16/darcula.css",
			"../reference/jquery-plugins/highlight.js-11.10.0/highlight.js.lib/highlight.min.js",
			"../reference/jquery-plugins/highlight.js-11.10.0/highlightjs-line-numbers.js/src/highlightjs-line-numbers.js"
		],

		[
			"../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.min.css",
			"../reference/light-blue/lib/bootstrap-datepicker.js",
			"../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.full.min.js",
			"../reference/lightblue4/docs/lib/widgster/widgster.js",
			"../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js",
			// jspreadsheet
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jsuites.js",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/index.js",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jsuites.css",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.css",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.datatables.css",
			"../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.theme.css",
			"/arms/js/common/jspreadsheet/spreadsheet.js",
			"/arms/css/jspreadsheet/custom_sheet.css"
		],

		[
			"../reference/jquery-plugins/dataTables-1.10.16/media/css/jquery.dataTables_lightblue4.css",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/css/responsive.dataTables_lightblue4.css",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/css/select.dataTables_lightblue4.css",
			"../reference/jquery-plugins/dataTables-1.10.16/media/js/jquery.dataTables.min.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/js/dataTables.responsive.min.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/js/dataTables.select.min.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/RowGroup/js/dataTables.rowsGroup.min.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/dataTables.buttons.min.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.html5.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.print.js",
			"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/jszip.min.js",
			// Table
			"../arms/js/common/table_new.js"
		]
		// 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다.
	];

	loadPluginGroupsParallelAndSequential(pluginGroups)
		.then(function () {
			console.log("모든 플러그인 로드 완료");

			//vfs_fonts 파일이 커서 defer 처리 함.
			setTimeout(function () {
				var script = document.createElement("script");
				script.src = "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/vfs_fonts.js";
				script.defer = true; // defer 속성 설정
				document.head.appendChild(script);
			}, 5000); // 5초 후에 실행됩니다.

			//pdfmake 파일이 커서 defer 처리 함.
			setTimeout(function () {
				var script = document.createElement("script");
				script.src = "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/pdfmake.min.js";
				script.defer = true; // defer 속성 설정
				document.head.appendChild(script);
			}, 5000); // 5초 후에 실행됩니다.

			// 사이드 메뉴 색상 설정
			$(".widget").widgster();
			setSideMenu("sidebar_menu_config", "sidebar_menu_config_schedule");

			// 데이터 테이블 로드 함수
			console.log("load :: init.scheduleListTable");
			$("#schedule_list_table").trigger($.Event("init.scheduleListTable"));

			// 버튼클릭이벤트 활성화
			btnClickEvent();

			// 현재 스케줄 목록 가져오기
			getCurrentScheduleList();
		})
		.catch(function (error) {
			console.error("플러그인 로드 중 오류 발생");
			console.log(error);
		});
}

////////////////////////////////////////////////////////////////////////////////////////
// --- 데이터 테이블 설정 --- //
////////////////////////////////////////////////////////////////////////////////////////
// 데이터 테이블 구성 이후 꼭 구현해야 할 메소드 : 열 클릭시 이벤트
function dataTableClick(tempDataTable, selectedData) {
	console.log(selectedData);
}

// 데이터 테이블 데이터 렌더링 이후 콜백 함수.
function dataTableCallBack(settings, json) {
	console.log("check");
}

function dataTableDrawCallback(tableInfo) {
	//	resourceDataTable.columns.adjust();
	console.log(tableInfo);
}

+(function ($) {
	let columns = [
		{
			name: "idx",
			title: "No.",
			// data: null, // idx 는 데이터소스에 있는 필드가 아님
			data: null, // idx 는 데이터소스에 있는 필드가 아님
			render: function (data, type, row, meta) {
				if (type === "display") {
					return meta.row + 1; // meta.row는 현재 행의 인덱스 (0부터 시작)
				}
				return meta.row + 1; // 정렬, 필터링 등 다른 타입에서도 인덱스 값 반환
			},
			className: "dt-body-center", // 가운데 정렬
			orderable: false, // 정렬 불가
			searchable: false // 검색 불가
		},
		{
			name: "fileName",
			title: "스케줄 그룹(파일명)",
			data: "fileName",
			render: function (data, type, row, meta) {
				if (type === "display") {
					return '<label style="color: #a4c6ff">' + data + "</label>";
				}
				return data;
			},
			className: "dt-body-left",
			visible: true
		},
		{
			name: "name",
			title: "스케줄 명",
			data: "name",
			render: function (data, type, row, meta) {
				if (type === "display") {
					return '<label style="color: #a4c6ff">' + data + "</label>";
				}
				return data;
			},
			className: "dt-body-left",
			visible: true
		},
		{
			name: "cron",
			title: "주기(cron)",
			data: "cron",
			render: function (data, type, row, meta) {
				if (type === "display") {
					return '<label style="color: #a4c6ff">' + data + "</label>";
				}
				return data;
			},
			className: "dt-body-left",
			visible: true
		},
		{
			name: "notes",
			title: "비고",
			data: "notes",
			render: function (data, type, row, meta) {
				if (type === "display") {
					return '<label style="color: #a4c6ff">' + data + "</label>";
				}
				return data;
			},
			className: "dt-body-left",
			visible: true
		},
		{
			name: "enabled",
			title: "스케줄 동작",
			data: "enabled",
			render: function (data, type, row, meta) {
				if (type === "display") {
					let innerText = "";
					if (data === true) {
						return (
							'<label style="color: #a4c6ff"><i class="fa fa-play-circle" style="color: #2D8515"></i>' +
							"&nbsp;동작</label>"
						);
					} else {
						return (
							'<label style="color: #a4c6ff"><i class="fa fa-pause" style="color: #DB2A34"></i>' + "&nbsp;중지 </label>"
						);
					}
				}
				return data;
			},
			className: "dt-body-left",
			visible: true
		}
	];

	$(document).one("init.scheduleListTable", function () {
		let lastScrollTop = 0;

		$("#schedule_list_table")
			.on("length.dt", function (e, settings, len) {
				lastScrollTop = $(window).scrollTop();
			})
			.on("page.dt", function () {
				console.log("workerStatusTable :: page.dt");
				lastScrollTop = $(window).scrollTop();
			})
			.on("select.table", function (event, selectedData, rowIndex) {
				console.log("event => ", $(event.target).closest("tr").index() + 1);
				console.log("select => ", selectedData);
				$("#modify_schedule_btn").removeClass("disabled");
				$("#remove_schedule_btn").removeClass("disabled");

				let table = $("#schedule_list_table").DataTable();
				let page = table.page.info().page;
				let pageLength = table.page.info().length;
				var idx = page * pageLength + $(event.target).closest("tr").index() + 1;
				setEditScheduleContents($.extend({}, { idx: idx }, selectedData));
				setRemoveScheduleContents($.extend({}, { idx: idx }, selectedData));
				// 스케줄 이력 조회 (methodName)
				fetchScheduleHistory(selectedData.methodName ? selectedData.methodName : selectedData.name);
				// sender 설정 (스케줄 명)
				changeSender(selectedData.name);
			})
			.on("deselect.table", function (event, selectedData) {
				console.log("deselect => ", selectedData);
				$("#modify_schedule_btn").addClass("disabled");
				$("#remove_schedule_btn").addClass("disabled");
				selectedIndex = null;
				modalInitialize();
				// sender 설정
				changeSender();
				//$("#selectedSchedule").text("선택되지 않음");
				// 엑셀초기화
				$("#schedule_history_excel")[0].jexcel.destroy();
			})
			.table({
				order: [],
				columns: columns,
				// isAddCheckbox: true,
				scrollCollapse: false,
				scrollY: "350px",
				data: [],
				drawCallback: function () {
					console.log("scheduleListTable :: drawCallback");
					console.log("lastScrollTop => ", lastScrollTop);
					setTimeout(() => {
						$(window).scrollTop(lastScrollTop);
					}, 0); // 필요시 10~20ms로 늘릴 수 있음
				}
			});
	});
})(jQuery);

/////////////////////////////////
// 선택한 스케줄 이름 표시
/////////////////////////////////
function changeSender(text) {
	if (text) {
		$("#schedule-history-chat-message .chat-message-body").css("border-color", "#e5603b");
		$("#schedule-history-chat-message .chat-message-body .arrow").css("border-right", "5px solid #e5603b");
		$("#schedule-history-chat-message .sender #senderSelected").text(text);
	} else {
		$("#schedule-history-chat-message .chat-message-body").css("border-color", "#a4c6ff");
		$("#schedule-history-chat-message .chat-message-body .arrow").css("border-right", "5px solid #a4c6ff");
		$("#schedule-history-chat-message .sender #senderSelected").text("선택되지 않음");
	}
}

/////////////////////////////////
// 스케줄 이력 조회 (by fluentd)
/////////////////////////////////
function fetchScheduleHistory(methodName) {
	$.ajax({
		url: "/engine-search-api/engine/search/schedule-history-log",
		type: "POST",
		contentType: "application/json",
		data: JSON.stringify({ searchString: methodName }),
		dataType: "json",
		success: function (result) {
			let elapsedTimeFormatted = result.map((item) => {
				return {
					...item,
					formatElapsedTime: formatElapsedTime(item.elapsedTime)
				};
			});
			drawExcel("schedule_history_excel", elapsedTimeFormatted);
		}
	});
}

/////////////////////////////////
// 스케줄 목록 조회
/////////////////////////////////
function getCurrentScheduleList() {
	$.ajax({
		url: "/auth-sche/getCurrentScheduleList",
		type: "GET",
		contentType: "application/json;charset=UTF-8",
		dataType: "json",
		progress: true,
		async: true,
		statusCode: {
			200: function (data) {
				console.log("[analysisCost :: getCurrentScheduleList] :: response => ", data);
				scheduleList = data;
				$("#schedule_list_table").table().reDraw(data);
			}
		}
	});
}

// 수정/삭제 모달 초기화
function modalInitialize() {
	let $radioInputsEdit = $('#edit_modal_enabled input[type="radio"]');
	let $radioLabelsEdit = $radioInputsEdit.parent("label");
	$radioLabelsEdit.removeClass("active").removeClass("focus");
	$("#schedule_edit_modal .modal-content #fileName").val("");
	$("#schedule_edit_modal .modal-content #name").val("");
	$("#schedule_edit_modal .modal-content #methodName").val("");
	$("#schedule_edit_modal .modal-content #cron").val("");
	$("#schedule_edit_modal .modal-content #notes").val("");
	$("#schedule_edit_modal .modal-content #enabled").val("");
	let $radioInputsRemove = $('#remove_modal_enabled input[type="radio"]');
	let $radioLabelsRemove = $radioInputsRemove.parent("label");
	$radioLabelsRemove.removeClass("active").removeClass("focus");
	$("#schedule_remove_modal .modal-content #fileName").val("");
	$("#schedule_remove_modal .modal-content #name").val("");
	$("#schedule_remove_modal .modal-content #methodName").val("");
	$("#schedule_remove_modal .modal-content #cron").val("");
	$("#schedule_remove_modal .modal-content #notes").val("");
	$("#schedule_remove_modal .modal-content #enabled").val("");
}

// 스케줄 수정 모달 세팅
function setEditScheduleContents(selectedData) {
	console.log("selected Row Idx => ", selectedData.idx);
	selectedIndex = selectedData.idx;
	$("#schedule_edit_modal .modal-content #fileName").val(selectedData.fileName);
	$("#schedule_edit_modal .modal-content #name").val(selectedData.name);
	$("#schedule_edit_modal .modal-content #methodName").val(selectedData.methodName);
	$("#schedule_edit_modal .modal-content #cron").val(selectedData.cron);
	$("#schedule_edit_modal .modal-content #notes").val(selectedData.notes);
	$("#schedule_edit_modal .modal-content #enabled").val(selectedData.enabled);
	console.log("selectedData.enabled => ", selectedData.enabled);

	let $activeOption = $('#edit_modal_enabled input[value="true"]');
	let $inactiveOption = $('#edit_modal_enabled input[value="false"]');

	if (selectedData.enabled && selectedData.enabled === true) {
		$activeOption.prop("checked", true);
		$activeOption.parent("label").addClass("active").addClass("focus");
		$inactiveOption.parent("label").removeClass("active").removeClass("focus");
	} else {
		$inactiveOption.prop("checked", true);
		$activeOption.parent("label").removeClass("active").removeClass("focus");
		$inactiveOption.parent("label").addClass("active").addClass("focus");
	}
}
// 스케줄 삭제 모달 세팅
function setRemoveScheduleContents(selectedData) {
	console.log("selected Row Idx => ", selectedData.idx);
	selectedIndex = selectedData.idx;
	$("#schedule_remove_modal .modal-content #fileName").val(selectedData.fileName);
	$("#schedule_remove_modal .modal-content #name").val(selectedData.name);
	$("#schedule_remove_modal .modal-content #methodName").val(selectedData.methodName);
	$("#schedule_remove_modal .modal-content #cron").val(selectedData.cron);
	$("#schedule_remove_modal .modal-content #notes").val(selectedData.notes);
	$("#schedule_remove_modal .modal-content #enabled").val(selectedData.enabled);

	let $radioInputs = $('#remove_modal_enabled input[type="radio"]'); // 모든 라디오 input 선택
	let $radioLabels = $radioInputs.parent("label"); // 해당 라디오 input의 부모 label 선택

	// 1. 모든 라디오 버튼과 레이블을 비활성화
	$radioInputs.prop("disabled", true); // input 자체를 disabled
	$radioLabels.css("pointer-events", "none"); // 클릭 이벤트를 막음 (혹시 모를 우회 방지)
	$radioLabels.css("cursor", "not-allowed"); // 마우스 커서 변경

	// 2. 현재 데이터에 따라 'active' 상태를 설정 (비활성화 상태이지만, 데이터는 반영)
	let $activeOption = $('#remove_modal_enabled input[value="true"]');
	let $inactiveOption = $('#remove_modal_enabled input[value="false"]');

	if (selectedData.enabled && selectedData.enabled === true) {
		$activeOption.prop("checked", true);
		$activeOption.parent("label").addClass("active").addClass("focus");
		$inactiveOption.parent("label").removeClass("active").removeClass("focus");
	} else {
		$inactiveOption.prop("checked", true);
		$activeOption.parent("label").removeClass("active").removeClass("focus");
		$inactiveOption.parent("label").addClass("active").addClass("focus");
	}

	$radioLabels.removeClass("focus");
}

function btnClickEvent() {
	$("#modify_schedule_btn, #remove_schedule_btn").on("click", function (event) {
		if ($(this).hasClass("disabled")) {
			event.preventDefault();
			event.stopPropagation();
		}
	});

	$("#save_edit_schedule_btn").on("click", function () {
		console.log("scheduleConfig :: save_edit_schedule_btn is clicked");

		let formDataArray = $("#schedule_edit_modal #scheduleForm").serializeArray();

		let enabledValue = $('#edit_modal_enabled input[name="edit_modal_enabled_options"]:checked').val();

		let notesValue = $("#notes").val();

		let dataToSave = {};
		formDataArray.forEach(function (item) {
			dataToSave[item.name] = item.value;
		});

		dataToSave["enabled"] = enabledValue === "true"; // 문자열 "true"/"false"를 boolean으로 변환
		dataToSave["notes"] = notesValue; // notes 필드 추가
		dataToSave["idx"] = selectedIndex;
		delete dataToSave.edit_modal_enabled_options;

		// 1. scheduleList 에서 해당 idx 의 element 를 dataToSave 로 변경
		let convertedSchedules = convertedScheduleList(dataToSave, scheduleList);
		// 2. saveScheduleList API 호출 -> fileName 및 scheduleList 전달
		saveScheduleList(convertedSchedules);
	});

	$("#remove_edit_schedule_btn").on("click", function () {
		if (!selectedIndex || selectedIndex === null) {
			jError("선택된 스케줄이 없습니다.(삭제 대상 없음)");
		}
		console.log("scheduleConfig :: remove_edit_schedule_btn is clicked");
		// 1. scheduleList 에서 해당 idx 의 element 를 삭제
		// 2. fileName 과 동일한 내용만 필터링
		let dataToRemove = {};
		dataToRemove["fileName"] = $("#schedule_remove_modal #scheduleForm #fileName").val();
		dataToRemove["idx"] = selectedIndex;
		let convertedSchedules = updatedScheduleListByRemoval(dataToRemove, scheduleList);
		console.log("[ scheduleConfig :: remove_edit_schedule_btn ] :: remove.convertedSchedules => ", convertedSchedules);
		saveScheduleList(convertedSchedules);
	});
}

var updatedScheduleListByRemoval = function removeScheduleElement(targetData, scheduleList) {
	let updatedRawData = $.extend(true, [], scheduleList);
	let targetIndex = targetData.idx;
	updatedRawData.splice(targetIndex - 1, 1);

	// 업데이트된 rawData 중에서 targetData의 fileName과 일치하는 요소만 필터링
	let filteredData = updatedRawData.filter((item) => item.fileName === targetData.fileName);

	return { updatedScheduleList: updatedRawData, targetSchedules: filteredData };
};

var convertedScheduleList = function convertScheduleElement(targetData, scheduleList) {
	let updatedRawData = $.extend(true, [], scheduleList);

	let taretIndex = targetData.idx;
	if (taretIndex !== undefined && taretIndex > 0 && taretIndex <= updatedRawData.length) {
		delete targetData.idx;
		updatedRawData[taretIndex - 1] = targetData;
	} else {
		console.warn(
			"targetData.idx가 유효한 배열 인덱스를 벗어나거나 정의되지 않았습니다. 데이터를 업데이트하지 못했습니다."
		);
	}

	let filteredData = updatedRawData.filter((item) => item.fileName === targetData.fileName);

	return { updatedScheduleList: updatedRawData, targetSchedules: filteredData };
};

function saveScheduleList(convertedSchedules) {
	$.ajax({
		url: "/auth-sche/saveScheduleList?fileName=" + convertedSchedules.targetSchedules[0].fileName,
		type: "POST",
		data: JSON.stringify(convertedSchedules.targetSchedules),
		contentType: "application/json;charset=UTF-8",
		dataType: "json",
		success: function (result) {
			if (result === 200 || result === "200") {
				console.log("[ scheduleConfig:: saveScheduleList ] :: complete");
				scheduleList = convertedSchedules.updatedScheduleList;
				$("#schedule_list_table").table().reDraw(scheduleList);
				selectedIndex = null;
			} else {
				console.error("[ scheduleConfig:: saveScheduleList ] :: unexpected server response : ", result);
			}
		},
		error: function (xhr, status, error) {
			console.error("AJAX 요청 실패:", status, error);
			console.error("응답 본문:", xhr.responseText);
		}
	});
}

////////////////
// 엑셀 그리기
////////////////
function drawExcel(target, data) {
	var columnList = [
		{ readOnly: true, type: "hidden", name: "scheduleName", title: "스케줄 명", wRatio: 0 }, // 0 스케줄명
		{ readOnly: true, type: "text", name: "startedAt", title: "시작 시점", wRatio: 0.4 }, // 1 시작시점
		// { readOnly: true, type: "calendar", options: {format: "YYYY/MM/DD"}, name: "createDate", title: "ALM 이슈 생성일", wRatio: 0.1 }, 			//10
		{ readOnly: true, type: "text", name: "finishedAt", title: "종료 시점", wRatio: 0.4 }, // 2 종료시점
		{ readOnly: true, type: "text", name: "formatElapsedTime", title: "경과", wRatio: 0.2 }, // 3 경과시간(ms)
		{ readOnly: true, type: "hidden", name: "elapsedTime", title: "경과 시간(ms)", wRatio: 0 }, // 3 경과시간(ms)
		{ readOnly: true, type: "hidden", name: "threadName", title: "스레드명", wRatio: 0 }, // 4 (히든) 스레드명
		{ readOnly: true, type: "hidden", name: "threadId", title: "스레드아이디", wRatio: 0 } // 5 (히든) 스레드아이디
	];

	var customOption = {
		toolbar: [],
		pagination: 30,
		contextMenu: [],
		search: true,
		allowInsertRow: false,
		allowInsertColumn: false,
		columnSorting: false,
		onload: function (element) {
			var $jexcel = $(element);
			var $searchInput = $(
				'<span style="margin-left: 2px;display: flex;flex-direction: ' +
					'row;align-items: center; font-style: normal; height: 100%; width:100% !important;"><i class="fa fa-search"></i>' +
					' <input class="jexcel_search" placeholder="시트에서 검색" style="margin-left: 5px;background-color: transparent;border: none; width: 100%; color: #FFF">' +
					"</span>"
			);
			$jexcel.find(".jexcel_toolbar_item[data-k='undo']").addClass("fa fa-mail-reply ");
			$jexcel.find(".jexcel_toolbar_item[data-k='redo']").addClass("fa fa-mail-forward ");
			$jexcel.find(".jexcel_toolbar_item[data-k='save']").addClass("fa fa-save");
			$jexcel
				.find(".jexcel_toolbar_item[data-k='text-align'][data-v='left']")
				.addClass("fa fa-align-left fa-flip-vertical");
			$jexcel
				.find(".jexcel_toolbar_item[data-k='text-align'][data-v='center']")
				.addClass("fa fa-align-center fa-flip-vertical");
			$jexcel
				.find(".jexcel_toolbar_item[data-k='text-align'][data-v='right']")
				.addClass("fa fa-align-right fa-flip-vertical");
			$jexcel.find(".jexcel_toolbar_item[data-k='font-weight'][data-v='bold']").addClass("fa fa-bold");
			$jexcel.find(".jexcel_toolbar_item[data-k='font-style'][data-v='italic']").addClass("fa fa-italic");
			$jexcel.find(".jexcel_toolbar_item[data-k='text-decoration'][data-v='underline']").addClass("fa fa-underline");
			$jexcel
				.find(".jexcel_toolbar_item[data-k='text-decoration'][data-v='line-through']")
				.addClass("fa fa-strikethrough");
			$jexcel.find(".jexcel_toolbar_item[data-k='color']").addClass("fa fa-font");
			$jexcel.find(".jexcel_toolbar_item[data-k='background-color']").addClass("fa fa-font fa-background");
			$jexcel.find(".jexcel_filter").addClass("hidden");
			$jexcel.find(".jexcel_toolbar_item[data-k='search-box']").addClass("search-box").append($searchInput);

			// 검색 input 에 focus 일때, 선택 초기화
			var $inputField = $searchInput.find("input.jexcel_search");
			if ($inputField.length) {
				$inputField.on("focus", function () {
					if (element.jexcel) {
						element.jexcel.resetSelection();
					}
				});
			}
		},
		updateTable: function (instace, cell, col, row, val, id) {
			cell.style.whiteSpace = "normal";
			cell.style.textAlign = "left";
			cell.style.color = "#a4c6ff";
			if (col === 20 && val !== true) {
				// 현재 행(row)에 해당하는 모든 셀 가져오기
				let rowCells = cell.parentElement.children;
				// 해당 행의 모든 셀의 글꼴 색상을 red로 변경
				for (let i = 0; i < 14; i++) {
					rowCells[i].style.color = "#f8f8f8";
				}
			}
		},
		oneditionstart: function () {
			SpreadsheetFunctions.isEditingCell = true;
			SpreadsheetFunctions.stopObserver();
		},
		oneditionend: function () {
			SpreadsheetFunctions.isEditingCell = false;
			SpreadsheetFunctions.startObserver();
		}
	};
	SpreadsheetFunctions.setTargetId(target);
	SpreadsheetFunctions.setDefaultTargetRect();

	SpreadsheetFunctions.setColumns(columnList);
	SpreadsheetFunctions.setColumnWidth(SpreadsheetFunctions.getTargetRect("width"));
	SpreadsheetFunctions.setOptions(customOption);
	SpreadsheetFunctions.startObserver();
	SpreadsheetFunctions.setExcelData(data);
	SpreadsheetFunctions.drawResizedExcel(SpreadsheetFunctions.getTargetId());
}

var SpreadsheetFunctions = (function () {
	let targetId = { v: "", jq: "" };
	let targetRect = { width: 0, height: 0 };
	let excelData; // 엑셀 데이터
	let excelColumns; // 엑셀 컬럼
	let customOptions; // 엑셀 커스텀 옵션들 :: 정의 안할 경우 default
	let isEditingCell = false;

	var setDefaultTargetRect = function () {
		let defaultWidth = $(getTargetId("jq")).width();
		let defaultHeight = $(getTargetId("jq")).height();
		setTargetRect(defaultWidth, defaultHeight);
	};
	var setTargetRect = function (width, height) {
		targetRect.width = width;
		targetRect.height = height;
	};

	var getTargetRect = function (type) {
		if (type === "width") {
			return targetRect.width;
		} else if (type === "height") {
			return targetRect.height;
		} else {
			return targetRect;
		}
	};

	var setTargetId = function (target) {
		targetId.v = target;
		targetId.jq = "#" + target;
	};

	var getTargetId = function (type) {
		if (type === "jq") {
			return targetId.jq;
		} else {
			return targetId.v;
		}
	};

	var setExcelData = function (data) {
		excelData = data;
	};
	var getExcelData = function () {
		return excelData;
	};
	var setColumns = function (columns) {
		excelColumns = columns;
	};
	var getColumns = function () {
		return excelColumns;
	};

	var setColumnWidth = function (width) {
		if (excelColumns) {
			excelColumns = excelColumns.map((column) => ({
				...column,
				width: width * column.wRatio - 1
			}));
		}
	};

	function setColumnWidthAsync(width) {
		return new Promise((resolve) => {
			if (excelColumns) {
				excelColumns = excelColumns.map((column) => ({
					...column,
					width: width * column.wRatio - 1
				}));
			}
			resolve(); // 컬럼 너비 설정이 완료된 후 resolve 호출
		});
	}

	var setOptions = function (options) {
		customOptions = options;
	};
	var getOptions = function () {
		return customOptions ? customOptions : null;
	};

	var resizeObserver = new ResizeObserver(function (entries) {
		if (isEditingCell) {
			// 수정중에는 resize 비활성화
			return;
		}
		for (let entry of entries) {
			setTargetRect(entry.contentRect.width, entry.contentRect.height);
			handleResize(entry.target.id, getTargetRect("width"), getTargetRect("height"));
		}
	});

	// 모달요소 크기 변화 관찰(Observer)
	function startObserver() {
		resizeObserver.observe($(getTargetId("jq"))[0]);
	}

	// Observer 멈추기
	function stopObserver() {
		console.log("Stopping ResizeObserver");
		resizeObserver.disconnect(); // 크기 변화를 더 이상 감지하지 않음
	}

	function handleResize(id, width, height) {
		if (id === getTargetId() && height !== 0) {
			if (excelData) {
				drawResizedExcel(getTargetId());
			} else {
				console.log("Spreadsheet.handleResize :: 엑셀 데이터 없음");
			}
		} else {
			console.log("Spreadsheet.handleResize :: id 불일치 또는 height 가 0 입니다.");
		}
	}

	function drawResizedExcel(target) {
		let $targetId = "#" + target;

		if ($($targetId).length > 0 && $($targetId)[0].jexcel) {
			$($targetId)[0].jexcel.destroy();
		}

		setColumnWidthAsync(getTargetRect("width") - 50).then(() => {
			$($targetId).spreadsheet(
				$.extend(
					{},
					{
						columns: getColumns(),
						data: getExcelData()
					},
					getOptions()
				)
			);

			let jexcel_content_height = getTargetRect("height") - 40 - 30 - 35 - 34;
			$($targetId + " .jexcel_content").css("max-height", jexcel_content_height);
			$($targetId + " .jexcel_content").css("width", "100%");
		});
	}

	function drawExcel(target) {
		let $targetId = "#" + target;

		if ($($targetId).length > 0 && $($targetId)[0].jexcel) {
			$($targetId)[0].jexcel.destroy();
		}

		$($targetId).spreadsheet(
			$.extend(
				{},
				{
					columns: getColumns(),
					data: getExcelData()
				},
				getOptions()
			)
		);

		let jexcel_content_height = getTargetRect("height") - 40 - 30 - 35 - 34;
		$($targetId + " .jexcel_content").css("max-height", jexcel_content_height);
		$($targetId + " .jexcel_content").css("width", "100%");
	}

	return {
		setTargetId,
		getTargetId,
		setTargetRect,
		getTargetRect,
		setDefaultTargetRect,
		setExcelData,
		getExcelData,
		setColumns,
		getColumns,
		setColumnWidth,
		setOptions,
		getOptions,

		startObserver,
		stopObserver,
		drawExcel,
		drawResizedExcel
	};
})();

////////////////////////////////
// 경과시간
////////////////////////////////
function formatElapsedTime(milliseconds) {
	if (milliseconds === undefined || milliseconds === null) {
		return ""; // 또는 다른 적절한 기본값
	}

	const ms = parseInt(milliseconds, 10); // 문자열을 숫자로 변환
	if (isNaN(ms)) {
		return "Invalid Time";
	}

	const seconds = Math.floor(ms / 1000);
	const hours = Math.floor(seconds / 3600);
	const minutes = Math.floor((seconds % 3600) / 60);
	const remainingSeconds = seconds % 60;

	let result = "";
	if (hours > 0) {
		result += `${hours}h`;
	}
	if (minutes > 0) {
		result += `${minutes}m`;
	}
	if (remainingSeconds > 0) {
		result += `${remainingSeconds}s`;
	}

	if (result === "") {
		return "0s"; // 시간이 0ms인 경우
	}

	return result.trim();
}
