<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>モダンチャット</title>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="login-container" class="login-container">
        <div id="login-form">
            <h2>ログイン</h2>
            <input type="text" id="loginId" placeholder="ID">
            <input type="password" id="loginPassword" placeholder="パスワード">
            <button onclick="login()">ログイン</button>
            <button onclick="showCreateAccount()">アカウントを作成</button>
        </div>
        <div id="create-account-form" style="display: none;">
            <h2>アカウント作成</h2>
            <input type="text" id="createId" placeholder="新しいID">
            <input type="password" id="createPassword" placeholder="新しいパスワード">
            <input type="password" id="confirmPassword" placeholder="パスワード（確認）">
            <button onclick="createAccount()">作成</button>
            <button onclick="showLogin()">ログインに戻る</button>
        </div>
    </div>

    <div id="username-container" class="username-container" style="display: none;">
        <input type="text" id="usernameInput" placeholder="ユーザー名を入力...">
        <button onclick="setUsername()">決定</button>
    </div>
    <div class="chat-container" style="display: none;">
        <div class="chat-header">
            <select id="channelSelect" onchange="changeChannel()">
                <option value="general">General</option>
                <option value="random">Random</option>
            </select>
            モダンチャット
        </div>
        <div class="chat-area" id="chatArea"></div>
        <div class="input-area">
            <input type="text" id="messageInput" placeholder="メッセージを入力...">
            <input type="file" id="fileInput" style="display: none;" accept="image/*">
            <button onclick="document.getElementById('fileInput').click()">📎</button>
            <button onclick="sendMessage()">送信</button>
        </div>
    </div>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        const socket = io();
        let username = '';
        let pingStartTime = 0;
        let currentChannel = 'general';
        // メッセージ履歴用の変数を追加
        let messageHistory = [];
        let historyIndex = -1;

        // アカウント管理の関数を追加
        function showCreateAccount() {
            document.getElementById('login-form').style.display = 'none';
            document.getElementById('create-account-form').style.display = 'block';
        }

        function showLogin() {
            document.getElementById('login-form').style.display = 'block';
            document.getElementById('create-account-form').style.display = 'none';
        }

        function createAccount() {
            const id = document.getElementById('createId').value.trim();
            const password = document.getElementById('createPassword').value;
            const confirmPassword = document.getElementById('confirmPassword').value;

            if (!id || !password) {
                alert('IDとパスワードを入力してください');
                return;
            }

            if (password !== confirmPassword) {
                alert('パスワードが一致しません');
                return;
            }

            const users = JSON.parse(localStorage.getItem('chatUsers') || '{}');
            
            if (users[id]) {
                alert('このIDは既に使用されています');
                return;
            }

            users[id] = {
                password: password,
                createdAt: new Date().toISOString()
            };

            localStorage.setItem('chatUsers', JSON.stringify(users));
            alert('アカウントを作成しました');
            showLogin();
        }

        function login() {
            const id = document.getElementById('loginId').value.trim();
            const password = document.getElementById('loginPassword').value;

            const users = JSON.parse(localStorage.getItem('chatUsers') || '{}');
            const user = users[id];

            if (!user || user.password !== password) {
                alert('IDまたはパスワードが間違っています');
                return;
            }

            // ログイン成功
            document.getElementById('login-container').style.display = 'none';
            document.getElementById('username-container').style.display = 'block';
            document.getElementById('usernameInput').value = id;
        }

        // 既存のsetUsername関数を修正
        function setUsername() {
            const usernameInput = document.getElementById('usernameInput');
            username = usernameInput.value.trim();
            if (username) {
                document.getElementById('username-container').style.display = 'none';
                document.querySelector('.chat-container').style.display = 'flex';
                // ユーザー名設定時にサーバーに通知
                socket.emit('set username', username);
            }
        }

        function changeChannel() {
            currentChannel = document.getElementById('channelSelect').value;
            document.getElementById('chatArea').innerHTML = '';
            socket.emit('change channel', currentChannel);
        }

        const messageInput = document.getElementById('messageInput');
        const chatArea = document.getElementById('chatArea');
        const fileInput = document.getElementById('fileInput');

        function sendMessage() {
            const messageText = messageInput.value.trim();
            if (messageText) {
                // メッセージを履歴に追加
                messageHistory.unshift(messageText);
                historyIndex = -1;

                if (messageText === '/ping') {
                    pingStartTime = Date.now();
                    socket.emit('ping');
                    messageInput.value = '';
                } else if (messageText.startsWith('/changeid ')) {
                    const newUsername = messageText.slice(10).trim();
                    if (newUsername) {
                        const oldUsername = username;
                        username = newUsername;
                        socket.emit('change username', { oldUsername, newUsername });
                        // システムメッセージを表示
                        const messageDiv = document.createElement('div');
                        messageDiv.className = 'message system';
                        messageDiv.innerHTML = `
                            <div class="message-bubble">IDを ${oldUsername} から ${newUsername} に変更しました</div>
                        `;
                        chatArea.appendChild(messageDiv);
                        chatArea.scrollTop = chatArea.scrollHeight;
                    }
                    messageInput.value = '';
                } else if (messageText === '/sad') {
                    const msg = {
                        username: username,
                        text: '(´・ω・`)'
                    };
                    socket.emit('chat message', msg);
                    messageInput.value = '';
                } else if (messageText === '/tableflip') {
                    const msg = {
                        username: username,
                        text: '(╯°□°)╯︵ ┻━┻'
                    };
                    socket.emit('chat message', msg);
                    messageInput.value = '';
                } else {
                    const msg = {
                        username: username,
                        text: messageText,
                        channel: currentChannel
                    };
                    socket.emit('chat message', msg);
                    messageInput.value = '';
                }
            }
        }

        // メッセージ入力欄のキーイベントリスナーを修正
        messageInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') {
                sendMessage();
            } else if (e.key === 'ArrowUp') {
                e.preventDefault();
                if (historyIndex < messageHistory.length - 1) {
                    historyIndex++;
                    messageInput.value = messageHistory[historyIndex];
                    // カーソルを末尾に移動
                    setTimeout(() => {
                        messageInput.selectionStart = messageInput.selectionEnd = messageInput.value.length;
                    }, 0);
                }
            } else if (e.key === 'ArrowDown') {
                e.preventDefault();
                if (historyIndex > -1) {
                    historyIndex--;
                    messageInput.value = historyIndex === -1 ? '' : messageHistory[historyIndex];
                    // カーソルを末尾に移動
                    setTimeout(() => {
                        messageInput.selectionStart = messageInput.selectionEnd = messageInput.value.length;
                    }, 0);
                }
            }
        });

        fileInput.addEventListener('change', () => {
            const file = fileInput.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = () => {
                    const msg = {
                        username: username,
                        file: reader.result,
                        fileName: file.name,
                        channel: currentChannel
                    };
                    socket.emit('file upload', msg);
                };
                reader.readAsDataURL(file);
            }
        });

        // Markdownスタイルのテキスト装飾を適用する関数を追加
        function formatMessage(text) {
            // 装飾用の正規表現パターン
            const patterns = [
                [/\*\*\*([^\*]+)\*\*\*/g, '<strong><em>$1</em></strong>'],  // 太字＆斜体
                [/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>'],               // 太字
                [/\*([^\*]+)\*/g, '<em>$1</em>'],                          // 斜体
                [/__([^_]+)__/g, '<u>$1</u>'],                             // 下線
                [/~~([^~]+)~~/g, '<del>$1</del>'],                        // 取り消し線
                [/\|\|([^\|]+)\|\|/g, '<span class="spoiler">$1</span>'],  // ネタバレ防止
                [/`([^`]+)`/g, '<code>$1</code>'],                        // コードブロック
                [/^> (.+)$/gm, '<blockquote>$1</blockquote>']             // 引用
            ];

            // 各パターンを適用
            patterns.forEach(([pattern, replacement]) => {
                text = text.replace(pattern, replacement);
            });

            return text;
        }

        // convertYouTubeLinks関数を修正
        function convertYouTubeLinks(text) {
            // 装飾を適用
            text = formatMessage(text);
            
            // YouTube埋め込み
            const youtubeRegex = /(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/watch\?v=)([a-zA-Z0-9_-]+)/g;
            return text.replace(youtubeRegex, (match, videoId) => {
                return `<iframe 
                    width="100%" 
                    height="250" 
                    src="https://www.youtube.com/embed/${videoId}" 
                    frameborder="0" 
                    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" 
                    allowfullscreen>
                </iframe>`;
            });
        }

        // スタイルを追加
        const style = document.createElement('style');
        style.textContent = `
            .spoiler {
                background-color: #000;
                color: #000;
                padding: 0 4px;
                cursor: pointer;
                user-select: none;
            }
            .spoiler:hover {
                background-color: transparent;
                color: inherit;
            }
            code {
                background-color: #f0f0f0;
                padding: 2px 4px;
                border-radius: 3px;
                font-family: monospace;
            }
            blockquote {
                border-left: 4px solid #ddd;
                margin: 0;
                padding-left: 10px;
                color: #666;
            }
        `;
        document.head.appendChild(style);

        socket.on('chat message', (msg) => {
            if (msg.channel !== currentChannel) return;
            const messageDiv = document.createElement('div');
            messageDiv.className = 'message received';
            const convertedText = convertYouTubeLinks(msg.text);
            messageDiv.innerHTML = `
                <div class="message-avatar" data-username="${msg.username}"><span>${msg.username}</span></div>
                <div class="message-bubble" data-message-id="${Date.now()}">
                    ${convertedText}
                    ${msg.username === username ? `
                        <div class="message-actions">
                            <button onclick="editMessage(this)"><span class="material-icons">edit</span></button>
                            <button onclick="deleteMessage(this)"><span class="material-icons">delete</span></button>
                        </div>
                    ` : ''}
                </div>
            `;
            chatArea.appendChild(messageDiv);
            chatArea.scrollTop = chatArea.scrollHeight;
        });

        // メッセージ削除機能
        function deleteMessage(button) {
            const messageBubble = button.closest('.message-bubble');
            const messageId = messageBubble.dataset.messageId;
            socket.emit('delete message', messageId);
            messageBubble.closest('.message').remove();
        }

        // メッセージ編集機能
        function editMessage(button) {
            const messageBubble = button.closest('.message-bubble');
            const messageId = messageBubble.dataset.messageId;
            const currentText = messageBubble.childNodes[0].textContent;
            
            messageBubble.classList.add('editing');
            messageBubble.innerHTML = `
                <input type="text" class="edit-input" value="${currentText}">
                <div class="message-actions">
                    <button onclick="saveEdit(this)"><span class="material-icons">check</span></button>
                    <button onclick="cancelEdit(this)"><span class="material-icons">close</span></button>
                </div>
            `;
        }

        function saveEdit(button) {
            const messageBubble = button.closest('.message-bubble');
            const messageId = messageBubble.dataset.messageId;
            const newText = messageBubble.querySelector('.edit-input').value;
            
            socket.emit('edit message', {
                messageId: messageId,
                newText: newText
            });
            
            const convertedText = convertYouTubeLinks(newText);
            messageBubble.classList.remove('editing');
            messageBubble.innerHTML = `
                ${convertedText}
                <div class="message-actions">
                    <button onclick="editMessage(this)"><span class="material-icons">edit</span></button>
                    <button onclick="deleteMessage(this)"><span class="material-icons">delete</span></button>
                </div>
            `;
        }

        function cancelEdit(button) {
            const messageBubble = button.closest('.message-bubble');
            const currentText = messageBubble.querySelector('.edit-input').value;
            const convertedText = convertYouTubeLinks(currentText);
            
            messageBubble.classList.remove('editing');
            messageBubble.innerHTML = `
                ${convertedText}
                <div class="message-actions">
                    <button onclick="editMessage(this)"><span class="material-icons">edit</span></button>
                    <button onclick="deleteMessage(this)"><span class="material-icons">delete</span></button>
                </div>
            `;
        }

        socket.on('file upload', (msg) => {
            if (msg.channel !== currentChannel) return;
            const messageDiv = document.createElement('div');
            messageDiv.className = 'message received';
            messageDiv.innerHTML = `
                <div class="message-avatar" data-username="${msg.username}"><span>${msg.username}</span></div>
                <div class="message-bubble">
                    <img src="${msg.file}" alt="${msg.fileName}" style="max-width: 100%;">
                </div>
            `;
            chatArea.appendChild(messageDiv);
            chatArea.scrollTop = chatArea.scrollHeight;
        });

        socket.on('pong', () => {
            const pingTime = Date.now() - pingStartTime;
            const messageDiv = document.createElement('div');
            messageDiv.className = 'message received';
            messageDiv.innerHTML = `
                <div class="message-avatar" data-username="システム"><span>システム</span></div>
                <div class="message-bubble">Ping: ${pingTime}ms</div>
            `;
            chatArea.appendChild(messageDiv);
            chatArea.scrollTop = chatArea.scrollHeight;
        });

        // システムメッセージの受信処理を追加
        socket.on('system message', (msg) => {
            const messageDiv = document.createElement('div');
            messageDiv.className = 'message system';
            messageDiv.innerHTML = `
                <div class="message-bubble">${msg}</div>
            `;
            chatArea.appendChild(messageDiv);
            chatArea.scrollTop = chatArea.scrollHeight;
        });

        document.querySelector('button[onclick="sendMessage()"]').setAttribute('onclick', 'sendMessage()');

        // Add this block to reload the page when the code is updated
        if (module.hot) {
            module.hot.accept(() => {
                window.location.reload();
            });
        }

        // コード更新時のリロード処理を追加
        socket.on('code_updated', () => {
            window.location.reload();
        });

        // メッセージ削除の受信処理を追加
        socket.on('message deleted', (messageId) => {
            const messageToDelete = document.querySelector(`.message-bubble[data-message-id="${messageId}"]`);
            if (messageToDelete) {
                messageToDelete.closest('.message').remove();
            }
        });

        // メッセージ編集の受信処理を追加
        socket.on('message edited', (data) => {
            const messageToEdit = document.querySelector(`.message-bubble[data-message-id="${data.messageId}"]`);
            if (messageToEdit) {
                const convertedText = convertYouTubeLinks(data.newText);
                const isOwnMessage = messageToEdit.querySelector('.message-actions') !== null;
                
                messageToEdit.innerHTML = `
                    ${convertedText}
                    ${isOwnMessage ? `
                        <div class="message-actions">
                            <button onclick="editMessage(this)"><span class="material-icons">edit</span></button>
                            <button onclick="deleteMessage(this)"><span class="material-icons">delete</span></button>
                        </div>
                    ` : ''}
                `;
            }
        });

        let typingTimeout = null;
        let lastTypedText = '';

        messageInput.addEventListener('input', (e) => {
            const text = e.target.value.trim();
            
            // テキストが変更されたら入力中の状態を送信
            if (text !== lastTypedText) {
                socket.emit('typing', {
                    username: username,
                    text: text
                });
                lastTypedText = text;

                // タイピング終了タイマーをリセット
                clearTimeout(typingTimeout);
                typingTimeout = setTimeout(() => {
                    socket.emit('stop typing', username);
                }, 1000);
            }
        });

        socket.on('user typing', (data) => {
            let typingDiv = document.querySelector(`#typing-${data.username}`);
            if (!typingDiv) {
                typingDiv = document.createElement('div');
                typingDiv.id = `typing-${data.username}`;
                typingDiv.className = 'typing-indicator';
                chatArea.appendChild(typingDiv);
            }
            typingDiv.innerHTML = `
                <span>${data.username} が入力中</span>
                <span class="typing-text">${data.text}</span>
            `;
            chatArea.scrollTop = chatArea.scrollHeight;
        });

        socket.on('user stop typing', (username) => {
            const typingDiv = document.querySelector(`#typing-${username}`);
            if (typingDiv) {
                typingDiv.remove();
            }
        });
        // Ctrlキーの状態を監視
        document.addEventListener('keydown', function(e) {
            if (e.ctrlKey) {
                document.querySelectorAll('.message.received').forEach(msg => {
                    msg.classList.add('ctrl-pressed');
                });
            }
        });

        document.addEventListener('keyup', function(e) {
            if (!e.ctrlKey) {
                document.querySelectorAll('.message.received').forEach(msg => {
                    msg.classList.remove('ctrl-pressed');
                });
            }
        });

        // ページがフォーカスを失った時にctrl-pressedクラスを削除
        window.addEventListener('blur', function() {
            document.querySelectorAll('.message.received').forEach(msg => {
                msg.classList.remove('ctrl-pressed');
            });
        });
    </script>
    
    <style>
        .login-container {
            max-width: 400px;
            margin: 50px auto;
            padding: 20px;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }

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

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

        .login-container button {
            width: 100%;
            padding: 10px;
            margin-bottom: 10px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .login-container button:hover {
            background: #45a049;
        }

        .login-container button:last-child {
            background: #2196F3;
        }

        .login-container button:last-child:hover {
            background: #1976D2;
        }

        .spoiler {
            background-color: #000;
            color: #000;
            padding: 2px 8px;
            cursor: pointer;
            user-select: none;
            border-radius: 12px;
            transition: all 0.3s ease;
        }
        .spoiler:hover {
            background-color: transparent;
            color: inherit;
        }
        code {
            background-color: #f0f0f0;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: monospace;
        }
        blockquote {
            border-left: 4px solid #ddd;
            margin: 0;
            padding-left: 10px;
            color: #666;
        }

        .message-actions {
            display: none;
            position: absolute;
            right: 5px;
            top: 5px;
            pointer-events: none; /* クリック判定を無効にする */
        }

        .message-bubble {
            position: relative;
        }

        .message.received:hover .message-actions {
            /* デフォルトでは非表示のまま */
            opacity: 0;
        }

        /* Ctrlキーが押されている時のみ表示 */
        .message.received.ctrl-pressed:hover .message-actions {
            display: block;
            opacity: 1;
            pointer-events: auto; /* クリック判定を有効にする */
        }
    </style>
</body>
</html>
