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

<head>
    <link rel="icon" href="./image/waveform_icon.svg" type="image/x-icon">
    <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;
        }



        
        /* 모달 창을 가운데 정렬하기 위한 스타일 */
        .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;
            white-space: nowrap;
            text-overflow: ellipsis; /* 넘치는 텍스트를 ...으로 표시 */
        }

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


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


        #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;
        }


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

        /* Webkit (Chrome, Safari, Edge) 용 thumb 스타일 */
        #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;
            border: none;  /* Edge에서 기본 테두리 제거 */
        }

        /* Firefox용 thumb 스타일 */
        #zoomSlider::-moz-range-thumb {
            width: 15px;
            height: 15px;
            border-radius: 50%;
            background: #1ec49d;
            cursor: pointer;
            transition: background 0.2s ease;
            border: none;
        }

        /* Edge용 track 스타일 */
        #zoomSlider::-ms-track {
            width: 100%;
            height: 4px;
            background: transparent;
            border-color: transparent;
            color: transparent;
        }

        /* Edge용 fill 스타일 */
        #zoomSlider::-ms-fill-lower,
        #zoomSlider::-ms-fill-upper {
            background: #ddd;
            border-radius: 2px;
        }

        /* 호버 효과 */
        #zoomSlider::-webkit-slider-thumb:hover {
            background: #16a085;
        }

        #zoomSlider::-moz-range-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: 5px;
            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);
            }
        }

        /* 저장 형식 체크박스 스타일링 */
        /* 체크박스 공통 스타일 */
        input[type="checkbox"].save-format {
            appearance: none;
            -webkit-appearance: none;
            width: 16px;
            height: 16px;
            border: 2px solid #1ec49d;
            border-radius: 4px;
            margin-right: 5px;
            position: relative;
            cursor: pointer;
            vertical-align: middle;
            transition: all 0.2s ease;
        }

        input[type="checkbox"].save-format:checked {
            background-color: #1ec49d;
        }

        input[type="checkbox"].save-format:checked::after {
            content: '✓';
            position: absolute;
            color: white;
            font-size: 12px;
            left: 2px;
            top: -1px;
        }

        input[type="checkbox"].save-format:hover {
            border-color: #16a085;
        }

        input[type="checkbox"].save-format:checked:hover {
            background-color: #16a085;
        }

        /* 다크모드 대응 */
        @media (prefers-color-scheme: dark) {
            #LimitContainer span {
                color: #eee;
            }
        }


        #loadingOverlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.7);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 9999;
        }

        .loading-spinner-container {
            position: relative;
            width: 60px;  /* 컨테이너 크기 지정 */
            height: 60px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .loading-spinner {
            position: absolute;
            width: 100%;
            height: 100%;
            border: 5px solid #f3f3f3;
            border-top: 5px solid #25D097;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        .loading-progress {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #fff;
            font-size: 12px;
            font-weight: bold;
        }

        .loading-text {
            color: #fff;
            margin-top: 20px;
            font-size: 18px;
            font-weight: bold;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </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">F3</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">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="loadingOverlay" style="display: none;">
        <div class="loading-spinner-container">
            <div class="loading-spinner"></div>
            <div class="loading-progress" style="display: none;">0%</div>
        </div>
        <div class="loading-text">파형 분석 중...</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 style="font-size: 12px; color: #666; margin-bottom: 2px;">
                예시 -> <span style="color: #1ec49d; font-weight: bold;">상:상용구</span> 추가 후 전사창에서 "상" 입력 후 F3
            </label>
            <ul class="select-box" id="boilerplates">
            </ul>
            <div class="add-box">
                <div style="display: flex; align-items: center; gap: 5px;">
                    <label for="addInput" style="margin-right: 5px;">상용구</label>
                    <input type="text" class="add-input" id="addInput" style="height: 15px;">
                    <button type="button" class="btn-add" id="boilerplate_add_button" style="height: 20px;">추가</button>
                    <button type="button" class="btn-add" id="boilerplate_fix_button" style="height: 20px;">수정</button>
                    <button type="button" class="btn-add" id="boilerplate_delete_button" style="height: 20px; background-color: #e74c3c;">삭제</button>
                </div>
                <button type="button" class="btn-add" id="boilerplateResetBtn" style="background-color: #e74c3c;">초기화</button>
                <button type="button" class="btn-add" id="boilerplate_save_button" style="margin-top: 10px; background-color: #f39c12; margin-left: 45%;">내보내기</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>1.0</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">New</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; min-width: 200px;">
                <label style="display: flex; align-items: center; min-width: 140px;">
                    <input type="checkbox" id="timeLimitCheck" class="save-format">
                    <span>구간 제한(초)</span>
                </label>
                <input type="number" id="timeLimit" min="1" max="3600" value="30" style="width: 50px; height: 20px;">
            </div>
            <div style="display: flex; align-items: center; min-width: 200px;">
                <label style="display: flex; align-items: center; min-width: 140px;">
                    <input type="checkbox" id="byteLimitCheck" class="save-format">
                    <span>길이 제한(Byte)</span>
                </label>
                <input type="number" id="byteLimit" min="1" max="2000" value="25" style="width: 50px; height: 20px;">
            </div>
        </div>
        <div style="display: flex; flex-direction: column; align-items: center;">
            
            <input type="range" id="zoomSlider" min="100" 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>
                <textarea class="input_box" start-time="0.00000" data-matching=null></textarea>
                
            </div>
        </div>
        <div id="blank_area">

        </div>
    </div>
    </div>
    <script src="./dist/Jquery.js"></script>
    <script type="module">
import WaveSurfer from './dist/wavesurfer.js';
import RegionsPlugin from './dist/plugins/regions.js';
import TimelinePlugin from './dist/plugins/timeline.js';
import Minimap from './dist/plugins/minimap.js';

window.regions = RegionsPlugin.create()
const fileInput = document.getElementById('fileInput');
let wavesurfer = null; // 전역 변수로 선언
let currentCheckEndTime = null; // 전역 변수로 추가
let activeRegion = null;
let isContentSaved = true; // 초기값은 true로 설정

// 상용구 모달 관련 요소들
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 handleInputKeyPress(e) {
    if (e.key === 'Enter') {
        if (e.shiftKey) {
            e.preventDefault();
            alert('줄바꿈을 할 수 없습니다.');
            return;
        }
        e.preventDefault();
    }
    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');
        window.end_time = wavesurfer.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 = " ";  
        }
        
        // region 추가
        regions.addRegion({
        id: nan_su, 
        start: parseFloat(startTimeValue),
        end: end_time,
        content: leftText,
        color: randomColor(),
        resize: true, 
        drag: false
        });

        // region 생성 후 별도의 timeout으로 확인
        setTimeout(() => {
            const waveformElement = document.querySelector('#waveform').firstElementChild;
            if (waveformElement && waveformElement.shadowRoot) {
                const regionElements = Array.from(
                    waveformElement.shadowRoot.querySelectorAll('div[part*="region"]')
                );
                regions.avoidOverlapping(regionElements);
                //reorderRegionDivs();
            } else {
            }
        }, 100);  // 시간을 100ms로 설정

        
        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);
        // input 이벤트에 바이트 카운터 업데이트 추가
        newInputBox.addEventListener('input', function() {
          updateByteCounter(this);
        });
        newInputBox.value = trimmedValue;
        // 만약 newinputbox와 매칭되는 speaker_box가 있으면 구간 시간 설정  
        
        // speaker_box 추가
        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;
        }
        // data-matching 찾기
        let nextElement = e.target.nextElementSibling;
        while (nextElement) {
            if (nextElement.hasAttribute("data-matching")) {
                // data-matching 속성을 가진 요소를 찾으면 루프 종료
                break;
            }
            nextElement = nextElement.nextElementSibling;
        }

        // data-matching 찾기
        if (nextElement !== null) {
        // 다음 input_box 찾기
            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 < regions.regions.length; i++) {
                    const regionId = regions.regions[i].id;
                    if (regionId.toString() === matchingValue) {
                        const currentRegion = regions.regions[i];
                
                        // region 수정
                        currentRegion.setOptions({
                        start: end_time
                        });
                        const regionContentElement = currentRegion.element.querySelector('[part="region-content"]');
                        regionContentElement.textContent = trimmedValue;
                        // 현재 region에 avoidOverlapping 적용
                        regions.avoidOverlapping(currentRegion);
                        
                        // 이전 region이 있다면 avoidOverlapping 적용
                        const prevRegion = regions.regions.find(r => 
                        parseFloat(r.end) === parseFloat(currentRegion.start)
                        );
                        if (prevRegion) {
                            regions.avoidOverlapping(prevRegion);
                        }
                        // 다음 region이 있다면 avoidOverlapping 적용
                        const nextRegion = regions.regions.find(r => 
                        parseFloat(r.start) >= parseFloat(currentRegion.end)
                        );
                        if (nextRegion) {
                            regions.avoidOverlapping(nextRegion);
                        }
                        break;
                    }
                
                }
            }
        } 
        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"))
        // newInputBox와 매칭되는 region을 찾기
        const matchingRegion = regions.regions.find(r => r.id.toString() === newInputBox.getAttribute("data-matching"));
        if (matchingRegion) {
            const duration = matchingRegion.end - matchingRegion.start;
            const formattedDurations = Math.floor(duration * 1000) / 1000; // 반올림하지 않고 소수점 3자리까지 표시
            newspeakerBox.value = formattedDurations;
        }
        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' });
        }
}




