<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="icon" href="data:,">
    <meta charset="utf-8" http-equiv='X-UA-Compatible' content='IE=Edge' />
    <title>YT MediaSync | Developed by Yongtae Kim</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            font-family: sans-serif;
            font-size: 16px;
            overflow: hidden;
            /* 그라데이션 배경 추가 */
            background: linear-gradient(
                135deg, 
                #f5f7fa 0%,
                #e8f0ed 50%,
                #e0eee9 100%
            );
            /* 애니메이션 효과 추가 (선택사항) */
            animation: gradientBG 15s ease infinite;
            min-height: 100vh;
        }
        /* 부드러운 애니메이션 효과 (선택사항) */
        @keyframes gradientBG {
            0% {
                background-position: 0% 50%;
            }
            50% {
                background-position: 100% 50%;
            }
            100% {
                background-position: 0% 50%;
            }
        }

        /* 다크모드 대응 */
        @media (prefers-color-scheme: dark) {
            body {
                background: linear-gradient(
                    135deg, 
                    #2c3e50 0%,
                    #203a43 50%,
                    #1e3c3a 100%
                );
                color: #eee;
            }
        }
        input {
            vertical-align: text-top;
        }

        @media (prefers-color-scheme: dark) {
            body {
                background: #333;
                color: #eee;
            }
        }

        #zoomSliderContainer {
            display: flex;
            justify-content: flex-end;
            margin-right: 10px;
        }

        #main_area {
            margin-left: 20px;
            margin-top: 0px;
            min-width: 1000px;
            display: flex;
            justify-content: flex-start;
            align-items: flex-start;
            overflow: hidden;

        }

        #video_container {
    margin-top: 20px;
    flex: 0 0 350px;
    position: sticky;
    top: 20px;
    height: 250px;  /* 컨테이너 높이 고정 */
    display: flex;  /* Flexbox 사용 */
    align-items: center;  /* 세로 중앙 정렬 */
    justify-content: center;  /* 가로 중앙 정렬 */
}

#video_container video {
    width: 100%;
    height: 100%;  /* 컨테이너 높이에 맞춤 */
    max-height: 250px;  /* 최대 높이 제한 */
    object-fit: contain;  /* 비율 유지하면서 컨테이너에 맞춤 */
}

        #text_area {
            flex: 1;
            margin-left: 20px;
            margin-top: 1px;
            display: flex;
            flex-direction: column;
            justify-content: flex-end;
            height: 80%;
            /* 부모 요소의 높이를 100%로 설정 */
        }

        #substitle_area {
            display: flex;
            justify-content: flex-start;
            align-items: center;
            flex-wrap: wrap;
            flex-direction: row;
            /* 수정된 부분 */
            overflow: hidden;
            color: #fff;
            height: 30px;
            background-color: #1ec49d;
        }

        #input_box_area {
            position: relative; /* 추가: 상대 위치 지정 */
            width: 100%;
            margin-top: 1px;
            overflow: auto;
            max-height: calc(80vh - 150px);
            padding: 10px;
            background-color: #fafafa;
            border-radius: 6px;
        }

        #substitle_area td {
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 0;
            margin: 0;
            border: none;
            width: auto;
            height: auto;
            font-family: sans-serif;
            font-size: 16px;
            background-color: transparent;
            color: initial;
            outline: none;
            cursor: pointer;
        }


        #blank_area {
            width: 10%;
        }



        #memo_area {
            position: sticky;
            top: 0;
            height: fit-content;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .memo_box {
            font-size: 16px;
            border: 2px solid #ccc;
            border-radius: 4px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            outline: none;
            transition: border-color 0.3s ease-in-out;
            padding: 10px;
            margin-bottom: 10px;
            margin-left: 30px;
        }

        .memo_box:focus {
            border-color: #00c3ff;
        }

        .input_box {
            width: calc(100% - 10px);
            height: 40px;
            min-height: 20px;
            max-height: 100px;
            margin-bottom: 20px;
            padding: 4px 12px;
            border: 1px solid #e0e0e0;
            border-radius: 4px;
            line-height: 1.1;
            font-family: inherit;
            font-size: 14px;
            resize: none;
            box-sizing: border-box;
            transition: border-color 0.2s ease, box-shadow 0.2s ease;
            background-color: #ffffff;
            clear: both; /* 추가: 새로운 행에서 시작 */
            display: block; /* 추가: 블록 레벨 요소로 변경 */
        }

        /* 컨테이너 추가 */
        .input-group {
            margin-bottom: 10px;
        }

        .header-group {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 5px;
        }
        .input_box:focus {
            border-color: #1ec49d;
            box-shadow: 0 0 0 2px rgba(30, 196, 157, 0.1);
            outline: none;
        }
        .input_box:hover {
            border-color: #1ec49d;
        }
        .speaker_box {
            width: 10%;
            height: 20px;
            font-size: 16px;
            border: 2px solid #ccc;
            border-radius: 4px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            outline: none;
            transition: border-color 0.3s ease-in-out;
            background-color: #f2f2f2;
            pointer-events: none;
            color: #333;
            text-align: center;
            font-family: monospace;
            padding: 0 5px;
            display: inline-block;
            vertical-align: middle;
            margin-bottom: 5px; /* 추가: input-box와의 간격 */
        }

        .add-input {
            font-size: 14px;
            border: 2px solid #ccc;
            border-radius: 4px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            outline: none;
            transition: border-color 0.3s ease-in-out;
        }

        .add-input:focus {
            border-color: #27e40e;
        }

        .speaker_box:focus {
            border-color: #27e40e;
        }

        #waveform {
            width: 90%;
            position: sticky;
            top: 0;
            background: #f5f5f5;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            margin: 10px auto; /* 0을 auto로 변경 */
            left: 0;          /* 추가 */
            right: 0;         /* 추가 */
        }
        /* 웨이브폼 스타일링 */
        #waveform ::part(wave) {
            border-radius: 3px;
        }

        /* 타임라인 스타일링 */
        #waveform ::part(time) {
            color: #666;
            font-size: 11px;
            font-family: monospace;
        }


        #waveform ::part(region-handle-right) {
            border-right-width: 3px !important;
            border-right-color: #FF0000 !important;
        }

        #waveform ::part(region-handle-left) {
            border-left-width: 3px !important;
            /* 왼쪽 테두리의 너비를 2px로 변경 */
            border-left-color: transparent !important;
            /* 왼쪽 테두리의 색상을 빨간색으로 변경 */
        }

        
        /* 모달 창을 가운데 정렬하기 위한 스타일 */
        .modal {
            display: none;
            /* 초기에 숨김 */
            position: fixed;
            z-index: 1;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0, 0, 0, 0.5);
            /* 어두운 배경색 */
        }

        .modal-content {
            background-color: #fefefe;
            margin: 15% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 400px;
        }

        .close {
            float: right;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
        }

        .select-box li {
            background-image: url("./image/speaker_icon.svg");
            display: inline-block;
            line-height: 30px;
            font-size: 14px;
            color: #333;
            padding-left: 31px;
            width: 100%;
            background-color: #fff;
            background-size: 20px 20px;
            background-repeat: no-repeat;
            background-position: 9px center;
        }
        /* 상용구 목록 스타일 */
        #boilerplates li {
            display: flex;
            align-items: center;
            padding: 5px 10px;
            margin: 2px 0;
            border-radius: 3px;
            transition: all 0.2s;
            cursor: pointer;
            background-image: none; /* 배경 이미지 제거 */
            width: 100%;
            background-color: #fff;
            font-size: 14px;
            color: #333;
        }
        #boilerplates li .icon {
            margin-right: 10px;
            min-width: 20px;
            text-align: center;
        }

        #boilerplates li .value {
            flex-grow: 1;
            text-align: left;
        }
        .select-box {
            width: 390px;
            height: 190px;
            border-radius: 5px;
            border: solid 1px #d2d2d2;
            overflow-y: auto;
            overflow-x: hidden;
            padding-left: 0px;
        }

        .select-box li:hover {
            background-color: #ffef87;
            cursor: pointer;
        }

        .select-box li:selected {
            background-color: #ffef87;
        }

        #speakers li.selected {
            background-color: rgb(0, 253, 219);
        }

        #speaker_add_button {
            background-color: #1ec49d;
            /* 다른 스타일 속성들 */
        }

        #speaker_add_button:hover {
            background-color: #16a085;
        }

        #speaker_fix_button {
            background-color: #ffaf40;
            /* 다른 스타일 속성들 */
        }

        #speaker_fix_button:hover {
            background-color: #e67e22;
        }

        #speaker_delete_button {
            background-color: #e74c3c;
            /* 다른 스타일 속성들 */
        }

        #speaker_delete_button:hover {
            background-color: #c0392b;
        }

        .btn-add {
            display: inline-block;
            font-size: 15px;
            font-weight: bold;
            text-align: center;
            text-decoration: none;
            background-color: #1ec49d;
            color: #fff;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        h2 {
            font-size: 24px;
            font-weight: bold;
            color: #333;
            padding: 10px;
            border-bottom: 2px solid #ccc;
            background-image: url("./image/groub_speaker_icon.svg");
            background-size: 30px 30px;
            background-repeat: no-repeat;
            background-position: left center;
            padding-left: 40px;
        }

        /* 웨이브폼 스타일링 */
        #waveform ::part(wave) {
            border-radius: 3px;
        }

        /* 타임라인 스타일링 */
        #waveform ::part(time) {
            color: #666;
            font-size: 11px;
            font-family: monospace;
        }

        /* 커서 스타일링 */
        #waveform ::part(cursor) {
            width: 2px;
            background: #fa0202;
            box-shadow: 0 0 3px rgba(30, 196, 157, 0.5);
        }

        /* Region 스타일링 */
        #waveform ::part(region) {
            border-radius: 3px;
            transition: background-color 0.2s ease;
        }

        #waveform ::part(region):hover {
            opacity: 0.8;
        }

        #waveform ::part(region-handle-left),
        #waveform ::part(region-handle-right) {
            width: 1px;
            background: rgba(0,0,0,0.1);
            transition: background 0.2s ease;
        }

        #waveform ::part(region-handle-left):hover,
        #waveform ::part(region-handle-right):hover {
            background: rgba(0,0,0,0.2);
        }

        #waveform ::part(region-handle-right) {
            border-right-width: 1px !important;
            border-right-color: #1ec49d !important;
        }

        #waveform ::part(region-handle-left) {
            border-left-width: 1px !important;
            border-left-color: transparent !important;
        }

        /* 줌 슬라이더 스타일링 */
        #zoomSlider {
            width: 200px;
            height: 4px;
            border-radius: 2px;
            background: #ddd;
            outline: none;
            margin: 0 15px;
        }

        #zoomSlider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 15px;
            height: 15px;
            border-radius: 50%;
            background: #1ec49d;
            cursor: pointer;
            transition: background 0.2s ease;
        }

        #zoomSlider::-webkit-slider-thumb:hover {
            background: #16a085;
        }

        /* 버튼 컨테이너 스타일링 */
        #buttonContainer {
            margin-top: 5px;
            padding: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 15px;
        }

        #buttonContainer button {
            padding: 8px 15px;
            border: none;
            border-radius: 4px;
            background: #1ec49d;
            color: white;
            font-size: 14px;
            cursor: pointer;
            transition: background 0.2s ease, transform 0.1s ease;
        }

        #buttonContainer button:hover {
            background: #16a085;
            transform: translateY(-1px);
        }

        #buttonContainer button:active {
            transform: translateY(0);
        }

        #buttonContainer button:disabled {
            background: #ccc;
            cursor: not-allowed;
        }

        /* 파일 입력 스타일링 */
        #fileInput {
            padding: 10px;
            margin-left: 80px;
            border: 2px dashed #1ec49d;
            border-radius: 4px;
            cursor: pointer;
            width: calc(100% - 999px); /* 패딩과 마진을 고려한 전체 너비 */
            white-space: nowrap; /* 줄바꿈 방지 */
            overflow: hidden; /* 넘치는 텍스트 숨김 */
            text-overflow: ellipsis; /* 넘치는 텍스트를 ...으로 표시 */
        }

        #fileInput:hover {
            border-color: #16a085;
            background: rgba(30, 196, 157, 0.05);
        }

        /* 단축키 모달 스타일 */
        .shortcut-list {
            margin-top: 20px;
        }

        .shortcut-item {
            display: flex;
            align-items: center;
            margin-bottom: 15px;
            padding: 8px;
            border-radius: 4px;
            background-color: #f5f5f5;
        }

        .shortcut-item:hover {
            background-color: #e9e9e9;
        }

        .key {
            display: inline-block;
            padding: 5px 10px;
            margin-right: 15px;
            background-color: #1ec49d;
            color: white;
            border-radius: 4px;
            font-family: monospace;
            font-weight: bold;
            min-width: 80px;
            text-align: center;
        }

        .description {
            color: #333;
            font-size: 14px;
        }

        #shortcutButton {
            background-color: #4a90e2;
        }

        #shortcutButton:hover {
            background-color: #357abd;
        }
        .credit {
            text-align: right;
            padding: 5px 15px;
            color: #666;
            font-size: 12px;
            font-style: italic;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            white-space: nowrap; /* 줄바꿈 방지 */
        }

        .credit span {
            color: #1ec49d;
            font-weight: bold;
        }
        /* 로그인 모달 스타일 추가 */
        #loginModal {
            display: block;
            position: fixed;
            z-index: 9999;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.7);
        }

        .login-content {
            background-color: #fefefe;
            margin: 15% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 300px;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        .login-content h2 {
            margin-bottom: 20px;
            color: #333;
            text-align: center;
        }

        .boilerplate-title {
            margin-bottom: 1px;
            color: #333;
        }

        .login-content input {
            width: 100%;
            padding: 10px;
            margin: 10px 0;
            border: 1px solid #ddd;
            border-radius: 4px;
            box-sizing: border-box;
        }

        .login-content button {
            width: 100%;
            padding: 10px;
            background-color: #1ec49d;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-top: 10px;
        }

        .login-content button:hover {
            background-color: #16a085;
        }

        #mainContent {
            display: none;
        }

        .byte-counter {
            display: inline-block;
            text-align: right;
            color: #666;
            font-size: 12px;
            margin-top: 10px;
            margin-right: 10px;
            margin-left: auto; /* 수정: 오른쪽 정렬을 위해 auto로 변경 */
            vertical-align: middle;
            width: auto;
            position: absolute; /* 추가: 절대 위치 지정 */
            right: 20px; /* 추가: 오른쪽 여백 */
        }
        
        .byte-counter.exceeded {
            color: #e74c3c;
            font-weight: bold;
        }
        /* CSS 부분 */
        #boilerplates li.selected {
            background-color: #25D097;  /* 초록색 배경 */
            color: white;              /* 텍스트 색상을 흰색으로 */
            font-weight: bold;         /* 글자를 굵게 */
        }

        #boilerplates li {
            cursor: pointer;           /* 마우스 오버시 포인터 커서 */
            padding: 5px 10px;        /* 내부 여백 */
            margin: 2px 0;            /* 항목간 간격 */
            border-radius: 3px;       /* 모서리 둥글게 */
            transition: all 0.2s;     /* 부드러운 전환 효과 */
        }

        #boilerplates li:hover {
            background-color: #e0e0e0; /* 호버 시 배경색 */
        }

        #boilerplates li.selected:hover {
            background-color: #1fb17f; /* 선택된 항목 호버 시 더 진한 초록색 */
        }
        #boilerplateResetBtn {
            margin-left: 5px;
            /* 기존 modal-button 스타일과 동일하게 적용 */
        }
            /* Beta 배지 스타일 */
        .beta-badge {
            position: absolute;
            top: -10px;
            right: -15px;
            background: #FF6B6B;
            color: white;
            font-size: 9px;
            padding: 2px 6px;
            border-radius: 10px;
            font-weight: bold;
            text-transform: uppercase;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.1);
            }
            100% {
                transform: scale(1);
            }
        }
    </style>
</head>

