{% extends "app.html" %}

{% block header_text %}<h2 style="color:#fff">{{ name }}</h2>{% endblock %} 

{% block main %}
{% include "channel.html" %}
<section class="chat-area">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm/css/xterm.css">
    <script src="https://cdn.jsdelivr.net/npm/xterm/lib/xterm.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit/lib/xterm-addon-fit.js"></script>
    
    <div id="terminal" class="hidden"></div>
        <message-list class="chat-messages">
        {% if not messages %}
        
        <div>
          <h1>Welcome to your new channel!</h1>
          <p>This is the start of something great. Use the commands below to get started:</p>
          <ul>
            <li>Press <code>/invite</code> to invite someone.</li>
            <li>Press <code>/online</code> to see who's currently online.</li>
            <li>Press <code>/help</code> to view all available commands.</li>
          </ul>
          <p>Enjoy chatting!</p>
        </div>
        {% endif %}

        {% for message in messages %}
            {% autoescape false %}
            {{ message.html }}
            {% endautoescape %}
        {% endfor %}

        <div class="message-list-bottom"></div>
    </message-list>
    <chat-input live-type="true" channel="{{ channel.uid.value }}"></chat-input>
</section>
{% include "dialog_container.html" %}
{% include "dialog_help.html" %}
{% include "dialog_online.html" %}
<script type="module">
    import { app } from "/app.js";
import { Schedule } from "/schedule.js";

// --- Cache selectors ---
const chatInputField = document.querySelector("chat-input");
const messagesContainer = document.querySelector(".chat-messages");
const chatArea = document.querySelector(".chat-area");
const channelUid = "{{ channel.uid.value }}";
const username = "{{ user.username.value }}";
let container = null
// --- Command completions ---
chatInputField.autoCompletions = {
    "/online": showOnline,
    "/clear": () => { messagesContainer.innerHTML = ''; },
    "/live": () => { chatInputField.liveType = !chatInputField.liveType; },
    "/help": showHelp,
    "/container": async() =>{ 
        if(container == null){
            window.c = await window.getContainer()
            await window.c.start()
            window.t = document.querySelector("#terminal")
            window.t.classList.toggle("hidden")
            window.c.render(window.t)
        }
        //containerDialog.openWithStatus()
    }
};

// --- Throttle utility ---
function throttle(fn, wait) {
    let last = 0;
    return function(...args) {
        const now = Date.now();
        if (now - last >= wait) {
            last = now;
            fn.apply(this, args);
        }
    };
}

// --- Scroll: load extra messages, throttled ---
let isLoadingExtra = false;
async function loadExtra() {
    const firstMessage = messagesContainer.querySelector(".message:first-child");
    if (isLoadingExtra || !isScrolledPastHalf() || !firstMessage) return;
    isLoadingExtra = true;
    const messages = await app.rpc.getMessages(channelUid, 0, firstMessage.dataset.created_at);
    if (messages.length) {
        const frag = document.createDocumentFragment();
        messages.forEach(msg => {
            const temp = document.createElement("div");
            temp.innerHTML = msg.html;
            frag.appendChild(temp.firstChild);
        });
        firstMessage.parentNode.insertBefore(frag, firstMessage);
        updateLayout(false);
    }
    isLoadingExtra = false;
}
messagesContainer.addEventListener("scroll", throttle(loadExtra, 200));

// --- Only update visible times ---
function updateTimes() {
    const containers = messagesContainer.querySelectorAll(".time");
    const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
    containers.forEach(container => {
        const rect = container.getBoundingClientRect();
        if (rect.top >= 0 && rect.bottom <= viewportHeight) {
            const messageDiv = container.closest('.message');
            const text = messageDiv.querySelector(".text").innerText;
            const time = document.createElement("span");
            time.innerText = app.timeDescription(container.dataset.created_at);
            container.replaceChildren(time);
            const reply = document.createElement("a");
            reply.innerText = " reply";
            reply.href = "#reply";
            container.appendChild(reply);
            reply.addEventListener('click', e => {
                e.preventDefault();
                replyMessage(text);
            });
        }
    });
}
setInterval(() => requestIdleCallback(updateTimes), 30000);

// --- Paste & drag/drop uploads ---
const textBox = chatInputField.textarea;
textBox.addEventListener("paste", async (e) => {
    try {
        const clipboardItems = await navigator.clipboard.read();
        const dt = new DataTransfer();
        for (const item of clipboardItems) {
            for (const type of item.types.filter(t => !t.startsWith('text/'))) {
                const blob = await item.getType(type);
                dt.items.add(new File([blob], "image.png", { type }));
            }
        }
        if (dt.items.length > 0) {
            const uploadButton = chatInputField.uploadButton;
            const input = uploadButton.shadowRoot.querySelector('.file-input');
            input.files = dt.files;
            await uploadButton.uploadFiles();
        }
    } catch (error) {
        console.error("Failed to read clipboard contents: ", error);
    }
});
chatArea.addEventListener("drop", async (e) => {
    e.preventDefault();
    const dt = e.dataTransfer;
    if (dt.items.length > 0) {
        const uploadButton = chatInputField.uploadButton;
        const input = uploadButton.shadowRoot.querySelector('.file-input');
        input.files = dt.files;
        await uploadButton.uploadFiles();
    }
});
chatArea.addEventListener("dragover", e => {
    e.preventDefault();
    e.dataTransfer.dropEffect = "link";
});