// 줌 슬라이더 이벤트 리스너
const zoomSlider = document.querySelector('#zoomSlider')
zoomSlider.addEventListener('input', (e) => {
    if (!wavesurfer) return; // wavesurfer가 초기화되지 않았으면 리턴

    const minPxPerSec = 1
    const maxPxPerSec = 1000
    const zoomLevel = e.target.value
    
    const pxPerSec = minPxPerSec + ((maxPxPerSec - minPxPerSec) * (zoomLevel / 1000))
    wavesurfer.zoom(pxPerSec)
})

// 최근 폴더로 다시 세팅
function previousFileSetting(){
    const previousFile = fileInput.dataset.previousFile;
    if (previousFile) {
        const dt = new DataTransfer();
        const previousFileObj = fileInput.dataset.previousFileObj ? 
            JSON.parse(fileInput.dataset.previousFileObj) : null;
        
        if (previousFileObj) {
            const file = new File([previousFileObj.content], previousFileObj.name, {
                type: previousFileObj.type,
                lastModified: previousFileObj.lastModified
            });
            dt.items.add(file);
            fileInput.files = dt.files;
        }
    }
}



// 파일 불러오기 이벤트
fileInput.setAttribute('multiple', 'true');
fileInput.setAttribute('accept', 'video/*,audio/*,.txt');
fileInput.addEventListener('change', async (event) => {
    // 저장되지 않은 내용이 있는 경우 확인
    if (!isContentSaved) {
        const confirmChange = confirm('저장하지 않으셨습니다. 그래도 파일을 선택하시겠습니까?');
        if (!confirmChange) {
            previousFileSetting()
            return;
        }
    }

    const files = Array.from(event.target.files);

    // 미디어 파일과 텍스트 파일 찾기
    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/'));
    
    if (files.length === 0) {
        alert('파일을 선택해주세요.');
        previousFileSetting()
        return;
    }
    if (!txtFile) {
        if (files.length > 1) {
            alert('텍스트 파일과 미디어 파일을 선택해주세요.');
            previousFileSetting()
            return;
        }
    }
    if (!mediaFile) {
        alert('미디어 파일을 선택해주세요.');
        previousFileSetting()
        return;
    }
    // 파일 개수 체크
    if (files.length > 2) {
        alert('파일은 최대 2개까지만 선택할 수 있습니다.');
        previousFileSetting()
        return;
    }
    
    const video = document.querySelector('#video');
    const bottomTimeline = TimelinePlugin.create({
        height: 10,
        timeInterval: 10,
        primaryLabelInterval: 60,
        secondaryLabelInterval: 60,
        style: {
            fontSize: '10px',
            color: '#6A3274',
        },
    });
    video.pause();
    video.removeAttribute('src');
    video.load();

    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);
        }
        initializeWaveSurfer();
        const url = URL.createObjectURL(mediaFile);

        wavesurfer = WaveSurfer.create({
            container: '#waveform',
            waveColor: '#25D097',
            progressColor: '#D4D1E0',
            cursorColor: 'red',
            cursorWidth: 2,
            height: 70,
            normalize: true,
            backend: 'MediaElement',
            url: url,
            mediaControls: true,
            interact: true,
            autoCenter: false,
            hideScrollbar: false,
            responsive: true,
            media: video,
            minPxPerSec: 100,
            maxPxPerSec: 1000,
            plugins: [
                // Register the plugin
                Minimap.create({
                    height: 20,
                    waveColor: '#ddd',
                    progressColor: '#999',
                    // the Minimap takes all the same options as the WaveSurfer itself
                }),
                bottomTimeline,
                window.regions,
            ],
        })
        
        // 초기화 함수 정의
        const initializeWavesurferEvents = () => {
            const initialZoom = zoomSlider.value;
            const minPxPerSec = 100;
            const maxPxPerSec = 1000;
            const pxPerSec = minPxPerSec + ((maxPxPerSec - minPxPerSec) * (initialZoom / 1000));
            wavesurfer.zoom(pxPerSec);
            
            // 시간 업데이트를 위한 이벤트 리스너 추가
            wavesurfer.on('audioprocess', updateTimeDisplay);   
            wavesurfer.on('pause', () => {
                const currentTime = wavesurfer.getCurrentTime();
                updateTimeDisplay(currentTime);
            });
            
            // 파형 클릭 이벤트 추가
            wavesurfer.on('click', async() => {
                await wavesurfer.pause();
                if (currentCheckEndTime) {
                    wavesurfer.un('audioprocess', currentCheckEndTime);
                    currentCheckEndTime = null;
                }
                activeRegion = null;
            });
        };

        // 캔버스 대기 후 이벤트 초기화
        await waitForCanvases();
        initializeWavesurferEvents();
        // 웨이브서퍼 로드 완료 후 초기 줌 레벨 설정
        wavesurfer.on('ready', () => {
            const initialZoom = zoomSlider.value
            const minPxPerSec = 100
            const maxPxPerSec = 1000
            const pxPerSec = minPxPerSec + ((maxPxPerSec - minPxPerSec) * (initialZoom / 1000))
            wavesurfer.zoom(pxPerSec)
            // 시간 업데이트를 위한 이벤트 리스너 추가
            wavesurfer.on('audioprocess', updateTimeDisplay);   
            wavesurfer.on('pause', () => {
                const currentTime = wavesurfer.getCurrentTime();
                updateTimeDisplay(currentTime);
            });
            // Give regions a random color when they are created
            const random = (min, max) => Math.random() * (max - min) + min
            const randomColor = () => `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)`
            const inputElement = document.querySelector('.input_box');
            inputElement.setAttribute('data-matching', null);
        })
        const previousFile = mediaFile.name;
        
        //텍스트파일 읽어서 내용 출력
        if (txtFile) {
            const loadingOverlay = document.getElementById('loadingOverlay');
            const loadingText = loadingOverlay.querySelector('.loading-text');
            const loadingProgress = loadingOverlay.querySelector('.loading-progress');

            loadingOverlay.style.display = 'flex';
            loadingText.textContent = '구역 생성 중...';
            const reader = new FileReader();
            reader.onload = async function(e) {  // async 추가
                const contents = e.target.result;

                // input_box_area 비우기 전에 기존 regions 제거
                if (regions) {
                    regions.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가 있는 줄들 처리
                for (let i = 0; i < timeMatchLines.length; i++) {
                    const item = timeMatchLines[i];
                    const progress = Math.round((i / timeMatchLines.length) * 100);
                    loadingProgress.textContent = `${progress}%`;
                    const startTime = parseFloat(item.timeMatch[1]);
                    const text = item.timeMatch[2].trim();
                    const isLastTimeMatch = i === 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[i + 1].timeMatch;
                        const endTime = parseFloat(nextTimeMatch[1]);

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

                        // region 생성
                        const region = regions.addRegion({
                            id: nanSu,
                            start: parseFloat(startTime) || 0,
                            end: endTime,
                            content: text || ' ',
                            color: randomColor(),
                            resize: true,
                            drag: false
                        }, true);
                        // region 포커스
                        // 구간 시간 계산 (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;
                    }
                };
                // 작업 완료 후 로딩 화면 숨김
                loadingProgress.textContent = '100%';
                await new Promise(resolve => setTimeout(resolve, 500));
                loadingOverlay.style.display = 'none';
            };
            reader.readAsText(txtFile);
        }
    }
    // 유효한 파일이 선택된 경우 이전 파일로 저장
    fileInput.dataset.previousFile = mediaFile.name;
    fileInput.dataset.previousFileObj = JSON.stringify({
        name: mediaFile.name,
        type: mediaFile.type,
        lastModified: mediaFile.lastModified,
        content: await mediaFile.arrayBuffer()
    });
    previousFileSetting()
});