<body>
    <!-- 로그인 모달 추가 -->
    <div id="loginModal">
        <div class="login-content">
            <h2>로그인</h2>
            <form action="login.php" method="POST">
                <input type="text" name="userID" id="username" placeholder="아이디" required>
                <input type="password" name="userPassword" id="password" placeholder="비밀번호" required>
                <button type="submit" id="loginButton">로그인</button>
            </form>
        </div>
    </div>

    <!-- 단축키 설명 모달 추가 -->
    <div id="shortcutModal" class="modal">
      <div class="modal-content">
        <span class="close">&times;</span>
        <h2>단축키 설명</h2>
        <div class="shortcut-list">
            <div class="shortcut-item">
                <span class="key">ESC</span>
                <span class="description">재생/일시정지</span>
            </div>
            <div class="shortcut-item">
                <span class="key">F1</span>
                <span class="description">
                    뒤로 이동
                    <input type="number" id="backwardTime" value="2" min="0.1" max="60" step="0.1" style="width: 50px; margin-left: 10px;"> 초
                </span>
            </div>
            <div class="shortcut-item">
                <span class="key">F4</span>
                <span class="description">
                    앞으로 이동
                    <input type="number" id="forwardTime" value="2" min="0.1" max="60" step="0.1" style="width: 50px; margin-left: 10px;"> 초
                </span>
            </div>
              <div class="shortcut-item">
                  <span class="key">Ctrl + ↑</span>
                  <span class="description">이전 싱크로 이동</span>
              </div>
              <div class="shortcut-item">
                  <span class="key">Ctrl + ↓</span>
                  <span class="description">다음 싱크로 이동</span>
              </div>
              <div class="shortcut-item">
                <span class="key">Ctrl + ←</span>
                <span class="description">싱크 삭제 (또는 전사 박스 마우스 우클릭)</span>
            </div>
              <div class="shortcut-item">
                  <span class="key">Enter</span>
                  <span class="description">싱크 분할</span>
              </div>
          </div>
      </div>
    </div>
    <!-- 단축키 버튼 추가 -->
    

    <!-- 모달 창 -->
    <div id="myModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <h2>화자 정보</h2>
            <ul class="select-box" id="speakers">
            </ul>
            <div class="add-box">
                <label for="addInput">화자추가</label>
                <input type="text" class="add-input" id="addInput">
                <button type="button" class="btn-add" id="speaker_add_button">추가</button>
                <button type="button" class="btn-add" id="speaker_fix_button">수정</button>
                <button type="button" class="btn-add" id="speaker_delete_button">삭제</button>
            </div>
        </div>
    </div>
    <div id="BoilerplateModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <h2 class="boilerplate-title">상용구</h2>
            <label style="font-size: 12px; color: #666; margin-bottom: 2px;">예시 -> 상:상용구</label>
            <ul class="select-box" id="boilerplates">
            </ul>
            <div class="add-box">
                <label for="addInput">상용구</label>
                <input type="text" class="add-input" id="addInput">
                <button type="button" class="btn-add" id="boilerplate_add_button">추가</button>
                <button type="button" class="btn-add" id="boilerplate_fix_button">수정</button>
                <button type="button" class="btn-add" id="boilerplate_delete_button" style="margin-top: 10px; background-color: #e74c3c;    ">삭제</button>
                <button type="button" class="btn-add" id="boilerplate_save_button" style="margin-top: 10px; background-color: #f39c12; margin-left: 35%;">내보내기</button>
                <button type="button" class="btn-add" id="boilerplate_import_button" style="margin-top: 10px; background-color: #3498db;">불러오기</button>
            </div>
        </div>
    </div>
    <div id="mainContent">
        <div style="display: flex; justify-content: space-between; align-items: center; padding: 0 15px;">
            <input type="file" id="fileInput" accept="audio/*,video/*,text/*" />
            <div style="flex: 1;"></div> <!-- 왼쪽 여백용 빈 div -->
            <div class="save-format-container" style="display: flex; align-items: center; gap: 15px;">
                <label style="font-size: 14px; color: #666;">저장 형식:</label>
                <div style="display: flex; gap: 10px;">
                    <label style="display: flex; align-items: center; gap: 5px;">
                        <input type="checkbox" class="save-format" value="txt" checked>
                        <span>TXT</span>
                    </label>
                    <label style="display: flex; align-items: center; gap: 5px;">
                        <input type="checkbox" class="save-format" value="smi">
                        <span>SMI</span>
                    </label>
                    <label style="display: flex; align-items: center; gap: 5px;">
                        <input type="checkbox" class="save-format" value="srt">
                        <span>SRT</span>
                    </label>
                </div>
            </div>
            <div style="flex: 1; display: flex; justify-content: flex-end;">
                <div class="credit" style="margin-right: 10px;">© 2024 <span>Yongtae Kim</span> | Version <span>0.6</span> | All rights reserved.</div>
            </div>
        </div>
    <div id="waveform">
    </div>
    
    <div id="buttonContainer">
        <button id="shortcutButton" style="margin: 0 10px;">단축키 정보</button>
        <button 
        style="margin: 0 10px; background-color: #ccc; cursor: not-allowed; display: none;" 
        id="speakersettingButton" 
        disabled 
        title="아직 지원하지 않는 기능입니다">화자추가</button>
        <!-- 버튼 코드 수정 -->
        <button id="boilerplatesettingButton" style="margin: 0 10px; position: relative;">
            상용구
            <span class="beta-badge">BETA</span>
        </button>
        <!--button style="margin: 0 10px;" id="selectFolderButton">저장폴더 지정</button-->
        <button style="margin: 0 10px;" id="loadButton">파일 불러오기</button>
        <button style="margin: 0 10px;" id="saveButton">저장하기</button>
        
        <!-- 시간 표시 요소 추가 -->
        <div style="display: flex; align-items: center;">
            <div style="display: flex; flex-direction: column; align-items: center; margin: 0 15px;">
                <label style="font-size: 12px; color: #666; margin-bottom: 2px;">현재 재생 시간</label>
                <div id="timeDisplay" style="
                    padding: 5px 10px;
                    background-color: #f5f5f5;
                    border-radius: 4px;
                    font-family: monospace;
                    font-size: 14px;
                    color: #333;
                    min-width: 120px;
                    text-align: center;
                ">00:00:00.000</div>
            </div>
            <div style="display: flex; flex-direction: column; align-items: center; margin: 0 15px;">
                <label style="font-size: 12px; color: #666; margin-bottom: 2px;">이전 싱크로부터 경과 시간</label>
                <div id="syncTimeDisplay" style="
                    padding: 5px 10px;
                    background-color: #f5f5f5;
                    border-radius: 4px;
                    font-family: monospace;
                    font-size: 14px;
                    color: #333;
                    min-width: 120px;
                    text-align: center;
                ">00:00:00.000</div>
            </div>
        </div>
        <div id="LimitContainer" style="margin-left: 20px; display: flex; flex-direction: column; gap: 5px;">
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="timeLimitCheck" style="margin: 0; vertical-align: middle;">
                <label for="timeLimit" style="font-size: 12px; color: #666; margin: 0 5px;">구간 제한(초): </label>
                <input type="number" id="timeLimit" min="1" max="3600" value="30" style="width: 40px; height: 20px;">
            </div>
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="byteLimitCheck" style="margin: 0; vertical-align: middle;">
                <label for="byteLimit" style="font-size: 12px; color: #666; margin: 0 5px;">길이 제한(Byte): </label>
                <input type="number" id="byteLimit" min="1" max="2000" value="25" style="width: 40px; height: 20px;">
            </div>
        </div>
        <div style="display: flex; flex-direction: column; align-items: center;">
            
            <input type="range" id="zoomSlider" min="1" max="1000" value="250" step="1" />
            <label for="zoomSlider" style="font-size: 12px; color: #666; margin-top: 8px;">확대/축소</label>
        </div>
    </div>
    <div id="main_area">
      <div id="video_container">
        <video id="video" crossorigin="anonymous" controls playsinline>
            <source type="video/mp4">
            Your browser does not support the video tag.
        </video>
    </div>
        <div id="text_area">
            
            <!--div id="memo_area">
                <textarea style="width: 83.2%; height: 20px;" type="text" class="memo_box"></textarea>
            </div-->

            <div id="input_box_area">
                <input type="text" class="speaker_box" speaker-matching=null tabindex="-1">
                <div class="byte-counter" byte-matching=null>0 / 25 Bytes</div>
                <input type="text" class="input_box" start-time="0.00000" data-matching=null>
                
            </div>
        </div>
        <div id="blank_area">

        </div>
    </div>
    </div>
    <script src="./upload_files/Jquery.js"></script>
    <script type="module">
    import WaveSurfer from './upload_files/wavesurfer.js';
    import RegionsPlugin from './upload_files/regions.js';
    import TimelinePlugin from './upload_files/timeline.js';
    //import $ from './upload_files/Jquery.js';
    console.log('Yongtae Kim. All rights reserved. :)');
    let ws = null;
    let zoomValue = 1;
    let activeRegion = null;
    let wsRegions = null;
    let action_resize = null;
    let count_ids = 0
    let selectedFolderHandle;
    let currentBlobUrl = null;
    let currentCheckEndTime = null; // 전역 변수로 추가
    let isContentSaved = true; // 초기값은 true로 설정
    let savedCursorPosition = {
    inputBoxId: null,
    position: 0
    };
    // 상용구 모달 관련 요소들
    const boilerplateModal = document.getElementById('BoilerplateModal');
    const boilerplateBtn = document.getElementById('boilerplatesettingButton');
    const boilerplateCloseBtn = boilerplateModal.querySelector('.close');
    const boilerplateAddBtn = document.getElementById('boilerplate_add_button');
    const boilerplateFixBtn = document.getElementById('boilerplate_fix_button');
    const boilerplateDeleteBtn = document.getElementById('boilerplate_delete_button');
    const boilerplateList = document.getElementById('boilerplates');
    const boilerplateSaveBtn = document.getElementById('boilerplate_save_button');
    const boilerplateImportBtn = document.getElementById('boilerplate_import_button');
    //초기화 함수
    function initializeWaveSurfer() {
      resetInputBoxes();
      const inputElement = document.querySelector('.input_box');
      //난수 생성
      let nan_su = generateUniqueNanSu(); // 유일한 nan_su 값을 생성

      while (hasDuplicateNanSu(nan_su)) {
        nan_su = generateUniqueNanSu(); // 중복이 있으면 다시 유일한 nan_su 값을 생성
      }
      inputElement.setAttribute('data-matching', null);
      const speakerElement = document.querySelector('.speaker_box');
      speakerElement.setAttribute('speaker-matching', null);
      inputElement.addEventListener('mousedown', handleInputBoxClick);
      inputElement.addEventListener('keypress', handleInputKeyPress);
      inputElement.addEventListener('keydown', handleF2KeyPress);
      inputElement.addEventListener('keydown', handleArrowNavigation);
      updateByteCounter(inputElement);
        
      if (ws) {
        ws.destroy();
        ws = null;
      }
      
      ws = WaveSurfer.create({
    container: '#waveform',
    waveColor: 'blue',
    progressColor: 'rgb(100, 0, 100)',
    backend: 'MediaElement', 
    media: document.querySelector('video'),
    cursorColor: 'red', // 커서 색상을 빨간색으로 변경
    cursorWidth: 5,
    progressColor: '#D4D1E0',
    waveColor: '#25D097',
    normalize: true,
    autoCenter: false,
});

      wsRegions = ws.registerPlugin(RegionsPlugin.create({
        resize: true, 
        drag: false
      }));
      
      ws.registerPlugin(TimelinePlugin.create())
    }
    // inputbox에서 엔터 키 눌렀을 때 동작 함수
    function handleInputKeyPress(e) {
      if (e.key === 'Enter') {
        if (e.shiftKey) {
            e.preventDefault();
            alert('줄바꿈을 할 수 없습니다.');
            return;
        }
      }
      const random = (min, max) => Math.random() * (max - min) + min;
      const randomColor = () => `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.3)`;
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        var matchingValue = e.target.dataset.matching;
         // start-time 값 가져오기
        window.startTimeValue = document.querySelector(`[data-matching="${matchingValue}"]`).getAttribute('start-time');
        
        //console.log(startTimeValue);
        window.end_time = ws.getCurrentTime() || 0;
        const timeLimit = parseFloat(document.getElementById('timeLimit').value);
        
        // 시간 제한 체크
        if (document.getElementById('timeLimitCheck').checked) {  // 체크박스 상태 확인
    // input box의 값 가져오기
            const inputValue = e.target.value;  // 앞뒤 공백 제거
            const noSpaceValue = inputValue;  // 모든 공백 제거
            
            // "%"가 정확히 한 개이고 다른 문자가 없는 경우 체크 건너뛰기
            const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");
            
            if (!isOnlyPercent) {  // "%"만 있는 경우가 아닐 때만 시간 제한 체크
                if (end_time - parseFloat(startTimeValue) > timeLimit) {
                    alert(`구간이 ${timeLimit}초를 초과할 수 없습니다.`);
                    return;
                }
            }
        }
        
        if (startTimeValue >= end_time) {
            alert('start-time과 end-time이 같을 수 없습니다.');
            return;
        }

        if ( e.target.hasAttribute('end-time') ) {
          if ( end_time > e.target.getAttribute('end-time') ) {
            alert('end-time보다 크게 싱크를 나눌 수 없습니다.')
            return;
          }
        }

        var nextSibling = document.querySelector(`[data-matching="${matchingValue}"]`).nextElementSibling;
        while (nextSibling && !nextSibling.classList.contains('input_box')) {
          nextSibling = nextSibling.nextElementSibling;
        }
        if (nextSibling && nextSibling.hasAttribute('start-time')) {
          var nextStartTimeValue = nextSibling.getAttribute('start-time');
          if ( nextStartTimeValue < end_time ) {
            alert('다음 싱크의 start-time보다 end-time이 클 수 없습니다.')
            return;
          }
        }
        // 현재 포커스가 있는 input 요소에 end-time 속성 추가
        e.target.setAttribute('end-time', window.end_time);

      let 다음인풋요소 = e.target.nextElementSibling;
      while (다음인풋요소 && !다음인풋요소.classList.contains(e.target.classList[0])) {
          다음인풋요소 = 다음인풋요소.nextElementSibling; // 다음 형제 요소로 이동
      }

      const matchingValuess = e.target.getAttribute('data-matching');

        // data-matching 값이 존재하는지 확인
        if (matchingValuess !== null && matchingValuess !== '') {
            // 존재할 경우 수행할 작업
            //console.log('data-matching 값:', matchingValuess);
        }
        else{
          matchingValuess = null
        }
      //난수 생성
      let nan_su = generateUniqueNanSu(); // 유일한 nan_su 값을 생성

      while (hasDuplicateNanSu(nan_su)) {
        nan_su = generateUniqueNanSu(); // 중복이 있으면 다시 유일한 nan_su 값을 생성
      }

      // window.nan_su = Math.floor(new Date().getTime() + Math.random());
      e.target.setAttribute('data-matching', nan_su);
      e.target.previousElementSibling.previousElementSibling.setAttribute('speaker-matching', nan_su);
      e.target.previousElementSibling.setAttribute('byte-matching', nan_su);

        //console.log(end_time);
        const inputValue = e.target.value;
        const cursorPosition = e.target.selectionEnd;
        const regionContent = e.target.value; // 현재 inputBox의 값 가져오기
        const trimmedValue = inputValue
        .substring(cursorPosition)
        .split('\n')  // 줄 단위로 분리
        .filter(line => line.trim() !== '')  // 빈 줄 제거
        .join('\n');  // 다시 하나의 문자열로 합치기
        let leftText = inputValue.substring(0, cursorPosition);
        if (leftText.trim() == '') {
            leftText = " ";  
        }
        wsRegions.addRegion({
          id: nan_su, 
          start: parseFloat(startTimeValue),
          end: end_time,
          content: leftText,
          color: randomColor(),
          resize: true, 
          drag: false
        });
        e.target.value = leftText.trim();
        
        //새로운 input_box를 추가합니다 
        const newInputBox = document.createElement('textarea');
        //newInputBox.type = 'text';
        newInputBox.classList.add('input_box');
        newInputBox.setAttribute('start-time', end_time);
        newInputBox.addEventListener('keypress', handleInputKeyPress);
        newInputBox.addEventListener('mousedown', handleInputBoxClick);
        newInputBox.addEventListener('keydown', handleArrowNavigation);
        newInputBox.addEventListener('contextmenu', e => createContextMenu(e, newInputBox));
        // input 이벤트에 바이트 카운터 업데이트 추가
        newInputBox.addEventListener('input', function() {
          updateByteCounter(this);
        });
        newInputBox.value = trimmedValue;


        const newspeakerBox = document.createElement('input');
        newspeakerBox.type = 'text';
        newspeakerBox.classList.add('speaker_box');
        newspeakerBox.setAttribute('tabindex', "-1");
        // 구간 시간 계산 (end_time - startTimeValue)
        const duration = end_time - parseFloat(startTimeValue);
        const formattedDuration = Math.floor(duration * 1000) / 1000; // 반올림하지 않고 소수점 3자리까지 표시

        // 해당 speaker_box 찾아서 구간 시간 설정
        const matchingSpeakerBox = document.querySelector(`[speaker-matching="${nan_su}"]`);
        if (matchingSpeakerBox) {
            matchingSpeakerBox.value = formattedDuration;
        }
        let nextElement = e.target.nextElementSibling;
        while (nextElement) {
            if (nextElement.hasAttribute("data-matching")) {
                // data-matching 속성을 가진 요소를 찾으면 루프 종료
                break;
            }
            nextElement = nextElement.nextElementSibling;
        }
        
        if (nextElement !== null) {
          const startTime = nextElement.getAttribute('start-time');
          //console.log("시작시간:" + startTime);
          const check_matching_id = nextElement.getAttribute('data-matching');
          if (startTime !== null) {
            // start-time 값이 존재하는 경우에 대한 처리
    newInputBox.setAttribute('end-time', startTime);
    newInputBox.dataset.matching = matchingValue;
    
    // region 찾기 및 수정
    for (let i = 0; i < wsRegions.regions.length; i++) {
        const regionId = wsRegions.regions[i].id;
        if (regionId.toString() === matchingValue) {
            const currentRegion = wsRegions.regions[i];
            
            // region 수정
            currentRegion.setOptions({
                start: end_time
            });
            const regionContentElement = currentRegion.element.querySelector('[part="region-content"]');
            regionContentElement.textContent = trimmedValue;
            // 현재 region에 avoidOverlapping 적용
            wsRegions.avoidOverlapping(currentRegion);
            
            // 이전 region이 있다면 avoidOverlapping 적용
            const prevRegion = wsRegions.regions.find(r => 
                parseFloat(r.end) === parseFloat(currentRegion.start)
            );
            if (prevRegion) {
                wsRegions.avoidOverlapping(prevRegion);
            }
            
            // 다음 region이 있다면 avoidOverlapping 적용
            const nextRegion = wsRegions.regions.find(r => 
                parseFloat(r.start) >= parseFloat(currentRegion.end)
            );
            if (nextRegion) {
                wsRegions.avoidOverlapping(nextRegion);
            }
            
            break;
        } else {
                }
            }
          } else {
          }
        } else {
          let nan_su = generateUniqueNanSu(); // 유일한 nan_su 값을 생성

          while (hasDuplicateNanSu(nan_su)) {
            nan_su = generateUniqueNanSu(); // 중복이 있으면 다시 유일한 nan_su 값을 생성
          }

        }
          newInputBox.setAttribute("data-matching", matchingValuess)
          newspeakerBox.setAttribute("speaker-matching", newInputBox.getAttribute("data-matching"))
          const newByteCounter = document.createElement('div');
          newByteCounter.className = 'byte-counter';
          const byteLimit = document.getElementById('byteLimit').value || 2000;
          newByteCounter.textContent = `0 / ${byteLimit} Bytes`;
          newByteCounter.setAttribute("byte-matching", newInputBox.getAttribute("data-matching"))

          e.target.parentNode.insertBefore(newspeakerBox, e.target.nextSibling);
          e.target.parentNode.insertBefore(newByteCounter, e.target.nextSibling.nextSibling);
          e.target.parentNode.insertBefore(newInputBox, e.target.nextSibling.nextSibling.nextSibling);
          newInputBox.focus();
          updateByteCounter(newInputBox);
          updateByteCounter(e.target);
          // setTimeout을 사용하여 focus 이후 커서 위치 설정
          setTimeout(() => {
                newInputBox.setSelectionRange(0, 0);
                newInputBox.scrollLeft = 0;
                newInputBox.scrollTop = 0;
            }, 0);
            newInputBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
          reorderRegionDivs();
      }

      // region-업데이트 시 실행 함수
      wsRegions.on('region-updated', (region, e) => {
          activeRegion = region;
          const clickedRegionId = region.id;
          const clickedRegionStart = region.start;
          const clickedRegionEnd = region.end;
          //console.log('클릭된 지역 시작 시간:', clickedRegionStart);
          //console.log('클릭된 지역 종료 시간:', clickedRegionEnd);

          // 매칭되는 입력 상자 찾기
          const matchingInputBox = document.querySelector(`[data-matching="${clickedRegionId}"]`);
          if (matchingInputBox) {
              // 리전 조정에 따른 start-time 및 end-time 최신화
              matchingInputBox.setAttribute('start-time', clickedRegionStart);
              matchingInputBox.setAttribute('end-time', clickedRegionEnd);

              // 모든 input_box를 선택
              const inputBoxes = document.querySelectorAll('.input_box');
              
              // 현재 매칭되는 input_box의 인덱스를 찾기
              const currentIndex = Array.from(inputBoxes).indexOf(matchingInputBox);
              
              // 다음 input_box가 존재하는지 확인하고 start-time 업데이트
              if (currentIndex < inputBoxes.length - 1) { // 다음 요소가 있을 경우
                  const nextInputBox = inputBoxes[currentIndex + 1];
                  //console.log('다음 input_box의 start-time:', nextInputBox.getAttribute('start-time'));
                  nextInputBox.setAttribute('start-time', clickedRegionEnd);
              } else {
                  //console.log('다음 input_box가 존재하지 않습니다.');
              }
          }

          // 모든 input_box에 대해 각 위치를 최신화
          const inputBoxes = document.querySelectorAll('.input_box');
          inputBoxes.forEach((box, index) => {
              if (index === inputBoxes.length - 1) { // 마지막 input_box인 경우
                  const prevEndTime = inputBoxes[index - 1].getAttribute('end-time');
                  box.setAttribute('start-time', prevEndTime);
                  if (prevEndTime !== null) { // 이전 input_box에 end-time이 있는지 확인
                      box.setAttribute('start-time', prevEndTime);
                  }
              }
          });
      });

      let currentCheckEndTime = null;
      // 전역 region 클릭 이벤트도 같은 방식으로 수정
      wsRegions.on('region-clicked', async (region, e) => {
    e.stopPropagation();
    
    try {
        // 현재 재생 중인 경우 먼저 정지
        await ws.pause();
        
        // 이전 체크 함수 제거
        if (currentCheckEndTime) {
            ws.un('audioprocess', currentCheckEndTime);
            currentCheckEndTime = null;
        }

        activeRegion = region;
        
        // 매칭되는 input-box 찾기 및 포커스
        const matchingInputBox = document.querySelector(`[data-matching="${region.id}"]`);
        if (matchingInputBox) {
            matchingInputBox.focus();
            setTimeout(() => {
                matchingInputBox.setSelectionRange(0, 0);
                matchingInputBox.scrollLeft = 0;
                matchingInputBox.scrollTop = 0;
            }, 0);
            matchingInputBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }

        // 현재 region의 시작 시간으로 이동
        ws.setTime(region.start);
        await ws.play();

        // 새로운 재생 상태 모니터링
        currentCheckEndTime = () => {
            if (!activeRegion) return; // activeRegion이 없으면 체크하지 않음
            
            const currentTime = ws.getCurrentTime();
            if (currentTime >= activeRegion.end) {
                ws.pause();
                ws.setTime(activeRegion.end);
                ws.un('audioprocess', currentCheckEndTime);
                currentCheckEndTime = null;
                activeRegion = null;
            }
        };

        ws.on('audioprocess', currentCheckEndTime);

    } catch (error) {
        if (error.name !== 'AbortError') {
            console.error('Playback error:', error);
        }
    }
});