// --- Focus input on load ---
chatInputField.textarea.focus();

// --- Reply helper ---
function replyMessage(message) {
    chatInputField.value = "```markdown\n> " + (message || '') + "\n```\n";
    chatInputField.focus();
}

// --- Mention helpers ---
function extractMentions(message) {
    return [...new Set(message.match(/@\w+/g) || [])];
}
function isMentionToMe(message) {
    return message.toLowerCase().includes('@' + username.toLowerCase());
}
function isMentionForSomeoneElse(message) {
    const mentions = extractMentions(message);
    return mentions.length > 0 && !mentions.includes('@' + username);
}

// --- WebSocket events ---
app.ws.addEventListener("refresh", (data) => {
    app.starField.showNotify(data.message);
    setTimeout(() => window.location.reload(), 4000);
});
app.ws.addEventListener("stars_render", (data)=>{
    app.starField.renderWord(data.message, { rainbow: true, resolution: 8 });
    setTimeout(() => app.starField.shuffleAll(5000), 10000);
})
app.ws.addEventListener("deployed", (data) => {
    app.starField.renderWord("Deployed", { rainbow: true, resolution: 8 });
    setTimeout(() => app.starField.shuffleAll(5000), 10000);
});
app.ws.addEventListener("starfield.render_word", (data) => {
    app.starField.renderWord(data.word, data);
});

// --- Channel message event ---
app.addEventListener("channel-message", (data) => {
    
    let display = data.text && data.text.trim() ? 'block' : 'none';

    if (data.channel_uid !== channelUid) {
        if (!isMentionForSomeoneElse(data.message)) {
            channelSidebar.notify(data);
            app.playSound("messageOtherChannel");
        }
        return;
    }
    if (data.username !== username) {
        if (isMentionToMe(data.message)) {
            app.playSound("mention");
        } else if (!isMentionForSomeoneElse(data.message)) {
            if(data.is_final){
                app.playSound("message");
            }
        }
    }
    const lastElement = messagesContainer.querySelector(".message-list-bottom");
    const doScrollDown = messagesContainer.isScrolledToBottom();
    
    const oldMessage = messagesContainer.querySelector(`.message[data-uid="${data.uid}"]`);
    if (oldMessage) {
        oldMessage.remove();
    }

    const message = document.createElement("div");
    

    message.innerHTML = data.html;
    message.style.display = display;
    messagesContainer.insertBefore(message.firstChild, lastElement);
    updateLayout(doScrollDown);
    setTimeout(() => updateLayout(doScrollDown), 1000);
    app.rpc.markAsRead(channelUid);
});

// --- Keyboard shortcuts ---
let escPressed = false, gPressCount = 0, keyTimeout;
document.addEventListener('keydown', function(event) {
    if (event.key === 'Escape') {
        gPressCount = 0;
        document.activeElement.blur();
    }
    if (event.key === 'g' && !chatInputField.isActive()) {
        gPressCount++;
        clearTimeout(keyTimeout);
        keyTimeout = setTimeout(() => { gPressCount = 0; }, 300);
        if (gPressCount === 2) {
            gPressCount = 0; 
            messagesContainer.querySelector(".message:first-child")?.scrollIntoView({ block: "end", inline: "nearest" });
            loadExtra();
        }
    }
    if(event.key == 'i' && !chatInputField.isActive()) {
        event.preventDefault();
        chatInputField.focus();
    }
    if(event.key == 'r' && !chatInputField.isActive()) {
        event.preventDefault();
        const replyLinks = document.querySelectorAll('.time a')
        if(replyLinks.length){
            const replyLink = replyLinks[replyLinks.length - 1]
            replyLink.click()
        }
    }
    if (event.shiftKey && event.key === 'G') {
        if (!chatInputField.isActive()) {
            event.preventDefault();
            updateLayout(true);
            setTimeout(() => chatInputField.focus(), 500);
        }
    }
});

// --- Image click-to-zoom (delegated) ---
// --- Layout update ---
function updateLayout(doScrollDown) {
    updateTimes();
    let previousUser = null, previousDate = null;
    messagesContainer.querySelectorAll(".message").forEach((message) => {
        if (previousUser !== message.dataset.user_uid) {
            message.classList.add("switch-user");
            previousUser = message.dataset.user_uid;
            previousDate = new Date(message.dataset.created_at);
        } else {
            message.classList.remove("switch-user");
            if (!previousDate) {
                previousDate = new Date(message.dataset.created_at);
            } else {
                const currentDate = new Date(message.dataset.created_at);
                if (currentDate.getTime() - previousDate.getTime() > 1000 * 60 * 20) {
                    message.classList.add("long-time");
                } else {
                    message.classList.remove("long-time");
                }
                previousDate = currentDate;
            }
        }
    });
    if (doScrollDown) messagesContainer.scrollToBottom?.();
}

// --- Utility: check if element is visible ---


// --- Utility: check if scrolled past half ---
function isScrolledPastHalf() {
    let scrollTop = messagesContainer.scrollTop;
    let scrollableHeight = messagesContainer.scrollHeight - messagesContainer.clientHeight;
    return scrollTop < scrollableHeight / 2;
}

// --- Initial layout update ---
updateLayout(true);



</script>
{% endblock %}