// input_box 엔터 키 이벤트
document.addEventListener('keypress', (e) => {
    // input_box 클래스를 가진 요소에서만 동작하도록 체크
    if (e.target.classList.contains('input_box')) {
        handleInputKeyPress(e);
    }
});

// 컨트롤 + 화살표 이동 이벤트 추가
document.addEventListener('keydown', handleArrowNavigation);

// 바이트 카운터 업데이트 함수
document.addEventListener('input', function(e) {
    if (e.target.classList.contains('input_box')) {
        updateByteCounter(e.target);
    }
});

// 인풋박스 클릭 이벤트
document.addEventListener('mousedown', function(e) {
    if (e.target.classList.contains('input_box')) {
        handleInputBoxClick(e);
    }
});

// 인풋박스 오른쪽 클릭 이벤트
document.addEventListener('contextmenu', function(e) {
    if (e.target.classList.contains('input_box')) {
        createContextMenu(e, e.target);
    }
}); 

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 = regions.regions.find(r => r.id.toString() === matchingValue);
        if (currentRegion) {
            prevInputBox.setAttribute('end-time', currentRegion.end);
            // Region 내용과 끝 시간 업데이트
            const prevRegion = regions.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 적용
                regions.avoidOverlapping(prevRegion);

                // 이전 region의 이전 region이 있다면 그것도 업데이트
                const prevPrevRegion = regions.regions.find(r =>
                    parseFloat(r.end) === parseFloat(prevRegion.start)
                );
                if (prevPrevRegion) {
                    regions.avoidOverlapping(prevPrevRegion);
                }
            }
        }
    }
    if (isLastSync) {
        // 현재 region 찾기
        const region = regions.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 = regions.regions.indexOf(region);

            // 이전 region 찾기
            if (currentIndex > 0) { // 이전 region이 존재하는지 확인
                const previousRegion = regions.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 = regions.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 적용
    regions.regions.forEach(region => {
        regions.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 });
}

// region 클릭 이벤트
regions.on('region-clicked', async (region, e) => {
    e.stopPropagation();

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

        // 이전 체크 함수 제거
        if (currentCheckEndTime) {
            wavesurfer.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의 시작 시간으로 이동
        wavesurfer.setTime(region.start);
        await wavesurfer.play();

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

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

        wavesurfer.on('audioprocess', currentCheckEndTime);

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

// region-업데이트 시 실행 함수
regions.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);
            }
        }
    });
});