// 시간 포맷팅 함수
function formatSpeakerTime(seconds) {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = Math.floor(seconds % 60);
    const milliseconds = Math.floor((seconds % 1) * 1000);
    return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}.${String(milliseconds).padStart(3, '0')}`;
}
      function reorderRegionDivs() {
  // 1. input_box들을 순서대로 가져오기
  const inputBoxes = Array.from(document.querySelectorAll('.input_box'));
  const matchingOrder = inputBoxes.map(inputBox => inputBox.getAttribute('data-matching'));

  // 2. regions 배열 정렬
  const sortedRegions = [];
  matchingOrder.forEach(matchingValue => {
    const region = wsRegions.regions.find(r => r.id.toString() === matchingValue);
    if (region) {
      sortedRegions.push(region);
    }
  });

  // 3. DOM에서 region div 재정렬
  const regionContainer = document.querySelector('#waveform')
    .firstElementChild.shadowRoot
    .querySelector('.wrapper')
    .querySelector('div[style*="position: absolute"]');
  
  const regions = Array.from(document.querySelector('#waveform')
    .firstElementChild.shadowRoot
    .querySelectorAll('[part^="region "]'));
  
  matchingOrder.forEach(matchingValue => {
    const regionDiv = regions.find(region => 
      region.getAttribute('part') === `region ${matchingValue}`
    );
    if (regionDiv) {
      regionContainer.appendChild(regionDiv);
    }
  });

  // 4. regions 배열 업데이트
  wsRegions.regions = sortedRegions;

  // 5. 각 region의 이전/다음 region 관계 업데이트
  sortedRegions.forEach((region, index) => {
    const prevRegion = index > 0 ? sortedRegions[index - 1] : null;
    const nextRegion = index < sortedRegions.length - 1 ? sortedRegions[index + 1] : null;
    
    region.prevRegion = prevRegion;
    region.nextRegion = nextRegion;
    
    // input_box의 start-time과 end-time도 업데이트
    const currentInputBox = inputBoxes[index];
    if (currentInputBox) {
      currentInputBox.setAttribute('start-time', region.start);
      currentInputBox.setAttribute('end-time', region.end);
      
      // 마지막 input_box가 아닌 경우, 다음 input_box의 start-time 설정
      if (index < inputBoxes.length - 1) {
          const nextInputBox = inputBoxes[index + 1];
          nextInputBox.setAttribute('start-time', region.end);
          
          // speaker-box 시간값 업데이트
          const currentSpeakerBox = document.querySelector(`[speaker-matching="${region.id}"]`);
          if (currentSpeakerBox && currentSpeakerBox.getAttribute('speaker-matching') !== "null") {
              const duration = region.end - region.start;
              const formattedDuration = Math.floor(duration * 1000) / 1000;
              currentSpeakerBox.value = formattedDuration;
              
              // timeLimit 체크하여 스타일 적용
                const timeLimitCheck = document.getElementById('timeLimitCheck');
                const timeLimit = parseFloat(document.getElementById('timeLimit').value);

                if (timeLimitCheck.checked) {  // 체크박스가 체크된 경우
                    // 매칭되는 input box 찾기
                    const matchingId = currentSpeakerBox.getAttribute('speaker-matching');
                    const matchingInputBox = document.querySelector(`[data-matching="${matchingId}"]`);
                    
                    if (matchingInputBox) {
                        const inputValue = matchingInputBox.value;
                        const noSpaceValue = inputValue;
                        const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");

                        
                        if (!isOnlyPercent) {  // %가 아닌 경우에만 스타일 적용
                            if (formattedDuration >= timeLimit) {
                                currentSpeakerBox.style.border = '2px solid #e71212';
                                currentSpeakerBox.style.backgroundColor = '#f10303';
                                currentSpeakerBox.style.color = '#ffffff';
                            } else {
                                currentSpeakerBox.style.border = '2px solid #ccc';
                                currentSpeakerBox.style.backgroundColor = '#f2f2f2';
                                currentSpeakerBox.style.color = '#333';
                            }
                        } else {
                            // % 포함된 경우 기본 스타일
                            currentSpeakerBox.style.border = '2px solid #ccc';
                            currentSpeakerBox.style.backgroundColor = '#f2f2f2';
                            currentSpeakerBox.style.color = '#333';
                        }
                    }
                } else {
                    // 체크박스가 해제된 경우 기본 스타일 적용
                    currentSpeakerBox.style.border = '2px solid #ccc';
                    currentSpeakerBox.style.backgroundColor = '#f2f2f2';
                    currentSpeakerBox.style.color = '#333';
                }
          }
      }
    }
  });
}
    }
    
    // 저장폴더 지정 버튼 클릭 시 함수
    /*
    document.getElementById('selectFolderButton').addEventListener('click', function() {
    // 숨겨진 input 요소 생성
    const folderInput = document.createElement('input');
    folderInput.type = 'file';
    folderInput.webkitdirectory = true; // 디렉토리 선택 활성화
    folderInput.style.display = 'none';
    document.body.appendChild(folderInput);

    // 파일 선택 다이얼로그 트리거
    folderInput.click();

    folderInput.addEventListener('change', function() {
        if (this.files && this.files.length > 0) {
            // 선택된 폴더 경로 저장
            selectedFolderHandle = this.files[0].webkitRelativePath.split('/')[0];
            document.getElementById('saveButton').disabled = false;
            
            // 선택된 폴더명 표시 (선택사항)
            alert(`선택된 폴더: ${selectedFolderHandle}`);
        }
        
        // 임시 input 요소 제거
        document.body.removeChild(folderInput);
    });
});
*/

    // 주어진 초를 포맷하는 함수
    function formatTime(seconds) {
        // 밀리초 계산
        let milliseconds = Math.round((seconds % 1) * 1000);
        let totalSeconds = Math.floor(seconds);

        // 시간을 계산
        let hours = Math.floor(totalSeconds / 3600);
        let minutes = Math.floor((totalSeconds % 3600) / 60);
        let secs = totalSeconds % 60;

        // 시간 형식으로 포맷팅
        return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')},${String(milliseconds).padStart(3, '0')}`;
    }
    // saveFile 함수 정의
    // saveFile 함수 수정
    async function saveFile(content, fileName) {
    try {
        // Blob 생성
        const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
        
        // 파일 다운로드
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = fileName;  // 수정: uniqueFileName 대신 원래 fileName 사용
        
        document.body.appendChild(a);
        a.click();
        
        // cleanup
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    } catch (error) {
        console.error('Error in saveFile:', error);
        alert('파일 저장 중 오류가 발생했습니다.');
    }
}

    // 저장하기 버튼 클릭 시 함수
    document.getElementById('saveButton').addEventListener('click', async function() {
         // 모든 input box 검사
        const inputBoxes = document.querySelectorAll('.input_box');
        let firstEmptyBox = null;
        
        inputBoxes.forEach(box => {
            const value = box.value.trim().replace(/\s+/g, '');
            if (value.length === 0 && !firstEmptyBox) {
                firstEmptyBox = box; // 첫 번째 빈 박스 저장
            }
        });
        
        if (firstEmptyBox) {
            firstEmptyBox.focus();
            alert('⚠️ 내용이 없는 구간이 있습니다!');
            
            const confirmSave = confirm('그래도 저장하시겠습니까?');
            if (!confirmSave) {
                return;
            }
            
            setTimeout(() => {
                firstEmptyBox.style.backgroundColor = '';
            }, 1000);
        }

        if (document.getElementById('timeLimitCheck').checked) {
        const timeLimit = parseFloat(document.getElementById('timeLimit').value);
        const inputBoxes = document.querySelectorAll('.input_box');
        const lastInputBox = document.querySelector('[data-matching="null"]');
        
        if (lastInputBox) {
            // input box의 값 가져오기
            const inputValue = lastInputBox.value.trim();  // 앞뒤 공백 제거
            const noSpaceValue = inputValue;  // 모든 공백 제거
            
            // "%"가 정확히 한 개이고 다른 문자가 없는 경우 체크 건너뛰기
            const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");
            
            if (!isOnlyPercent) {  // "%"만 있는 경우가 아닐 때만 시간 제한 체크
                const startTime = parseFloat(lastInputBox.getAttribute('start-time'));
                const endTime = ws.getDuration();
                const duration = endTime - startTime;
                
                if (duration > timeLimit) {
                    alert(`마지막 싱크가 ${timeLimit}초를 초과합니다. (${duration.toFixed(3)}초)\n확인 후 저장해 주세요.\n구간에 "%"만 있으면 초과 오류가 발생하지 않습니다.\n그럼에도 저장하려면 구간 제한 체크 해제를 하세요.`);
                    return;
                }
            }
        }
    }
    const fileInput = document.getElementById('fileInput');
    const selectedFile = fileInput.files[0];
    const selectedFileName = selectedFile.name;
    const baseFileName = selectedFileName.replace(/\.[^/.]+$/, "");
    
    try {
        // input box 요소들 가져오기
        const inputBoxes = document.querySelectorAll('.input_box');
        
        // 체크된 저장 형식 확인
        const saveFormats = document.querySelectorAll('.save-format:checked');
        
        for (const format of saveFormats) {
            const extension = format.value;
            const fileName = `${baseFileName}.${extension}`;
            let content = '';
            
            switch (extension) {
                case 'txt':
                    content = '# Generated by kimyongtae\n\n' + 
                             '# Durée :' + formatTime(ws.getDuration()) + 
                             '\n# Langue : kor\n\n\n\n\n' + 
                             Array.from(inputBoxes).map(inputBox => {
                                 const startTime = parseFloat(inputBox.getAttribute('start-time')).toFixed(5);
                                 return ` - {${startTime}} ${inputBox.value.trim().replace(/\s{2,}/g, ' ')}`; 
                             }).join('\n') + '\n';
                    break;

                case 'srt':
                    let index = 1;
                    content = Array.from(inputBoxes).map(inputBox => {
                        if (inputBox.getAttribute('data-matching') !== 'null') {
                            const startTime = parseFloat(inputBox.getAttribute('start-time'));
                            const endTime = parseFloat(inputBox.getAttribute('end-time'));
                            const text = inputBox.value.trim().replace(/\s{2,}/g, ' '); 
                            const startTimeFormatted = formatSrtTime(startTime);
                            const endTimeFormatted = formatSrtTime(endTime);
                            const entry = `${index}\n${startTimeFormatted} --> ${endTimeFormatted}\n${text}\n`;
                            index++;
                            return entry;
                        }
                        return '';
                    }).filter(entry => entry !== '').join('\n');
                    break;

                case 'smi':
                    content = Array.from(inputBoxes).map(inputBox => {
                        if (inputBox.getAttribute('data-matching') !== 'null') {
                            const startTime = Math.round(parseFloat(inputBox.getAttribute('start-time')) * 1000);
                            const text = inputBox.value.trim().replace(/\s{2,}/g, ' ');
                            return `<Sync Start=${startTime}><P Class=KRCC>\n${text}\n`;
                        }
                        return '';
                    }).filter(entry => entry !== '').join('');
                    break;
            }
            
            await saveFile(content, fileName);
        }
    } catch (error) {
        console.error('Error saving files:', error);
        alert('파일 저장 중 오류가 발생했습니다.');
    }
    isContentSaved = true; // 저장 완료 시 true로 설정
});

// SRT 시간 형식으로 변환하는 함수 추가
function formatSrtTime(seconds) {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor(seconds % 60);
    const milliseconds = Math.floor((seconds % 1) * 1000);
    
    return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')},${String(milliseconds).padStart(3, '0')}`;
}

    // 저장하기 함수 연계_중복된 파일명을 수정하여 유니크한 파일명 생성
    async function getUniqueFileName(directoryHandle, fileName) {
    const lastDotIndex = fileName.lastIndexOf('.');
    if (lastDotIndex === -1) return fileName;

    const baseName = fileName.substring(0, lastDotIndex);
    const fileExtension = fileName.substring(lastDotIndex + 1);
    let newFileName = fileName;

    // localStorage를 사용하여 이미 생성된 파일명 추적
    const existingFiles = JSON.parse(localStorage.getItem('savedFiles') || '[]');
    
    if (!existingFiles.includes(newFileName)) {
        existingFiles.push(newFileName);
        localStorage.setItem('savedFiles', JSON.stringify(existingFiles));
        return newFileName;
    }

    let index = 1;
    do {
        newFileName = `${baseName}(${index}).${fileExtension}`;
        index++;
    } while (existingFiles.includes(newFileName));

    existingFiles.push(newFileName);
    localStorage.setItem('savedFiles', JSON.stringify(existingFiles));
    return newFileName;
}

// 특정 확장자를 가진 파일 목록을 가져오는 함수
async function getFilesWithExtension(directoryHandle, extension) {
    const files = [];
    try {
        for await (const [name, handle] of directoryHandle.entries()) {
            if (handle.kind === 'file' && name.endsWith(`.${extension}`)) {
                files.push(name);
            }
        }
    } catch (error) {
        console.error('Error reading directory:', error);
    }
    return files;
}

     //난수 생성 함수
    function generateUniqueNanSu() {
    return Math.floor(new Date().getTime() + Math.random());
    }
    //난수 생성 함수 연계_생성된 난수 값이 중복이면 다시 생성 함수
    function hasDuplicateNanSu(nan_su) {
      const inputBoxes = document.getElementsByClassName('input_box');
      for (let i = 0; i < inputBoxes.length; i++) {
        const matchingId = inputBoxes[i].getAttribute('data-matching');
        if (matchingId === nan_su) {
          return true; // 중복된 nan_su 값을 찾으면 true 반환
        }
      }

      return false; // 중복된 nan_su 값을 찾지 못하면 false 반환
    }

    // F5 키 비활성화를 위한 이벤트 리스너 추가
    document.addEventListener('keydown', function(e) {
        if (e.key === 'F5' || (e.ctrlKey && e.key === 'r')) {
            e.preventDefault();
            alert('새로고침이 비활성화되어 있습니다.');
            return false;
        }
    }, true);

    // beforeunload 이벤트도 추가하여 실수로 페이지를 나가는 것을 방지
    window.addEventListener('beforeunload', function(e) {
        e.preventDefault();
        e.returnValue = '';
        return '';
    });
    // ESC 입력 시 함수
    document.addEventListener('keydown', async function(e) {
    if (e.keyCode === 27) { // ESC 키
        e.preventDefault();
        try {
            if (ws.isPlaying()) {
                await ws.pause();
            } else {
                await ws.play();
            }
        } catch (error) {
            if (error.name !== 'AbortError') {
                console.error('Playback error:', error);
            }
        }
    } else if (e.keyCode === 112) { // F1 키
        e.preventDefault();
        try {
            const backwardTime = parseFloat(document.getElementById('backwardTime').value) || 2;
            ws.seekTo((ws.getCurrentTime() - backwardTime) / ws.getDuration());
            await ws.play();
        } catch (error) {
            if (error.name !== 'AbortError') {
                console.error('Playback error:', error);
            }
        }
    } else if (e.keyCode === 115) { // F4 키
        e.preventDefault();
        try {
            const forwardTime = parseFloat(document.getElementById('forwardTime').value) || 2;
            ws.seekTo((ws.getCurrentTime() + forwardTime) / ws.getDuration());
            await ws.play();
        } catch (error) {
            if (error.name !== 'AbortError') {
                console.error('Playback error:', error);
            }
        }
    }
});

    //F2 입력 시 함수
    function handleF2KeyPress(e) {
      if (e.key === 'F2') {
        e.preventDefault(); // 기본 동작 방지
        //console.log('F2입력');
      }
    }

    //파일 선택 시 함수
    function loadFile(file) {
    const video = document.querySelector('#video');
    
    // 1. 기존 리소스 정리
    if (ws) {
        ws.destroy();
        ws = null;
    }
    
    video.pause();
    video.removeAttribute('src');
    video.load();
    
    if (currentBlobUrl) {
        URL.revokeObjectURL(currentBlobUrl);
        currentBlobUrl = null;
    }
    
    try {
        // 2. 새 blob URL 생성
        currentBlobUrl = URL.createObjectURL(file);
        video.src = currentBlobUrl;
        
        // 3. 메타데이터 로드 완료 후 WaveSurfer 초기화
        video.onloadedmetadata = async function() {
            //console.log('Video metadata loaded');
            
            // 약간의 지연을 주어 비디오 요소가 완전히 준비되도록 함
            await new Promise(resolve => setTimeout(resolve, 100));
            
            ws = WaveSurfer.create({
                container: '#waveform',
                waveColor: '#25D097',
                progressColor: '#D4D1E0',
                cursorColor: 'red',
                cursorWidth: 2,
                height: 60,
                normalize: true,
                backend: 'MediaElement',
                mediaControls: true,
                interact: true,
                hideScrollbar: false,
                responsive: true,
                media: video
            });

            ws.on('ready', () => {
                // localStorage에서 저장된 줌 레벨 가져오기
                const savedZoom = localStorage.getItem('waveformZoomLevel');
                zoomValue = savedZoom ? Number(savedZoom) : 250; // 기본값 250
                ws.isReady = true;  // isReady 플래그 설정
                document.getElementById('zoomSlider').value = zoomValue;
                ws.zoom(zoomValue);
                
                // 시간 업데이트를 위한 이벤트 리스너 추가
                ws.on('audioprocess', updateTimeDisplay);
                ws.on('pause', () => {
                    const currentTime = ws.getCurrentTime();
                    updateTimeDisplay(currentTime);
                });
                // 파형 클릭 이벤트 추가
                ws.on('click', async() => {
                    await ws.pause();
                    
                    // 이전 체크 함수와 activeRegion 제거
                    if (currentCheckEndTime) {
                        ws.un('audioprocess', currentCheckEndTime);
                        currentCheckEndTime = null;
                    }
                    activeRegion = null;
                    //await ws.play();
                });

                ws.on('seek', () => updateTimeDisplay(ws.getCurrentTime()));
                video.addEventListener('timeupdate', () => updateTimeDisplay(video.currentTime));
                wsRegions = ws.registerPlugin(RegionsPlugin.create({
                    regions: [],
                    dragSelection: false,
                    resize: true,
                    drag: false
                }));

                ws.registerPlugin(TimelinePlugin.create({
                  height: 10,
                  timeInterval: 1,
                  primaryLabelInterval: 5,
                  style: {
                    fontSize: '10px',
                    color: '#6A3274',
                  },
                }));
            });
        };

    } catch (error) {
        console.error('Error in loadFile:', error);
        if (currentBlobUrl) {
            URL.revokeObjectURL(currentBlobUrl);
            currentBlobUrl = null;
        }
    }
}

// 페이지 언로드 시 정리
window.addEventListener('unload', () => {
    if (currentBlobUrl) {
        URL.revokeObjectURL(currentBlobUrl);
    }
    if (ws) {
        ws.destroy();
    }
});

    // fileInput 속성 수정
const fileInput = document.getElementById('fileInput');
fileInput.setAttribute('multiple', 'true');
fileInput.setAttribute('accept', 'video/*,audio/*,.txt');