//난수 생성 함수
    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 반환
    }


// 인풋박스 화살표 이동 함수
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 = regions.regions.find(r => r.id.toString() === matchingValue);
                if (region) {
                    region.play();
                } else {
                    const startTime = parseFloat(targetInputBox.getAttribute('start-time'));
                    wavesurfer.seekTo(startTime / wavesurfer.getDuration());
                    wavesurfer.play();
                }
            }
        }
    }
}

// 바이트 카운터 업데이트 함수
function updateByteCounter(e) {
     // inputElement가 이벤트 객체인 경우 target을 사용
    const element = e.target || e;
    const text = element.value;
    const byteSize = getByteLength(text);
    const byteLimitCheck = document.getElementById('byteLimitCheck');
    const byteLimit = parseInt(document.getElementById('byteLimit').value) || 25;
    const matchingId = element.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 = regions.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';
                }
            }
            // 겹침 방지 적용
            regions.avoidOverlapping(matchingRegion);
            
            // 이전 region이 있다면 겹침 방지 적용
            const prevRegion = regions.regions.find(r => 
                parseFloat(r.end) === parseFloat(matchingRegion.start)
            );
            if (prevRegion) {
                regions.avoidOverlapping(prevRegion);
            }
            
            // 다음 region이 있다면 겹침 방지 적용
            const nextRegion = regions.regions.find(r => 
                parseFloat(r.start) >= parseFloat(matchingRegion.end)
            );
            if (nextRegion) {
                regions.avoidOverlapping(nextRegion);
            }
        }
    }
    if (byteCounter) {
        byteCounter.textContent = `${byteSize} / ${byteLimit} Bytes`;
        
        // 체크된 경우에만 스타일 적용
        if (byteLimitCheck.checked && byteSize > byteLimit) {
            byteCounter.classList.add('exceeded');
            element.style.color = '#e74c3c';
        } else {
            byteCounter.classList.remove('exceeded');
            element.style.color = '';
        }
    }
}