// 이벤트 핸들러 수정
fileInput.addEventListener('change', async function(e) {
    // 저장되지 않은 내용이 있는 경우 확인
    if (!isContentSaved) {
        const confirmChange = confirm('저장하지 않으셨습니다. 그래도 파일을 선택하시겠습니까?');
        if (!confirmChange) {
            // 파일 선택 취소 시 이전 파일 상태 복원
            const previousFile = this.dataset.previousFile;
            if (previousFile) {
                const dt = new DataTransfer();
                const previousFileObj = this.dataset.previousFileObj ? 
                    JSON.parse(this.dataset.previousFileObj) : null;
                
                if (previousFileObj) {
                    const file = new File([previousFileObj.content], previousFileObj.name, {
                        type: previousFileObj.type,
                        lastModified: previousFileObj.lastModified
                    });
                    dt.items.add(file);
                    this.files = dt.files;
                }
            }
            return;
        }
    }
    const files = Array.from(this.files);

    // 파일 개수 체크
    if (files.length > 2) {
        alert('파일은 최대 2개까지만 선택할 수 있습니다.');
        // 파일 선택이 취소된 경우, 이전 파일 선택을 복원
        const previousFile = this.dataset.previousFile;
        if (previousFile) {
            const dt = new DataTransfer();
            const previousFileObj = this.dataset.previousFileObj ? 
                JSON.parse(this.dataset.previousFileObj) : null;
            
            if (previousFileObj) {
                const file = new File([previousFileObj.content], previousFileObj.name, {
                    type: previousFileObj.type,
                    lastModified: previousFileObj.lastModified
                });
                dt.items.add(file);
                this.files = dt.files;
            }
        }
        return;
    }
    
    
    // 미디어 파일 존재 여부 체크
    // 미디어 파일과 텍스트 파일 찾기
    const txtFile = files.find(file => file.name.endsWith('.txt') || file.name.endsWith('.TXT'));
    const mediaFile = files.find(file => file.type.startsWith('video/') || file.type.startsWith('audio/'));
    // 선택된 파일 정보 출력
    const baseTxtFileName = txtFile ? txtFile.name.substring(0, txtFile.name.lastIndexOf('.')) : null;
    const baseMediaFileName = mediaFile ? mediaFile.name.substring(0, mediaFile.name.lastIndexOf('.')) : null;  
    if (txtFile && baseTxtFileName !== baseMediaFileName) {
        const loadAnyway = confirm('선택한 텍스트 파일명이 현재 미디어 파일명과 다릅니다.\n계속 불러오시겠습니까?');
        if (!loadAnyway) {
            // 파일 선택이 취소된 경우, 이전 파일 선택을 복원
        const previousFile = this.dataset.previousFile;
        if (previousFile) {
            const dt = new DataTransfer();
            const previousFileObj = this.dataset.previousFileObj ? 
                JSON.parse(this.dataset.previousFileObj) : null;
            
            if (previousFileObj) {
                const file = new File([previousFileObj.content], previousFileObj.name, {
                    type: previousFileObj.type,
                    lastModified: previousFileObj.lastModified
                });
                dt.items.add(file);
                this.files = dt.files;
            }
        }
            return;
        }
    }   
    if (!mediaFile) {
        alert('비디오/오디오 파일을 반드시 포함해야 합니다.');
        // 파일 선택이 취소된 경우, 이전 파일 선택을 복원
        const previousFile = this.dataset.previousFile;
        if (previousFile) {
            const dt = new DataTransfer();
            const previousFileObj = this.dataset.previousFileObj ? 
                JSON.parse(this.dataset.previousFileObj) : null;
            
            if (previousFileObj) {
                const file = new File([previousFileObj.content], previousFileObj.name, {
                    type: previousFileObj.type,
                    lastModified: previousFileObj.lastModified
                });
                dt.items.add(file);
                this.files = dt.files;
            }
        }
        return;
    }
    
    // txt 파일만 선택된 경우 체크
    const onlyTxtFile = files.every(file => file.name.toLowerCase().endsWith('.txt'));
    if (onlyTxtFile) {
        alert('txt 파일만 선택할 수 없습니다. 비디오/오디오 파일을 함께 선택해주세요.');
        // 파일 선택이 취소된 경우, 이전 파일 선택을 복원
        const previousFile = this.dataset.previousFile;
        if (previousFile) {
            const dt = new DataTransfer();
            const previousFileObj = this.dataset.previousFileObj ? 
                JSON.parse(this.dataset.previousFileObj) : null;
            
            if (previousFileObj) {
                const file = new File([previousFileObj.content], previousFileObj.name, {
                    type: previousFileObj.type,
                    lastModified: previousFileObj.lastModified
                });
                dt.items.add(file);
                this.files = dt.files;
            }
        }
        return;
    }
    
    if (mediaFile) {
         // DB에 파일 정보 저장
         try {
            const fileData = {
                fileName: mediaFile.name,
                fileType: mediaFile.type,
                fileSize: mediaFile.size
            };

            const response = await fetch('save_file_history.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(fileData)
            });

            const result = await response.json();
            if (!result.success) {
                console.error('파일 기록 저장 실패:', result.message);
            }
        } catch (error) {
            console.error('파일 기록 저장 중 오류:', error);
        }
         // 이전 파일명과 비교
         // 이전 파일과 같은지 확인
         if (this.dataset.previousFile !== mediaFile.name) {
            // 새 파일이면 초기화하고 로드
            initializeWaveSurfer();
            loadFile(mediaFile);
         }
            // wavesurfer가 준비될 때까지 대기
            await new Promise((resolve) => {
            const checkWs = setInterval(() => {
                if (ws && ws.isReady) {
                    clearInterval(checkWs);
                    resolve();
                }
            }, 100);
        });
        // 동일한 이름의 txt 파일 찾기
        const baseFileName = mediaFile.name.substring(0, mediaFile.name.lastIndexOf('.'));

        if (txtFile) {
            try {
            // FileReader를 사용하여 파일 내용 읽기
            const reader = new FileReader();
            reader.onload = function(e) {
                const contents = e.target.result;

                // input_box_area 비우기 전에 기존 regions 제거
                if (wsRegions) {
                    wsRegions.regions.forEach(region => region.remove());
                }
                // input_box_area 완전히 비우기
                const inputBoxArea = document.getElementById('input_box_area');
                inputBoxArea.innerHTML = '';

                

                // txt 파일 파싱 및 작업 복원
                const lines = contents.split('\n');
                const timeMatchLines = [];

                // 먼저 유효한 timeMatch가 있는 줄들만 찾기
                for (let i = 0; i < lines.length; i++) {
                    const line = lines[i].trim();
                    const timeMatch = line.match(/\s*-\s*\{(.+)\}(.*)/);
                    if (timeMatch) {
                        timeMatchLines.push({
                            line,
                            timeMatch,
                            index: i
                        });
                    }
                }
                // timeMatch가 있는 줄들 처리
                timeMatchLines.forEach((item, index) => {
                    const startTime = parseFloat(item.timeMatch[1]);
                    const text = item.timeMatch[2].trim();
                    const isLastTimeMatch = index === timeMatchLines.length - 1;

                    // input box 생성
                    const {
                        inputBox,
                        byteCounter
                    } = createInputBoxFromTxt(startTime, text);

                    // timeMatch의 마지막 줄이면 matching 값을 null로 설정
                    if (isLastTimeMatch) {
                        inputBox.setAttribute('data-matching', 'null');
                        byteCounter.setAttribute('byte-matching', 'null');
                    }

                    const matchingValue = inputBox.getAttribute('data-matching');
                    const speakerBox = createSpeakerBoxFromTxt(matchingValue);

                    inputBoxArea.appendChild(speakerBox);
                    inputBoxArea.appendChild(byteCounter);
                    inputBoxArea.appendChild(inputBox);
                    

                    // timeMatch의 마지막 줄이 아닐 때만 Region 생성
                    if (!isLastTimeMatch) {
                        const random = (min, max) => Math.random() * (max - min) + min;
                        const randomColor = () => `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.3)`;
                        const nanSu = inputBox.getAttribute('data-matching');

                        // 다음 timeMatch의 시작 시간을 현재 라인의 종료 시간으로 사용
                        const nextTimeMatch = timeMatchLines[index + 1].timeMatch;
                        const endTime = parseFloat(nextTimeMatch[1]);

                        // end-time 속성 설정
                        inputBox.setAttribute('end-time', endTime);

                        // region 생성
                        const region = wsRegions.addRegion({
                            id: nanSu,
                            start: parseFloat(startTime) || 0,
                            end: endTime,
                            content: text || ' ',
                            color: randomColor(),
                            resize: true,
                            drag: false
                        }, true);
                        
                        // 구간 시간 계산 (end - start)
                        const duration = region.end - region.start;
                        const formattedDuration = Math.floor(duration * 1000) / 1000;
                        // 해당 speaker_box 찾아서 구간 시간 설정
                        const matchingSpeakerBox = document.querySelector(`[speaker-matching="${nanSu}"]`);
                        if (matchingSpeakerBox) {
                            matchingSpeakerBox.value = formattedDuration;
                            // 시간 제한 체크박스가 활성화된 경우에만 스타일 적용
                            const timeLimitCheck = document.getElementById('timeLimitCheck');
                            if (timeLimitCheck && timeLimitCheck.checked) {
                                // 매칭되는 input box 찾기
                                const matchingId = matchingSpeakerBox.getAttribute('speaker-matching');
                                const matchingInputBox = document.querySelector(`[data-matching="${matchingId}"]`);
                                
                                if (matchingInputBox) {
                                    const inputValue = matchingInputBox.value;
                                    const noSpaceValue = inputValue;
                                    const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");
                                    
                                    if (!isOnlyPercent) {  // %가 아닌 경우에만 스타일 적용
                                        const timeLimit = parseFloat(document.getElementById('timeLimit').value);
                                        if (formattedDuration >= timeLimit) {
                                            matchingSpeakerBox.style.border = '2px solid #e71212';
                                            matchingSpeakerBox.style.backgroundColor = '#f10303';
                                            matchingSpeakerBox.style.color = '#ffffff';
                                        } else {
                                            matchingSpeakerBox.style.border = '2px solid #ccc';
                                            matchingSpeakerBox.style.backgroundColor = '#f2f2f2';
                                            matchingSpeakerBox.style.color = '#333';
                                        }
                                    } else {
                                        // % 포함된 경우 기본 스타일
                                        matchingSpeakerBox.style.border = '2px solid #ccc';
                                        matchingSpeakerBox.style.backgroundColor = '#f2f2f2';
                                        matchingSpeakerBox.style.color = '#333';
                                    }
                                }
                            }
                        }
                        let currentCheckEndTime = null;
                        // region이 성공적으로 생성된 후에 이벤트 리스너 추가
                        // 구간 시간 계산 및 speaker_box 업데이트
                        if (region) {
                            wsRegions.on('region-clicked', async (region, e) => {
                                e.stopPropagation();

                                try {
                                    // 현재 재생 중인 경우 먼저 정지
                                    await ws.pause();

                                    // 이전 체크 함수 제거
                                    if (currentCheckEndTime) {
                                        ws.un('audioprocess', currentCheckEndTime);
                                        currentCheckEndTime = null;
                                    }

                                    activeRegion = region;

                                    // 매칭되는 input-box 찾기 및 포커스
                                    const matchingInputBox = document.querySelector(`[data-matching="${region.id}"]`);
                                    if (matchingInputBox) {
                                        matchingInputBox.focus();
                                        setTimeout(() => {
                                            matchingInputBox.setSelectionRange(0, 0);
                                            matchingInputBox.scrollLeft = 0;
                                            matchingInputBox.scrollTop = 0;
                                        }, 0);
                                        matchingInputBox.scrollIntoView({
                                            behavior: 'smooth',
                                            block: 'center'
                                        });
                                    }

                                    // 현재 region의 시작 시간으로 이동
                                    ws.setTime(region.start);
                                    await ws.play();

                                    // 새로운 재생 상태 모니터링
                                    currentCheckEndTime = () => {
                                        if (!activeRegion) return; // activeRegion이 없으면 체크하지 않음

                                        const currentTime = ws.getCurrentTime();
                                        if (currentTime >= activeRegion.end) {
                                            ws.pause();
                                            ws.setTime(activeRegion.end);
                                            ws.un('audioprocess', currentCheckEndTime);
                                            currentCheckEndTime = null;
                                            activeRegion = null;
                                        }
                                    };

                                    ws.on('audioprocess', currentCheckEndTime);

                                } catch (error) {
                                    if (error.name !== 'AbortError') {
                                        console.error('Playback error:', error);
                                    }
                                }
                            });
                            // region-업데이트 시 실행 함수
                            wsRegions.on('region-updated', (region, e) => {
                                activeRegion = region;
                                const clickedRegionId = region.id;
                                const clickedRegionStart = region.start;
                                const clickedRegionEnd = region.end;
                                //console.log('클릭된 지역 시작 시간:', clickedRegionStart);
                                //console.log('클릭된 지역 종료 시간:', clickedRegionEnd);

                                // 매칭되는 입력 상자 찾기
                                const matchingInputBox = document.querySelector(`[data-matching="${clickedRegionId}"]`);
                                if (matchingInputBox) {
                                    // 리전 조정에 따른 start-time 및 end-time 최신화
                                    matchingInputBox.setAttribute('start-time', clickedRegionStart);
                                    matchingInputBox.setAttribute('end-time', clickedRegionEnd);

                                    // 모든 input_box를 선택
                                    const inputBoxes = document.querySelectorAll('.input_box');
                                    
                                    // 현재 매칭되는 input_box의 인덱스를 찾기
                                    const currentIndex = Array.from(inputBoxes).indexOf(matchingInputBox);
                                    
                                    // 다음 input_box가 존재하는지 확인하고 start-time 업데이트
                                    if (currentIndex < inputBoxes.length - 1) { // 다음 요소가 있을 경우
                                        const nextInputBox = inputBoxes[currentIndex + 1];
                                        //console.log('다음 input_box의 start-time:', nextInputBox.getAttribute('start-time'));
                                        nextInputBox.setAttribute('start-time', clickedRegionEnd);
                                    } else {
                                        //console.log('다음 input_box가 존재하지 않습니다.');
                                    }
                                }

                                // 모든 input_box에 대해 각 위치를 최신화
                                const inputBoxes = document.querySelectorAll('.input_box');
                                inputBoxes.forEach((box, index) => {
                                    if (index === inputBoxes.length - 1) { // 마지막 input_box인 경우
                                        const prevEndTime = inputBoxes[index - 1].getAttribute('end-time');
                                        box.setAttribute('start-time', prevEndTime);
                                        if (prevEndTime !== null) { // 이전 input_box에 end-time이 있는지 확인
                                            box.setAttribute('start-time', prevEndTime);
                                        }
                                    }
                                });
                            });
                        }
                    }
                });

                // 이벤트 리스너 재설정
                const inputBoxes = document.querySelectorAll('.input_box');
                inputBoxes.forEach(inputBox => {
                    inputBox.addEventListener('mousedown', handleInputBoxClick);
                    inputBox.addEventListener('keydown', handleArrowNavigation);
                    inputBox.addEventListener('keypress', handleInputKeyPress);
                    inputBox.addEventListener('contextmenu', e => createContextMenu(e, inputBox));
                    inputBox.addEventListener('input', function() {
                        updateByteCounter(this);
                    });
                });

            };
            reader.readAsText(txtFile);
        } catch (error) {
            console.error('Error loading file:', error);
            alert('파일을 불러오는 중 오류가 발생했습니다.');
        }
        }
    } else {
        // 파일 선택이 취소된 경우, 이전 파일 선택을 복원
        const previousFile = this.dataset.previousFile;
        if (previousFile) {
            const dt = new DataTransfer();
            const previousFileObj = this.dataset.previousFileObj ? 
                JSON.parse(this.dataset.previousFileObj) : null;
            
            if (previousFileObj) {
                const file = new File([previousFileObj.content], previousFileObj.name, {
                    type: previousFileObj.type,
                    lastModified: previousFileObj.lastModified
                });
                dt.items.add(file);
                this.files = dt.files;
            }
        }
    }
    
    // 현재 선택된 미디어 파일 정보 저장
    if (mediaFile) {
        this.dataset.previousFile = mediaFile.name;
        this.dataset.previousFileObj = JSON.stringify({
            name: mediaFile.name,
            type: mediaFile.type,
            lastModified: mediaFile.lastModified,
            content: await mediaFile.arrayBuffer()
        });
        const previousFile = this.dataset;
        if (previousFile) {
            const dt = new DataTransfer();
            const previousFileObj = this.dataset.previousFileObj ? 
                JSON.parse(this.dataset.previousFileObj) : null;
            
            if (previousFileObj) {
                const file = new File([previousFileObj.content], previousFileObj.name, {
                    type: previousFileObj.type,
                    lastModified: previousFileObj.lastModified
                });
                dt.items.add(file);
                this.files = dt.files;
            }
        }
    }
    isContentSaved = true;
});

    // Debounce 함수 추가
    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    };

    // 디바운스된 zoom 함수
    const debouncedZoom = debounce((value) => {
        ws.zoom(value);
        if (wsRegions) {
            wsRegions.regions.forEach(region => {
                wsRegions.avoidOverlapping(region);
            });
        }
    }, 0.1); // 50ms 딜레이
    
    //줌 슬라이더 함수
    //줌 슬라이더 함수 수정
    document.getElementById('zoomSlider').addEventListener('input', function() {
    zoomValue = Number(this.value);
    debouncedZoom(zoomValue);
    // 줌 레벨을 localStorage에 저장
    localStorage.setItem('waveformZoomLevel', zoomValue);
});

    //인풋박스 초기화
    function resetInputBoxes() {
    var textArea = document.getElementById("input_box_area");
    var children = Array.from(textArea.children);
    children.forEach(child => {
        if (child.classList.contains("input_box")) {
            textArea.removeChild(child);
        }
        if (child.classList.contains("speaker_box")) {
            textArea.removeChild(child);
        }
        if (child.classList.contains("byte-counter")) {
            textArea.removeChild(child);
        }
    });
    /*
    var memoBox = document.querySelector(".memo_box");
    memoBox.value = '';
    */
    var speaker_box = document.createElement("input");
    speaker_box.type = "text";
    speaker_box.className = "speaker_box";
    speaker_box.setAttribute("speaker-matching", "null");
    speaker_box.setAttribute("tabindex", "-1");
    textArea.appendChild(speaker_box);
    
    var byteCounter = document.createElement('div');
    byteCounter.className = 'byte-counter';
    byteCounter.textContent = '0 / 2,000 Bytes';
    byteCounter.setAttribute("byte-matching", "null");
    textArea.appendChild(byteCounter);

    var inputBox = document.createElement("textarea");  // Changed to textarea
    inputBox.className = "input_box";
    inputBox.setAttribute("start-time", "0.00000");
    inputBox.setAttribute("data-matching", "null");
    inputBox.addEventListener('input', function() {
        updateByteCounter(this);
    });
    //inputBox.style.marginLeft = "6px";
    inputBox.addEventListener('mousedown', handleInputBoxClick);
    textArea.appendChild(inputBox);

    
}