// 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;
}

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

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

        const startTimeValue = parseFloat(e.target.getAttribute('start-time'));
        wavesurfer.setTime(startTimeValue);
        await wavesurfer.play();
    } catch (error) {
        if (error.name !== 'AbortError') {
            console.error('Playback error:', error);
        }
    }
}

// ESC 입력 시 함수
document.addEventListener('keydown', async function(e) {
    if (e.keyCode === 27) { // ESC 키
        e.preventDefault();
        try {
            if (wavesurfer.isPlaying()) {
                await wavesurfer.pause();
            } else {
                await wavesurfer.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;
            wavesurfer.seekTo((wavesurfer.getCurrentTime() - backwardTime) / wavesurfer.getDuration());
            await wavesurfer.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;
            wavesurfer.seekTo((wavesurfer.getCurrentTime() + forwardTime) / wavesurfer.getDuration());
            await wavesurfer.play();
        } catch (error) {
            if (error.name !== 'AbortError') {
                console.error('Playback error:', error);
            }
        }
    }
});


/*
// region div 재정렬 함수   
function reorderRegionDivs() {
    if (!window.regions || !window.regions.regions) return; // 안전장치 추가
    // 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 = window.regions.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 regionElements = Array.from(document.querySelector('#waveform')
        .firstElementChild.shadowRoot
        .querySelectorAll('[part^="region "]'));
    
    matchingOrder.forEach(matchingValue => {
        const regionDiv = regionElements.find(region => 
        region.getAttribute('part') === `region ${matchingValue}`
        );
        if (regionDiv) {
        regionContainer.appendChild(regionDiv);
        }
        
    });
    // 4. regions 배열 업데이트
    window.regions.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';
                    }
            }
        }
        }
    });
}
*/

// wavesurfer 초기화 함수
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);
      updateByteCounter(inputElement);
        
      if (wavesurfer) {
        wavesurfer.destroy();
        wavesurfer = null;
      }
    }

//인풋박스 초기화
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 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')}`;
}

// 체크박스 이벤트 리스너 추가
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;
        // 체크 해제시 모든 input-box 스타일 초기화
        const inputBoxes = document.querySelectorAll('.input_box');
        inputBoxes.forEach(inputBox => updateByteCounter(inputBox));
});

// 모든 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';
                }
            }
        }
    });
}

// timeLimit input에 이벤트 리스너 추가
document.getElementById('timeLimit').addEventListener('input', function() {
    if (document.getElementById('timeLimitCheck').checked) {
        const timeLimit = parseFloat(this.value);
        updateAllSpeakerBoxStyles(timeLimit);
    }
});


// 시간 표시를 업데이트하는 함수는 전역 스코프에 유지
function updateTimeDisplay(time) {
    if (!time && time !== 0) {
        time = wavesurfer ? wavesurfer.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 (regions && regions.regions.length > 0) {
        const prevRegion = regions.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';
        }
    }
}

// 불러오기 버튼 클릭 시 함수
document.getElementById('loadButton').addEventListener('click', async function() {

    // 저장하지 않았다면 경고 메시지 출력
    if (!isContentSaved) {
        const confirmChange = confirm('저장하지 않으셨습니다. 그래도 파일을 선택하시겠습니까?');
        if (!confirmChange) {
            return;
        }
    }

    // 현재 선택된 비디오/오디오 파일명 확인
    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;
            }
        }
        
        if (file) {
            const loadingOverlay = document.getElementById('loadingOverlay');
            const loadingText = loadingOverlay.querySelector('.loading-text');
            const loadingProgress = loadingOverlay.querySelector('.loading-progress');

            loadingOverlay.style.display = 'flex';
            loadingText.textContent = '구역 생성 중...';
            const reader = new FileReader();
            reader.onload = async function(e) {  // async 추가
                const contents = e.target.result;

                // input_box_area 비우기 전에 기존 regions 제거
                if (regions) {
                    regions.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가 있는 줄들 처리
                for (let i = 0; i < timeMatchLines.length; i++) {
                    const item = timeMatchLines[i];
                    const progress = Math.round((i / timeMatchLines.length) * 100);
                    loadingProgress.textContent = `${progress}%`;
                    const startTime = parseFloat(item.timeMatch[1]);
                    const text = item.timeMatch[2].trim();
                    const isLastTimeMatch = i === 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[i + 1].timeMatch;
                        const endTime = parseFloat(nextTimeMatch[1]);

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

                        // region 생성
                        const region = regions.addRegion({
                            id: nanSu,
                            start: parseFloat(startTime) || 0,
                            end: endTime,
                            content: text || ' ',
                            color: randomColor(),
                            resize: true,
                            drag: false
                        }, true);
                        // region 포커스
                        // 구간 시간 계산 (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;
                    }
                };
                // 작업 완료 후 로딩 화면 숨김
                loadingProgress.textContent = '100%';
                await new Promise(resolve => setTimeout(resolve, 500));
                loadingOverlay.style.display = 'none';
            };
            reader.readAsText(file);
        } 
        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());
    // 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;
}