// 시간 표시를 업데이트하는 함수는 전역 스코프에 유지
function updateTimeDisplay(time) {
    if (!time && time !== 0) {
        time = ws ? ws.getCurrentTime() : 0;
    }
    
    // 기존 시간 표시 업데이트
    const hours = Math.floor(time / 3600);
    const minutes = Math.floor((time % 3600) / 60);
    const seconds = Math.floor(time % 60);
    const milliseconds = Math.floor((time % 1) * 1000);
    
    const timeString = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}.${String(milliseconds).padStart(3, '0')}`;
    
    const timeDisplay = document.getElementById('timeDisplay');
    if (timeDisplay) {
        timeDisplay.textContent = timeString;
    }

    // 싱크 시간 차이 계산 및 표시
    let prevRegionEndTime = 0;
    if (wsRegions && wsRegions.regions.length > 0) {
        const prevRegion = wsRegions.regions
            .filter(region => region.end <= time)
            .sort((a, b) => b.end - a.end)[0];
        
        if (prevRegion) {
            prevRegionEndTime = prevRegion.end;
        }
    }

    const timeDiff = time - prevRegionEndTime;
    const syncHours = Math.floor(timeDiff / 3600);
    const syncMinutes = Math.floor((timeDiff % 3600) / 60);
    const syncSeconds = Math.floor(timeDiff % 60);
    const syncMilliseconds = Math.floor((timeDiff % 1) * 1000);
    
    const syncTimeString = `${String(syncHours).padStart(2, '0')}:${String(syncMinutes).padStart(2, '0')}:${String(syncSeconds).padStart(2, '0')}.${String(syncMilliseconds).padStart(3, '0')}`;
    
    const syncTimeDisplay = document.getElementById('syncTimeDisplay');
    if (syncTimeDisplay) {
        syncTimeDisplay.textContent = syncTimeString;
        
        // 구간 제한 체크 확인 및 시간 초과 여부 확인
        const timeLimitCheck = document.getElementById('timeLimitCheck');
        const timeLimit = parseFloat(document.getElementById('timeLimit').value);
        
        if (timeLimitCheck.checked && timeDiff > timeLimit) {
            syncTimeDisplay.style.color = '#e74c3c'; // 빨간색으로 변경
            syncTimeDisplay.style.fontWeight = 'bold';
        } else {
            syncTimeDisplay.style.color = '#333'; // 기본 색상으로 복원
            syncTimeDisplay.style.fontWeight = 'normal';
        }
    }
}

//인풋박스 클릭 시 동작 함수
async function handleInputBoxClick(e) {
    try {
        // 이전에 포커스된 요소와 현재 클릭한 요소가 같은지 확인
        const previouslyFocusedElement = document.activeElement;
        
        if (previouslyFocusedElement === e.target) {
            //console.log('이미 포커스된 box를 클릭했습니다.');
            return;
        }

        // 현재 재생 중인 경우 먼저 정지
        await ws.pause();
        
        // 이전 체크 함수와 activeRegion 제거
        if (currentCheckEndTime) {
            ws.un('audioprocess', currentCheckEndTime);
            currentCheckEndTime = null;
        }
        activeRegion = null;

        const startTimeValue = parseFloat(e.target.getAttribute('start-time'));
        ws.setTime(startTimeValue);
        await ws.play();
    } catch (error) {
        if (error.name !== 'AbortError') {
            console.error('Playback error:', error);
        }
    }
}
    
    //모달창 열기 함수_화자추가 버튼 클릭 시 동작 함수
    document.getElementById('speakersettingButton').addEventListener('click', async function() {
      var modal = document.getElementById('myModal');
      modal.style.display = 'block';
    });
    
    //모달창 닫기 함수
    document.getElementsByClassName('close')[0].addEventListener('click', function() {
      var modal = document.getElementById('myModal');
      modal.style.display = 'none';
    });

    // 상용구 모달 열기
    boilerplateBtn.onclick = function() {
        boilerplateModal.style.display = "block";
    }

    // x 버튼으로 모달 닫기
    boilerplateCloseBtn.onclick = function() {
        boilerplateModal.style.display = "none";
    }

    // 모달 외부 클릭시 닫기
    window.onclick = function(event) {
        if (event.target == boilerplateModal) {
            boilerplateModal.style.display = "none";
        }
    }

    // 상용구 추가
    boilerplateAddBtn.onclick = function() {
        const boilerplateInput = document.querySelector('#BoilerplateModal .add-input');
        const inputValue = boilerplateInput.value.trim();
        
        // 입력값이 비어있는지 확인
        if (!inputValue) {
            alert('상용구를 입력하세요.');
            return;
        }
        
        // 콜론 없을 때 추가되도록 체크
        if (!inputValue.includes(':')) {
            alert('상용구는 콜론(:)을 포함해야 합니다.');
            return;
        }
        // 중복 검사
        const existingItems = Array.from(boilerplateList.querySelectorAll('li'));
        const isDuplicate = existingItems.some(item => item.textContent === inputValue);
        
        if (isDuplicate) {
            alert('이미 존재하는 상용구입니다.');
            return;
        }
        
        // 새로운 항목 추가
        const newItem = document.createElement('li');
        newItem.textContent = inputValue;
        boilerplateList.appendChild(newItem);
        boilerplateInput.value = ''; // 입력 필드 초기화
        saveBoilerplatesToLocalStorage(); // 상용구 추가 후 저장
    }

    // 상용구 수정
    boilerplateFixBtn.onclick = function() {
        const boilerplateInput = document.querySelector('#BoilerplateModal .add-input');
        const inputValue = boilerplateInput.value.trim();
        const selectedItem = boilerplateList.querySelector('li.selected');
        
        if (!selectedItem) {
            alert('수정할 항목을 선택하세요.');
            return;
        }
        
        if (!inputValue) {
            alert('상용구를 입력하세요.');
            return;
        }
        
        // 콜론 없을 때 수정 안 되도록 체크
        if (!inputValue.includes(':')) {
            alert('상용구는 콜론(:)을 포함해야 합니다.');
            return;
        }
        // 다른 항목과 중복되는지 확인 (현재 선택된 항목 제외)
        const otherItems = Array.from(boilerplateList.querySelectorAll('li')).filter(item => item !== selectedItem);
        const isDuplicate = otherItems.some(item => item.textContent === inputValue);
        
        if (isDuplicate) {
            alert('이미 존재하는 상용구입니다.');
            return;
        }
        
        selectedItem.textContent = inputValue;
        boilerplateInput.value = ''; // 입력 필드 초기화
        saveBoilerplatesToLocalStorage(); // 상용구 수정 후 저장
    }

    // 상용구 삭제
    boilerplateDeleteBtn.onclick = function() {
        const selectedItem = boilerplateList.querySelector('li.selected');
        if (selectedItem) {
            boilerplateList.removeChild(selectedItem);
        } else {
            alert('삭제할 항목을 선택하세요.');
        }
        saveBoilerplatesToLocalStorage(); // 상용구 삭제 후 저장
    }
    // 상용구 저장 함수
    function saveBoilerplatesToLocalStorage() {
        const boilerplateItems = boilerplateList.querySelectorAll('li');
        const boilerplates = Array.from(boilerplateItems).map(item => item.textContent.trim());
        localStorage.setItem('savedBoilerplates', JSON.stringify(boilerplates));
    }

    // 상용구 불러오기 함수
    function loadBoilerplatesFromLocalStorage() {
        const savedBoilerplates = localStorage.getItem('savedBoilerplates');
        if (savedBoilerplates) {
            const boilerplates = JSON.parse(savedBoilerplates);
            boilerplateList.innerHTML = ''; // 기존 목록 초기화
            boilerplates.forEach(text => {
                const newItem = document.createElement('li');
                newItem.textContent = text;
                boilerplateList.appendChild(newItem);
            });
        }
    }
    // 상용구 내보내기 버튼 클릭 시 함수
    boilerplateSaveBtn.addEventListener('click', function() {
        const boilerplateItems = boilerplateList.querySelectorAll('li');
        let iniContent = '';

        // 현재 날짜 구하기
        const today = new Date();
        const dateString = today.toISOString().split('T')[0].replace(/-/g, ''); // YYYYMMDD 형식

        boilerplateItems.forEach((item, index) => {
            const value = item.textContent.trim();
            iniContent += `item${index + 1}=${value}\n`;
        });

        const blob = new Blob([iniContent], { type: 'text/plain;charset=utf-8' });
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `media_tool_YT_상용구목록_${dateString}.ini`;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    });
    // 상용구 불러오기 버튼 클릭 시 함수
    boilerplateImportBtn.addEventListener('click', function() {
    const iniFileInput = document.createElement('input');
    iniFileInput.type = 'file';
    iniFileInput.accept = '.ini';
    iniFileInput.style.display = 'none';
    document.body.appendChild(iniFileInput);

    iniFileInput.addEventListener('change', function() {
        const file = iniFileInput.files[0];
        if (!file) {
            document.body.removeChild(iniFileInput);
            return;
        }

        const reader = new FileReader();
        reader.onload = function(e) {
            const contents = e.target.result;
            const lines = contents.split('\n');
            
            // 기존 리스트 초기화
            boilerplateList.innerHTML = '';
            
            lines.forEach(line => {
                const [key, value] = line.split('=');
                if (value) {
                    const newItem = document.createElement('li');
                    newItem.textContent = value.trim();
                    boilerplateList.appendChild(newItem);
                }
            });
            // 불러온 후 localStorage에 저장
            saveBoilerplatesToLocalStorage();
        };
        reader.readAsText(file);
        document.body.removeChild(iniFileInput);
    });

    iniFileInput.click();
});



    // 리스트 항목 클릭 시 선택 상태 토글
    boilerplateList.onclick = function(event) {
        if (event.target.tagName === 'LI') {
            const boilerplateInput = document.querySelector('#BoilerplateModal .add-input');
            const items = boilerplateList.querySelectorAll('li');
            
            // 다른 모든 항목의 선택 상태 제거
            items.forEach(item => item.classList.remove('selected'));
            
            // 클릭된 항목 선택
            event.target.classList.add('selected');
            
            // 선택된 항목의 텍스트를 입력 필드에 표시
            boilerplateInput.value = event.target.textContent;
            
            // 입력 필드에 포커스
            boilerplateInput.focus();
        }
    }
    // HTML 버튼 추가 부분
    const deleteBtn = document.querySelector('#boilerplate_delete_button');
    if (deleteBtn) {
        const resetBtn = document.createElement('button');
        resetBtn.id = 'boilerplateResetBtn';
        resetBtn.textContent = '초기화';
        resetBtn.style.backgroundColor = '#e74c3c';
        resetBtn.className = 'btn-add'; // 기존 버튼과 동일한 스타일 적용
        deleteBtn.parentNode.insertBefore(resetBtn, deleteBtn.nextSibling); // 삭제 버튼 옆에 추가

        // 초기화 버튼 클릭 이벤트
        resetBtn.addEventListener('click', function() {
            const confirmReset = confirm('상용구 목록을 모두 초기화하시겠습니까?');
            if (confirmReset) {
                boilerplateList.innerHTML = ''; // 목록 초기화
                saveBoilerplatesToLocalStorage(); // localStorage도 초기화
            }
        });
    }
    //화자 추가 버튼 클릭 시 함수
    document.getElementById('speaker_add_button').addEventListener('click', async function() {
      const parentElement = document.getElementById('speakers'); // .select-box 부모 요소
      const inputValue = document.getElementById('addInput').value; // 입력 필드의 값
      const existingLi = Array.from(parentElement.querySelectorAll('li')).find(li => li.textContent === inputValue); // 이미 존재하는 <li> 요소 확인
      
      if (existingLi) {
        alert("중복되었습니다."); // 중복된 값이 이미 존재하는 경우 알림창 표시
      } else {
        const newLi = document.createElement('li'); // 새로운 <li> 요소 생성
        newLi.textContent = inputValue; // 입력 필드의 값으로 텍스트 내용 설정
        newLi.addEventListener('click', function() {
          const selectedLi = parentElement.querySelector('.selected');
          if (selectedLi) {
            selectedLi.classList.remove('selected');
          }
          this.classList.add('selected');
          
          const selectedText = this.textContent;
          document.getElementById('addInput').value = selectedText;
        });  
        parentElement.appendChild(newLi); // 부모 요소에 새로운 <li> 요소 추가
      }
    });
    
    //화자 삭제 버튼 클릭 시 함수
    document.getElementById('speaker_delete_button').addEventListener('click', async function() {
      const parentElement = document.getElementById('speakers'); // .select-box 부모 요소
      const selectedLi = parentElement.querySelector('li.selected'); // 선택된 <li> 요소 확인
      
      if (selectedLi) {
        selectedLi.remove(); // 선택된 <li> 요소 삭제
      }
    });

    //화자 수정 버튼 클릭 시 함수
    document.getElementById('speaker_fix_button').addEventListener('click', async function() {
      const parentElement = document.getElementById('speakers'); // .select-box 부모 요소
      const selectedLi = parentElement.querySelector('li.selected'); // 선택된 <li> 요소 확인
      const inputValue = document.getElementById('addInput').value; // 입력 필드의 값
      
      if (selectedLi) {
        if (selectedLi.textContent === inputValue) {
          alert("변경된 값이 없습니다."); // 변경된 값이 없는 경우 알림창 표시
        } else if (Array.from(parentElement.querySelectorAll('li')).find(li => li.textContent === inputValue)) {
          alert("중복되었습니다."); // 중복된 값이 이미 존재하는 경우 알림창 표시
        } else {
          selectedLi.textContent = inputValue; // 선택된 <li> 요소의 텍스트 변경
        }
      }
    });
    

  // 불러오기 버튼 클릭 시 함수
  document.getElementById('loadButton').addEventListener('click', async function() {
    // 현재 선택된 비디오/오디오 파일명 확인
    const fileInput = document.getElementById('fileInput');
    if (!fileInput.files || fileInput.files.length === 0) {
        alert('먼저 비디오/오디오 파일을 선택해주세요.');
        return;
    }
    const mediaFileName = fileInput.files[0].name;
    const baseFileName = mediaFileName.substring(0, mediaFileName.lastIndexOf('.'));

    // 숨겨진 파일 입력 요소 생성
    const txtFileInput = document.createElement('input');
    txtFileInput.type = 'file';
    txtFileInput.accept = 'audio/*,video/*,text/*';
    txtFileInput.style.display = 'none';
    document.body.appendChild(txtFileInput);

    // 파일 선택 다이얼로그 트리거
    txtFileInput.click();

    txtFileInput.addEventListener('change', async function() {
        if (this.files.length === 0) {
            document.body.removeChild(txtFileInput);
            return;
        }

        const file = this.files[0];
        const txtFileName = file.name;
        const txtBaseFileName = txtFileName.substring(0, txtFileName.lastIndexOf('.'));
        if (!txtFileName.endsWith('.txt')) {
            alert('텍스트 파일을 선택해 주세요.');
            document.body.removeChild(txtFileInput);
            return;
        }
        // 파일명이 일치하는지 확인
        if (txtBaseFileName !== baseFileName) {
            const loadAnyway = confirm('선택한 텍스트 파일명이 현재 미디어 파일명과 다릅니다.\n계속 불러오시겠습니까?');
            if (!loadAnyway) {
                return;
            }
        }

        try {
            // FileReader를 사용하여 파일 내용 읽기
            const reader = new FileReader();
            reader.onload = async function(e) {
                const contents = e.target.result;

                // input_box_area 완전히 비우기
                const inputBoxArea = document.getElementById('input_box_area');
                inputBoxArea.innerHTML = '';

                // 기존 regions 모두 제거
                if (wsRegions) {
                    wsRegions.regions.forEach(region => {
                        region.remove();
                    });
                }

                // txt 파일 파싱 및 작업 복원
                const lines = contents.split('\n');
                const timeMatchLines = [];

                // 먼저 유효한 timeMatch가 있는 줄들만 찾기
                for (let i = 0; i < lines.length; i++) {
                    const line = lines[i].trim();
                    const timeMatch = line.match(/\s*-\s*\{(.+)\}(.*)/);
                    if (timeMatch) {
                        timeMatchLines.push({
                            line,
                            timeMatch,
                            index: i
                        });
                    }
                }

                // timeMatch가 있는 줄들 처리
                timeMatchLines.forEach((item, index) => {
                    const startTime = parseFloat(item.timeMatch[1]);
                    const text = item.timeMatch[2].trim();
                    const isLastTimeMatch = index === timeMatchLines.length - 1;

                    // input box 생성
                    const {
                        inputBox,
                        byteCounter
                    } = createInputBoxFromTxt(startTime, text);

                    // timeMatch의 마지막 줄이면 matching 값을 null로 설정
                    if (isLastTimeMatch) {
                        inputBox.setAttribute('data-matching', 'null');
                        byteCounter.setAttribute('byte-matching', 'null');
                    }

                    const matchingValue = inputBox.getAttribute('data-matching');
                    const speakerBox = createSpeakerBoxFromTxt(matchingValue);

                    inputBoxArea.appendChild(speakerBox);
                    inputBoxArea.appendChild(byteCounter);
                    inputBoxArea.appendChild(inputBox);
                    

                    // timeMatch의 마지막 줄이 아닐 때만 Region 생성
                    if (!isLastTimeMatch) {
                        const random = (min, max) => Math.random() * (max - min) + min;
                        const randomColor = () => `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.3)`;
                        const nanSu = inputBox.getAttribute('data-matching');

                        // 다음 timeMatch의 시작 시간을 현재 라인의 종료 시간으로 사용
                        const nextTimeMatch = timeMatchLines[index + 1].timeMatch;
                        const endTime = parseFloat(nextTimeMatch[1]);

                        // end-time 속성 설정
                        inputBox.setAttribute('end-time', endTime);

                        // region 생성
                        const region = wsRegions.addRegion({
                            id: nanSu,
                            start: parseFloat(startTime) || 0,
                            end: endTime,
                            content: text || ' ',
                            color: randomColor(),
                            resize: true,
                            drag: false
                        }, true);
                        // 구간 시간 계산 (end - start)
                        const duration = region.end - region.start;
                        const formattedDuration = Math.floor(duration * 1000) / 1000;
                        // 해당 speaker_box 찾아서 구간 시간 설정
                        const matchingSpeakerBox = document.querySelector(`[speaker-matching="${nanSu}"]`);
                        if (matchingSpeakerBox) {
                            matchingSpeakerBox.value = formattedDuration;
                            // 시간 제한 체크박스가 활성화된 경우에만 스타일 적용
                            const timeLimitCheck = document.getElementById('timeLimitCheck');
                            if (timeLimitCheck && timeLimitCheck.checked) {
                                // 매칭되는 input box 찾기
                                const matchingId = matchingSpeakerBox.getAttribute('speaker-matching');
                                const matchingInputBox = document.querySelector(`[data-matching="${matchingId}"]`);
                                
                                if (matchingInputBox) {
                                    const inputValue = matchingInputBox.value;
                                    const noSpaceValue = inputValue;
                                    const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");
                                    
                                    if (!isOnlyPercent) {  // %가 아닌 경우에만 스타일 적용
                                        const timeLimit = parseFloat(document.getElementById('timeLimit').value);
                                        if (formattedDuration >= timeLimit) {
                                            matchingSpeakerBox.style.border = '2px solid #e71212';
                                            matchingSpeakerBox.style.backgroundColor = '#f10303';
                                            matchingSpeakerBox.style.color = '#ffffff';
                                        } else {
                                            matchingSpeakerBox.style.border = '2px solid #ccc';
                                            matchingSpeakerBox.style.backgroundColor = '#f2f2f2';
                                            matchingSpeakerBox.style.color = '#333';
                                        }
                                    } else {
                                        // % 포함된 경우 기본 스타일
                                        matchingSpeakerBox.style.border = '2px solid #ccc';
                                        matchingSpeakerBox.style.backgroundColor = '#f2f2f2';
                                        matchingSpeakerBox.style.color = '#333';
                                    }
                                }
                            }
                        }
                        let currentCheckEndTime = null;
                        // region이 성공적으로 생성된 후에 이벤트 리스너 추가
                        // 구간 시간 계산 및 speaker_box 업데이트
                        if (region) {
                            wsRegions.on('region-clicked', async (region, e) => {
                                e.stopPropagation();

                                try {
                                    // 현재 재생 중인 경우 먼저 정지
                                    await ws.pause();

                                    // 이전 체크 함수 제거
                                    if (currentCheckEndTime) {
                                        ws.un('audioprocess', currentCheckEndTime);
                                        currentCheckEndTime = null;
                                    }

                                    activeRegion = region;

                                    // 매칭되는 input-box 찾기 및 포커스
                                    const matchingInputBox = document.querySelector(`[data-matching="${region.id}"]`);
                                    if (matchingInputBox) {
                                        matchingInputBox.focus();
                                        setTimeout(() => {
                                            matchingInputBox.setSelectionRange(0, 0);
                                            matchingInputBox.scrollLeft = 0;
                                            matchingInputBox.scrollTop = 0;
                                        }, 0);
                                        matchingInputBox.scrollIntoView({
                                            behavior: 'smooth',
                                            block: 'center'
                                        });
                                    }

                                    // 현재 region의 시작 시간으로 이동
                                    ws.setTime(region.start);
                                    await ws.play();

                                    // 새로운 재생 상태 모니터링
                                    currentCheckEndTime = () => {
                                        if (!activeRegion) return; // activeRegion이 없으면 체크하지 않음

                                        const currentTime = ws.getCurrentTime();
                                        if (currentTime >= activeRegion.end) {
                                            ws.pause();
                                            ws.setTime(activeRegion.end);
                                            ws.un('audioprocess', currentCheckEndTime);
                                            currentCheckEndTime = null;
                                            activeRegion = null;
                                        }
                                    };

                                    ws.on('audioprocess', currentCheckEndTime);

                                } catch (error) {
                                    if (error.name !== 'AbortError') {
                                        console.error('Playback error:', error);
                                    }
                                }
                            });
                            // region-업데이트 시 실행 함수
                            wsRegions.on('region-updated', (region, e) => {
                                activeRegion = region;
                                const clickedRegionId = region.id;
                                const clickedRegionStart = region.start;
                                const clickedRegionEnd = region.end;
                                //console.log('클릭된 지역 시작 시간:', clickedRegionStart);
                                //console.log('클릭된 지역 종료 시간:', clickedRegionEnd);

                                // 매칭되는 입력 상자 찾기
                                const matchingInputBox = document.querySelector(`[data-matching="${clickedRegionId}"]`);
                                if (matchingInputBox) {
                                    // 리전 조정에 따른 start-time 및 end-time 최신화
                                    matchingInputBox.setAttribute('start-time', clickedRegionStart);
                                    matchingInputBox.setAttribute('end-time', clickedRegionEnd);

                                    // 모든 input_box를 선택
                                    const inputBoxes = document.querySelectorAll('.input_box');
                                    
                                    // 현재 매칭되는 input_box의 인덱스를 찾기
                                    const currentIndex = Array.from(inputBoxes).indexOf(matchingInputBox);
                                    
                                    // 다음 input_box가 존재하는지 확인하고 start-time 업데이트
                                    if (currentIndex < inputBoxes.length - 1) { // 다음 요소가 있을 경우
                                        const nextInputBox = inputBoxes[currentIndex + 1];
                                        //console.log('다음 input_box의 start-time:', nextInputBox.getAttribute('start-time'));
                                        nextInputBox.setAttribute('start-time', clickedRegionEnd);
                                    } else {
                                        //console.log('다음 input_box가 존재하지 않습니다.');
                                    }
                                }

                                // 모든 input_box에 대해 각 위치를 최신화
                                const inputBoxes = document.querySelectorAll('.input_box');
                                inputBoxes.forEach((box, index) => {
                                    if (index === inputBoxes.length - 1) { // 마지막 input_box인 경우
                                        const prevEndTime = inputBoxes[index - 1].getAttribute('end-time');
                                        box.setAttribute('start-time', prevEndTime);
                                        if (prevEndTime !== null) { // 이전 input_box에 end-time이 있는지 확인
                                            box.setAttribute('start-time', prevEndTime);
                                        }
                                    }
                                });
                            });
                        }
                    }
                });

                // 이벤트 리스너 재설정
                const inputBoxes = document.querySelectorAll('.input_box');
                inputBoxes.forEach(inputBox => {
                    inputBox.addEventListener('mousedown', handleInputBoxClick);
                    inputBox.addEventListener('keydown', handleArrowNavigation);
                    inputBox.addEventListener('keypress', handleInputKeyPress);
                    inputBox.addEventListener('contextmenu', e => createContextMenu(e, inputBox));
                    inputBox.addEventListener('input', function() {
                        updateByteCounter(this);
                    });
                });

            };
            reader.readAsText(file);
        } catch (error) {
            console.error('Error loading file:', error);
            alert('파일을 불러오는 중 오류가 발생했습니다.');
        } finally {
            document.body.removeChild(txtFileInput);
        }
    });
    isContentSaved = true;
});

  function createInputBoxFromTxt(startTime, text) {
    const inputBox = document.createElement('textarea');
    inputBox.className = 'input_box';
    inputBox.value = text;
    inputBox.setAttribute('start-time', startTime);
    
    let nanSu = generateUniqueNanSu();
    while (hasDuplicateNanSu(nanSu.toString())) {
        nanSu = generateUniqueNanSu();
    }
    inputBox.setAttribute('data-matching', nanSu.toString());

    // ByteCounter 생성
    const byteCounter = document.createElement('div');
    byteCounter.className = 'byte-counter';
    const byteLimit = document.getElementById('byteLimit').value || 25;
    byteCounter.textContent = `0 / ${byteLimit} Bytes`;
    byteCounter.setAttribute('byte-matching', nanSu.toString());

    // input box에 이벤트 리스너 추가
    inputBox.addEventListener('mousedown', handleInputBoxClick);
    inputBox.addEventListener('keydown', handleArrowNavigation);
    inputBox.addEventListener('keypress', handleInputKeyPress);
    inputBox.addEventListener('contextmenu', e => createContextMenu(e, inputBox));
    inputBox.addEventListener('input', function() {
        updateByteCounter(this);
    });

    // ByteCounter 초기값 설정
    setTimeout(() => {
        updateByteCounter(inputBox);
    }, 0);

    return {
        inputBox,
        byteCounter
    };
}

// 새로운 Speaker box 생성 함수 (txt 파일용)
function createSpeakerBoxFromTxt(matchingValue) {
    const speakerBox = document.createElement('input');
    speakerBox.type = 'text';
    speakerBox.className = 'speaker_box';
    speakerBox.setAttribute('speaker-matching', matchingValue);
    speakerBox.setAttribute('tabindex', '-1');
    return speakerBox;
}


function handleArrowNavigation(event) {
    if (event.ctrlKey) {
        if (event.key === 'Backspace') {  // Ctrl + Backspace 처리
            event.preventDefault();
            handleDelete(event.target);
            return;
        }
        
        if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
            event.preventDefault();
            
            const allInputBoxes = Array.from(document.querySelectorAll('.input_box'));
            const currentIndex = allInputBoxes.indexOf(event.target);
            
            let newIndex;
            if (event.key === 'ArrowUp') {
                newIndex = Math.max(0, currentIndex - 1);
            } else {
                newIndex = Math.min(allInputBoxes.length - 1, currentIndex + 1);
            }
            
            if (newIndex !== currentIndex) {
                const targetInputBox = allInputBoxes[newIndex];
                targetInputBox.focus();
                
                setTimeout(() => {
                    targetInputBox.setSelectionRange(0, 0);
                    targetInputBox.scrollLeft = 0;
                    targetInputBox.scrollTop = 0;
                }, 0);
                
                const matchingValue = targetInputBox.dataset.matching;
                const region = wsRegions.regions.find(r => r.id.toString() === matchingValue);
                if (region) {
                    region.play();
                } else {
                    const startTime = parseFloat(targetInputBox.getAttribute('start-time'));
                    ws.seekTo(startTime / ws.getDuration());
                    ws.play();
                }
            }
        }
    }
}
    
function createContextMenu(e, inputBox) {
  e.preventDefault();
  
  const contextMenu = document.createElement('div');
  Object.assign(contextMenu.style, {
    position: 'absolute',
    top: `${e.clientY}px`,
    left: `${e.clientX}px`,
    background: '#fff',
    boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)'
  });
  
  const deleteMenuItem = createDeleteMenuItem(inputBox);
  contextMenu.appendChild(deleteMenuItem);
  document.body.appendChild(contextMenu);
  
  addContextMenuEventListeners(contextMenu);
}

function createDeleteMenuItem(inputBox) {
  const deleteMenuItem = document.createElement('div');
  Object.assign(deleteMenuItem.style, {
    cursor: 'pointer',
    padding: '2px 8px',
    background: '#eee',
    borderRadius: '4px'
  });
  deleteMenuItem.textContent = 'Delete';
  
  deleteMenuItem.addEventListener('click', () => handleDelete(inputBox));
  return deleteMenuItem;
}

function handleDelete(inputBox) {
    const matchingValue = inputBox.dataset.matching;
    const allInputBoxes = document.querySelectorAll('.input_box');
    const isLastSync = inputBox === allInputBoxes[allInputBoxes.length - 1];
    const prevLastInputBox = allInputBoxes[allInputBoxes.length - 2];

    // 이전 input box의 matchingValue를 가져옵니다.
    let prevLastInputBox_matchingValue = null;
    if (prevLastInputBox) {
        prevLastInputBox_matchingValue = prevLastInputBox.dataset.matching;
    }

    const isFirstSync = inputBox === allInputBoxes[0]; // 첫 번째 싱크 확인

    if (isFirstSync) { // 첫 번째 싱크일 경우
        alert('첫 번째 싱크는 삭제할 수 없습니다.');
        return;
    }

    // 이전 input box 찾기
    let prevInputBox = inputBox.previousElementSibling;
    while (prevInputBox && !prevInputBox.classList.contains('input_box')) {
        prevInputBox = prevInputBox.previousElementSibling;
    }

    if (prevInputBox) {
        // 이전 input box의 내용 뒤에 현재 내용 붙이기
        prevInputBox.value = prevInputBox.value.trim() + inputBox.value.trim();
        updateByteCounter(prevInputBox);

        // 삭제 후 이전 input box에 포커스
        prevInputBox.focus();
        setTimeout(() => {
            prevInputBox.setSelectionRange(0, 0);
            prevInputBox.scrollLeft = 0;
            prevInputBox.scrollTop = 0;
        }, 0);

        // 현재 region의 end-time을 이전 region의 end-time으로 설정
        const currentRegion = wsRegions.regions.find(r => r.id.toString() === matchingValue);
        if (currentRegion) {
            prevInputBox.setAttribute('end-time', currentRegion.end);
            // Region 내용과 끝 시간 업데이트
            const prevRegion = wsRegions.regions.find(r => r.id.toString() === prevInputBox.dataset.matching);
            if (prevRegion) {
                prevRegion.end = currentRegion.end;
                prevRegion.renderPosition();
                const regionContentElement = prevRegion.element.querySelector('[part="region-content"]');
                if (regionContentElement) {
                    regionContentElement.textContent = prevInputBox.value;
                }
                // 이전 speaker-box 시간 업데이트
                const updateSpeakerBoxStyle = (speakerBox, duration) => {
                    const timeLimitCheck = document.getElementById('timeLimitCheck');

                    if (timeLimitCheck && timeLimitCheck.checked) {
                        // speaker box에 매칭되는 input box 찾기
                        const matchingId = speakerBox.getAttribute('speaker-matching');
                        const matchingInputBox = document.querySelector(`[data-matching="${matchingId}"]`);

                        if (matchingInputBox) {
                            const inputValue = matchingInputBox.value;
                            const noSpaceValue = inputValue;
                            const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");

                            if (!isOnlyPercent) {  // %가 아닌 경우에만 스타일 적용
                                const timeLimit = parseFloat(document.getElementById('timeLimit').value);

                                if (duration >= timeLimit) {
                                    speakerBox.style.border = '2px solid #e71212';
                                    speakerBox.style.backgroundColor = '#f10303';
                                    speakerBox.style.color = '#ffffff';
                                } else {
                                    speakerBox.style.border = '2px solid #ccc';
                                    speakerBox.style.backgroundColor = '#f2f2f2';
                                    speakerBox.style.color = '#333';
                                }
                            } else {
                                // % 포함된 경우 기본 스타일
                                speakerBox.style.border = '2px solid #ccc';
                                speakerBox.style.backgroundColor = '#f2f2f2';
                                speakerBox.style.color = '#333';
                            }
                        } else {
                            // 매칭되는 input box가 없는 경우 기본 스타일
                            speakerBox.style.border = '2px solid #ccc';
                            speakerBox.style.backgroundColor = '#f2f2f2';
                            speakerBox.style.color = '#333';
                        }
                    } else {
                        // 체크박스 해제된 경우 기본 스타일
                        speakerBox.style.border = '2px solid #ccc';
                        speakerBox.style.backgroundColor = '#f2f2f2';
                        speakerBox.style.color = '#333';
                    }
                };
                const prevSpeakerBox = document.querySelector(`[speaker-matching="${prevInputBox.dataset.matching}"]`);
                if (prevSpeakerBox) {
                    const duration = prevRegion.end - prevRegion.start;
                    const formattedDuration = Math.floor(duration * 1000) / 1000;
                    prevSpeakerBox.value = formattedDuration;

                    // 스타일 업데이트 적용
                    updateSpeakerBoxStyle(prevSpeakerBox, duration);
                }

                // 이전 region에 avoidOverlapping 적용
                wsRegions.avoidOverlapping(prevRegion);

                // 이전 region의 이전 region이 있다면 그것도 업데이트
                const prevPrevRegion = wsRegions.regions.find(r =>
                    parseFloat(r.end) === parseFloat(prevRegion.start)
                );
                if (prevPrevRegion) {
                    wsRegions.avoidOverlapping(prevPrevRegion);
                }
            }
        }
    }
    if (isLastSync) {
        // 현재 region 찾기
        const region = wsRegions.regions.find(r => r.id.toString() === prevLastInputBox_matchingValue);
        const prevSpeakerBox = document.querySelector(`[speaker-matching="${prevLastInputBox_matchingValue}"]`);
        const prevByteCounter = document.querySelector(`[byte-matching="${prevLastInputBox_matchingValue}"]`);
        if (region) {
            // 현재 region의 인덱스 찾기
            const currentIndex = wsRegions.regions.indexOf(region);

            // 이전 region 찾기
            if (currentIndex > 0) { // 이전 region이 존재하는지 확인
                const previousRegion = wsRegions.regions[currentIndex - 1];
                // 이전 region에 대한 작업 수행
            }
            // Input box와 Speaker box 삭제
            const matchingInputBox = document.querySelector(`[data-matching="null"]`);
            const speakerMatchingInputBox = document.querySelector(`[speaker-matching="null"]`);
            const byteCounter = document.querySelector(`[byte-matching="null"]`);
            if (matchingInputBox) {
                updateNextInputBoxStartTime(matchingInputBox);
                matchingInputBox.remove();
            }

            if (speakerMatchingInputBox) {
                speakerMatchingInputBox.remove();
            }

            if (byteCounter) {
                byteCounter.remove();
            }
            prevSpeakerBox.value = '';
            prevInputBox.removeAttribute('end-time');
            prevInputBox.setAttribute('data-matching', 'null');
            prevSpeakerBox.setAttribute('speaker-matching', 'null');
            prevByteCounter.setAttribute('byte-matching', 'null');
            // speaker-box 스타일 초기화 추가
            prevSpeakerBox.style.border = '2px solid #ccc';
            prevSpeakerBox.style.backgroundColor = '#f2f2f2';
            prevSpeakerBox.style.color = '#333';
            // 현재 region 제거
            region.remove();
        }
    } else {
        // Region 삭제
        const region = wsRegions.regions.find(r => r.id.toString() === matchingValue);
        if (region) {
            region.remove();
        }
        // Input box와 Speaker box 삭제
        const matchingInputBox = document.querySelector(`[data-matching="${matchingValue}"]`);
        const speakerMatchingInputBox = document.querySelector(`[speaker-matching="${matchingValue}"]`);
        const byteCounter = document.querySelector(`[byte-matching="${matchingValue}"]`);
        if (matchingInputBox) {
            updateNextInputBoxStartTime(matchingInputBox);
            matchingInputBox.remove();
        }

        if (speakerMatchingInputBox) {
            speakerMatchingInputBox.remove();
        }

        if (byteCounter) {
            byteCounter.remove();
        }
    }

    updateLastInputBoxStartTime();

    // 모든 regions를 순회하면서 avoidOverlapping 적용
    wsRegions.regions.forEach(region => {
        wsRegions.avoidOverlapping(region);
    });
}

function updateNextInputBoxStartTime(currentInputBox) {
  const nextInputBox = currentInputBox.nextElementSibling;
  const prevInputBox = currentInputBox.previousElementSibling;
  
  if (nextInputBox && !nextInputBox.getAttribute('end-time')) {
    nextInputBox.setAttribute('start-time', prevInputBox.getAttribute('end-time'));
  }
}

function updateLastInputBoxStartTime() {
  const inputBoxes = document.querySelectorAll('.input_box');
  if (inputBoxes.length > 1) {
    const lastInputBox = inputBoxes[inputBoxes.length - 1];
    const secondLastInputBox = inputBoxes[inputBoxes.length - 2];
    
    if (secondLastInputBox.hasAttribute('end-time') && !lastInputBox.hasAttribute('end-time')) {
      lastInputBox.setAttribute('start-time', secondLastInputBox.getAttribute('end-time'));
    }
  }
}

function addContextMenuEventListeners(contextMenu) {
  document.addEventListener('mousedown', event => {
    if (event.button === 2) {
      contextMenu.remove();
    }
  });
  
  document.addEventListener('click', () => {
    contextMenu.remove();
  }, { once: true });
}
// timeLimit input에 이벤트 리스너 추가
document.getElementById('timeLimit').addEventListener('input', function() {
    if (document.getElementById('timeLimitCheck').checked) {
        const timeLimit = parseFloat(this.value);
        updateAllSpeakerBoxStyles(timeLimit);
    }
});
// 모든 speaker-box 스타일 업데이트 함수
function updateAllSpeakerBoxStyles(timeLimit) {
    const timeLimitCheck = document.getElementById('timeLimitCheck');
    if (!timeLimitCheck.checked) return;

    const speakerBoxes = document.querySelectorAll('.speaker_box');
    
    speakerBoxes.forEach(speakerBox => {
        const matchingId = speakerBox.getAttribute('speaker-matching');
        if (matchingId && matchingId !== 'null') {
            // 매칭되는 input box 찾기
            const matchingInputBox = document.querySelector(`[data-matching="${matchingId}"]`);
            
            if (matchingInputBox) {
                const inputValue = matchingInputBox.value;
                const noSpaceValue = inputValue;
                const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");
                
                if (!isOnlyPercent) {  // %가 아닌 경우에만 스타일 적용
                    const duration = parseFloat(speakerBox.value);
                    
                    if (duration >= timeLimit) {
                        speakerBox.style.border = '2px solid #e71212';
                        speakerBox.style.backgroundColor = '#f10303';
                        speakerBox.style.color = '#ffffff';
                    } else {
                        speakerBox.style.border = '2px solid #ccc';
                        speakerBox.style.backgroundColor = '#f2f2f2';
                        speakerBox.style.color = '#333';
                    }
                } else {
                    // % 포함된 경우 기본 스타일
                    speakerBox.style.border = '2px solid #ccc';
                    speakerBox.style.backgroundColor = '#f2f2f2';
                    speakerBox.style.color = '#333';
                }
            }
        }
    });
}




// 단축키 버튼 이벤트 리스너 추가
document.getElementById('shortcutButton').addEventListener('click', function() {
    document.getElementById('shortcutModal').style.display = 'block';
});

// 단축키 모달 닫기 버튼 이벤트 리스너
document.querySelector('#shortcutModal .close').addEventListener('click', function() {
    document.getElementById('shortcutModal').style.display = 'none';
});

// 모달 외부 클릭 시 닫기
window.addEventListener('click', function(event) {
    const shortcutModal = document.getElementById('shortcutModal');
    if (event.target === shortcutModal) {
        shortcutModal.style.display = 'none';
    }
});

// ESC 키로 모달 닫기
document.addEventListener('keydown', function(event) {
    if (event.key === 'Escape' && document.getElementById('shortcutModal').style.display === 'block') {
        document.getElementById('shortcutModal').style.display = 'none';
        event.stopPropagation(); // 다른 ESC 이벤트 실행 방지
    }
});

// 시간 입력값 저장
document.getElementById('backwardTime').addEventListener('change', function() {
    localStorage.setItem('backwardTime', this.value);
});

document.getElementById('forwardTime').addEventListener('change', function() {
    localStorage.setItem('forwardTime', this.value);
});

// 저장 형식, 제한 설정 저장
document.querySelectorAll('.save-format').forEach(checkbox => {
    checkbox.addEventListener('change', function() {
        localStorage.setItem(`saveFormat_${this.value}`, this.checked);
    });
});

document.getElementById('timeLimitCheck').addEventListener('change', function() {
    localStorage.setItem('timeLimitChecked', this.checked);
});

document.getElementById('timeLimit').addEventListener('change', function() {
    localStorage.setItem('timeLimit', this.value);
});

document.getElementById('byteLimitCheck').addEventListener('change', function() {
    localStorage.setItem('byteLimitChecked', this.checked);
});

document.getElementById('byteLimit').addEventListener('change', function() {
    localStorage.setItem('byteLimit', this.value);
});

// 페이지 로드 시 저장된 값 복원
window.addEventListener('load', function() {
    // 기존 시간 입력값 복원
    const backwardTime = localStorage.getItem('backwardTime');
    const forwardTime = localStorage.getItem('forwardTime');
    
    if (backwardTime) {
        document.getElementById('backwardTime').value = backwardTime;
    }
    if (forwardTime) {
        document.getElementById('forwardTime').value = forwardTime;
    }

    // 저장 형식 체크박스 상태 복원
    document.querySelectorAll('.save-format').forEach(checkbox => {
        const saved = localStorage.getItem(`saveFormat_${checkbox.value}`);
        if (saved !== null) {
            checkbox.checked = saved === 'true';
        }
    });

    // 구간 제한 설정 복원
    const timeLimitChecked = localStorage.getItem('timeLimitChecked');
    const timeLimit = localStorage.getItem('timeLimit');
    const timeLimitCheckbox = document.getElementById('timeLimitCheck');
    const timeLimitInput = document.getElementById('timeLimit');

    if (timeLimitChecked !== null) {
        timeLimitCheckbox.checked = timeLimitChecked === 'true';
        timeLimitInput.disabled = !timeLimitCheckbox.checked;
    }
    if (timeLimit) {
        timeLimitInput.value = timeLimit;
    }

    // 길이 제한 설정 복원
    const byteLimitChecked = localStorage.getItem('byteLimitChecked');
    const byteLimit = localStorage.getItem('byteLimit');
    const byteLimitCheckbox = document.getElementById('byteLimitCheck');
    const byteLimitInput = document.getElementById('byteLimit');

    if (byteLimitChecked !== null) {
        byteLimitCheckbox.checked = byteLimitChecked === 'true';
        byteLimitInput.disabled = !byteLimitCheckbox.checked;
    }
    if (byteLimit) {
        byteLimitInput.value = byteLimit;
    }

    // 설정 복원 후 스타일 업데이트
    if (timeLimitChecked === 'true') {
        updateAllSpeakerBoxStyles(parseFloat(timeLimit));
    }
    if (byteLimitChecked === 'true') {
        const inputBoxes = document.querySelectorAll('.input_box');
        inputBoxes.forEach(inputBox => updateByteCounter(inputBox));
    }
});

// EUC-KR 바이트 수 계산 함수
function getByteLength(str) {
    let byteLength = 0;
    for (let i = 0; i < str.length; i++) {
        const charCode = str.charCodeAt(i);
        // 한글 범위: AC00-D7AF (가-힣), 3130-318F (ㄱ-ㅎ, ㅏ-ㅣ)
        if ((charCode >= 0xAC00 && charCode <= 0xD7AF) || 
            (charCode >= 0x3130 && charCode <= 0x318F)) {
            byteLength += 2;
        } else {
            byteLength += 1;
        }
    }
    return byteLength;
}
// 바이트 카운터 업데이트 함수
function updateByteCounter(inputBox) {
    const text = inputBox.value;
    const byteSize = getByteLength(text);
    const byteLimitCheck = document.getElementById('byteLimitCheck');
    const byteLimit = parseInt(document.getElementById('byteLimit').value) || 25;
    const matchingId = inputBox.getAttribute('data-matching');
    const byteCounter = document.querySelector(`[byte-matching="${matchingId}"]`);
    const speakerBox = document.querySelector(`[speaker-matching="${matchingId}"]`);
    
    // % 체크 (speaker box 스타일링용)
    const noSpaceValue = text;
    const isOnlyPercent = (noSpaceValue.length === 1 && noSpaceValue === "%");

    // 매칭되는 region 찾기 및 업데이트
    if (matchingId !== 'null') {
        const matchingRegion = wsRegions.regions.find(r => r.id.toString() === matchingId);
        if (matchingRegion) {
            // region 콘텐츠 업데이트
            const regionContentElement = matchingRegion.element.querySelector('[part="region-content"]');
            if (regionContentElement) {
                regionContentElement.textContent = text;
            }
            
            // 구간 제한 체크 및 스타일 적용
            if (speakerBox && document.getElementById('timeLimitCheck').checked) {
                const duration = matchingRegion.end - matchingRegion.start;
                const timeLimit = parseFloat(document.getElementById('timeLimit').value);
                
                if (!isOnlyPercent && duration >= timeLimit) {
                    speakerBox.style.border = '2px solid #e71212';
                    speakerBox.style.backgroundColor = '#f10303';
                    speakerBox.style.color = '#ffffff';
                } else {
                    speakerBox.style.border = '2px solid #ccc';
                    speakerBox.style.backgroundColor = '#f2f2f2';
                    speakerBox.style.color = '#333';
                }
            }
            // 겹침 방지 적용
            wsRegions.avoidOverlapping(matchingRegion);
            
            // 이전 region이 있다면 겹침 방지 적용
            const prevRegion = wsRegions.regions.find(r => 
                parseFloat(r.end) === parseFloat(matchingRegion.start)
            );
            if (prevRegion) {
                wsRegions.avoidOverlapping(prevRegion);
            }
            
            // 다음 region이 있다면 겹침 방지 적용
            const nextRegion = wsRegions.regions.find(r => 
                parseFloat(r.start) >= parseFloat(matchingRegion.end)
            );
            if (nextRegion) {
                wsRegions.avoidOverlapping(nextRegion);
            }
        }
    }
    if (byteCounter) {
        byteCounter.textContent = `${byteSize} / ${byteLimit} Bytes`;
        
        // 체크된 경우에만 스타일 적용
        if (byteLimitCheck.checked && byteSize > byteLimit) {
            byteCounter.classList.add('exceeded');
            inputBox.style.color = '#e74c3c';
        } else {
            byteCounter.classList.remove('exceeded');
            inputBox.style.color = '';
        }
    }
}

// input box 내용 변경 시 저장 상태 업데이트
document.addEventListener('input', function(e) {
    if (e.target.classList.contains('input_box')) {
        isContentSaved = false; // 내용 변경 시 false로 설정
    }
});
// byteLimit input에 이벤트 리스너 추가
document.getElementById('byteLimit').addEventListener('input', function() {
    if (document.getElementById('byteLimitCheck').checked) {
        const byteLimit = parseInt(this.value) || 25;
        const inputBoxes = document.querySelectorAll('.input_box');
        inputBoxes.forEach(inputBox => updateByteCounter(inputBox));
    }
});

// 체크박스 이벤트 리스너 추가
document.getElementById('timeLimitCheck').addEventListener('change', function() {
    const timeLimitInput = document.getElementById('timeLimit');
    timeLimitInput.disabled = !this.checked;
    
    if (!this.checked) {
        // 체크 해제시 모든 speaker-box 스타일 초기화
        const speakerBoxes = document.querySelectorAll('.speaker_box');
        speakerBoxes.forEach(speakerBox => {
            speakerBox.style.border = '2px solid #ccc';
            speakerBox.style.backgroundColor = '#f2f2f2';
            speakerBox.style.color = '#333';
        });
    } else {
        // 체크시 현재 값으로 스타일 업데이트
        updateAllSpeakerBoxStyles(parseFloat(timeLimitInput.value));
    }
});

document.getElementById('byteLimitCheck').addEventListener('change', function() {
    const byteLimitInput = document.getElementById('byteLimit');
    byteLimitInput.disabled = !this.checked;
    
    if (!this.checked) {
        // 체크 해제시 모든 byte counter와 input box 스타일 초기화
        const byteCounters = document.querySelectorAll('.byte-counter');
        const inputBoxes = document.querySelectorAll('.input_box');
        
        byteCounters.forEach(counter => {
            counter.classList.remove('exceeded');
        });
        
        inputBoxes.forEach(inputBox => {
            inputBox.style.color = '';
        });
    } else {
        // 체크시 현재 값으로 스타일 업데이트
        const inputBoxes = document.querySelectorAll('.input_box');
        inputBoxes.forEach(inputBox => {
            updateByteCounter(inputBox);
        });
    }
});

// 페이지 로드 시 로그인 상태 확인
window.onload = function() {
    fetch('check_login.php')
        .then(response => response.json())
        .then(data => {
            if (data.isLoggedIn) {
                document.getElementById('loginModal').style.display = 'none';
                document.getElementById('mainContent').style.display = 'block';
            } else {
                document.getElementById('loginModal').style.display = 'block';
                document.getElementById('mainContent').style.display = 'none';
            }
        });
}

document.addEventListener('DOMContentLoaded', function() {
    loadBoilerplatesFromLocalStorage();
    // 페이지 로드 시 로그인 상태 확인
    const isLoggedIn = sessionStorage.getItem('isLoggedIn');
    if (isLoggedIn === 'true') {
        document.getElementById('loginModal').style.display = 'none';
        document.getElementById('mainContent').style.display = 'block';
    }

    // Enter 키로 폼 제출 (선택사항)
    document.getElementById('password').addEventListener('keypress', function(e) {
        if (e.key === 'Enter') {
            e.preventDefault();
            document.querySelector('#loginModal form').submit();
        }
    });
});

async function login() {
    const username = document.getElementById('username').value;
    const password = document.getElementById('password').value;
    
    // 여기에 원하는 아이디/비밀번호 조합을 설정하세요
    const validUsername = 'guest';
    // 비밀 키 설정
    
    const validPassword = await generatePassword();
    if (username === validUsername && password === validPassword) {
        document.getElementById('loginModal').style.display = 'none';
        document.getElementById('mainContent').style.display = 'block';
        
        // 로그인 상태를 세션 스토리지에 저장
        sessionStorage.setItem('isLoggedIn', 'true');
    } else {
        alert('아이디 또는 비밀번호가 올바르지 않습니다.');
    }
}
// 날짜와 비밀 키를 조합하여 SHA-256 암호 생성
async function generatePassword() {
    // 오늘 날짜에 4885일 추가
    const today = new Date();
    today.setDate(today.getDate() + 4885);
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, '0');
    const day = String(today.getDate()).padStart(2, '0');
    const dateStr = `${year}${month}${day}`;

    // 해시 생성할 문자열 (날짜 + 비밀 키)
    const secretKey = "who";
    const rawData = dateStr + secretKey;
    
    // SHA-256 해시 생성
    const encoder = new TextEncoder();
    const data = encoder.encode(rawData);
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
            
                // 해시값을 16진수 문자열로 변환 후 10자리 사용
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    return hashHex.slice(0, 4);
}

document.addEventListener('keydown', function(e) {
    if (e.key === 'F3') {
        e.preventDefault(); // 기본 F3 동작 방지
        
        // 현재 포커스된 요소가 input_box인지 확인
        if (document.activeElement.classList.contains('input_box')) {
            const inputBox = document.activeElement;
            const currentText = inputBox.value;
            const cursorPosition = inputBox.selectionStart;
            
            // 커서 위치 이전의 텍스트만 고려
            const textBeforeCursor = currentText.substring(0, cursorPosition);
            const textAfterCursor = currentText.substring(cursorPosition);
            
            // 마지막 단어 찾기 (공백 이후의 텍스트)
            const lastWord = textBeforeCursor.split(/\s/).pop();
            
            if (lastWord) {
                // 상용구 목록에서 일치하는 항목 찾기
                const boilerplates = document.querySelectorAll('#boilerplates li');
                for (const boilerplate of boilerplates) {
                    const boilerplateText = boilerplate.textContent;
                    // 콜론(:)으로 구분된 형식 확인
                    const [key, value] = boilerplateText.split(':');
                    
                    if (key === lastWord && value) {
                        // 마지막 단어를 상용구로 교체
                        const textBeforeWord = textBeforeCursor.substring(0, textBeforeCursor.length - lastWord.length);
                        inputBox.value = textBeforeWord + value.trim() + textAfterCursor;
                        
                        // 커서 위치 조정
                        const newCursorPosition = textBeforeWord.length + value.trim().length;
                        inputBox.setSelectionRange(newCursorPosition, newCursorPosition);
                        return;
                    }
                }
                // 일치하는 상용구가 없을 경우 알림
                alert('일치하는 상용구가 없습니다.');
            }
        }
    }
});
  </script>
</body>

</html>