// input box 내용 변경 시 저장 상태 업데이트
document.addEventListener('input', function(e) {
    if (e.target.classList.contains('input_box')) {
        isContentSaved = false; // 내용 변경 시 false로 설정
    }
});

// 저장하기 버튼 클릭 시 함수
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; // 첫 번째 빈 박스 저장
            }
        });

        const speakerBoxes = document.querySelectorAll('.speaker_box');
        const timeLimit = parseFloat(document.getElementById('timeLimit').value);
        let firstlimitBox = null;
        if (document.getElementById('timeLimitCheck').checked) {
            const speakerBoxesArray = Array.from(speakerBoxes);
            speakerBoxesArray.some(box => {
                const value = parseInt(box.value);
                if (value > timeLimit) {
                    // 해당 speaker_box와 매칭되는 input_box 찾기   
                    const matchingInputBox = document.querySelector(`[data-matching="${box.getAttribute('speaker-matching')}"]`);
                    if (matchingInputBox) {
                        firstlimitBox = matchingInputBox; // 첫 번째 초과 구간 저장
                        return true; // 첫 번째 초과 구간을 찾으면 루프 종료
                    }
                }
                return false; // 계속 검색
            });
        }

        if (firstlimitBox) {
            alert('⚠️ 구간 제한을 초과한 구간이 존재합니다!');
            const confirmSave = confirm('그래도 저장하시겠습니까?');
            if (!confirmSave) {
                firstlimitBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
                firstlimitBox.focus();
                return;
            }
            
        }
        if (firstEmptyBox) {
            alert('⚠️ 내용이 없는 구간이 있습니다!');
            const confirmSave = confirm('그래도 저장하시겠습니까?');
            if (!confirmSave) {
                firstEmptyBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
                firstEmptyBox.focus();
                return;
            }
            
        }

        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 = wavesurfer.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(wavesurfer.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로 설정
});

// 주어진 초를 포맷하는 함수
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('파일 저장 중 오류가 발생했습니다.');
    }
}

// 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')}`;
}

// 상용구 모달 열기
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();
    }
}
    

    // 초기화 버튼 클릭 이벤트
document.getElementById('boilerplateResetBtn').addEventListener('click', function() {
    const confirmReset = confirm('상용구 목록을 모두 초기화하시겠습니까?');
    if (confirmReset) {
        boilerplateList.innerHTML = ''; // 목록 초기화
        saveBoilerplatesToLocalStorage(); // localStorage도 초기화
    }
});

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);
                        const newText = textBeforeWord + value.trim() + textAfterCursor;
                        inputBox.value = newText;
                        
                        // 커서 위치 조정
                        const newCursorPosition = textBeforeWord.length + value.trim().length;
                        inputBox.setSelectionRange(newCursorPosition, newCursorPosition);

                        // region content 업데이트
                        const matchingId = inputBox.getAttribute('data-matching');
                        if (matchingId !== 'null') {
                            const matchingRegion = regions.regions.find(r => r.id.toString() === matchingId);
                            if (matchingRegion) {
                                const regionContentElement = matchingRegion.element.querySelector('[part="region-content"]');
                                if (regionContentElement) {
                                    regionContentElement.textContent = newText;
                                }
                            }
                        }
                        updateByteCounter(inputBox);
                        return;
                    }
                }
                // 일치하는 상용구가 없을 경우 알림
                alert('일치하는 상용구가 없습니다.');
            }
        }
    }
});

// 단축키 버튼 이벤트 리스너 추가
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));
    }

    // 구간 제한 체크 안 돼 있으면 구간 제한 입력 필드 비활성화 
    timeLimitInput.disabled = !timeLimitCheckbox.checked;

    // 길이 제한 체크 안 돼 있으면 길이 제한 입력 필드 비활성화 
    byteLimitInput.disabled = !byteLimitCheckbox.checked;
});

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();
        }
    });
});

// 페이지 로드 시 로그인 상태 확인
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';
            }
        });
}

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);
}

// 캔버스가 준비될 때까지 대기
function waitForCanvases() {
    // 로딩 오버레이 표시
    const loadingOverlay = document.getElementById('loadingOverlay');
    loadingOverlay.style.display = 'flex';
    
    let dots = '';
    const updateLoadingText = () => {
        dots = dots.length >= 3 ? '' : dots + '.';
        document.querySelector('.loading-text').textContent = `파형 분석 중${dots}`;
    };
    
    const loadingInterval = setInterval(updateLoadingText, 500);

    return new Promise((resolve) => {
        const checkCanvases = () => {
            const waveformElement = document.querySelector('#waveform').firstElementChild;
            if (waveformElement && waveformElement.shadowRoot) {
                const canvas = waveformElement.shadowRoot.querySelector('canvas[width]');
                if (canvas && canvas.width > 0) {
                    // 로딩 완료 시 오버레이 숨김
                    clearInterval(loadingInterval);
                    loadingOverlay.style.display = 'none';
                    resolve(canvas);
                } else {
                    requestAnimationFrame(checkCanvases);
                }
            } else {
                requestAnimationFrame(checkCanvases);
            }
        };
        checkCanvases();
    });
}

// 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 '';
    });
  </script>
</body>
</html>