//var stmd = require('stmd');


const messagesContainer = document.getElementById('messages');
const systemInput = document.getElementById('systemMessage');
const messageInput = document.getElementById('messageInput');
var parser = new stmd.DocParser();
var renderer = new stmd.HtmlRenderer();
var cur_idx = 0;
const questions = [];
const answers = [];
var selected_msg = [];

messageInput.addEventListener('keydown', (event) => {
    if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
        sendMessage();
    } else if (event.key === "Escape" && (event.metaKey || event.ctrlKey)) {
        sendAbort();
    }
});

function messageListener(elem, idx, type) {
    return () => {
        elem.classList.toggle('selected');
        const e = { id: idx, type: type };
        const i = selected_msg.indexOf(e);
        if (i === -1)
            selected_msg.push(e);
        else selected_msg.splice(i, 1);
    }
}

async function sendAbort() {
    fetch('/rkllm_abort', {
        method: 'POST',
        body: true
    }).catch(error => alert(error))
}

function _try_highlightAll() {
    try {
        hljs.highlightAll();
    } catch { /*e*/ }
}

async function sendMessage() {
    const messageText = messageInput.value.trim();
    if (!messageText) return;
    messageHTML = renderer.render(parser.parse(`**You:**\n\n${messageText}`))
    mess = document.createElement('div');
    mess.classList.add('message', 'clearfix');
    mess.style.float = "right"
    mess.innerHTML = messageHTML
    mess.addEventListener('click', messageListener(mess, cur_idx, 'q'));
    questions.push(messageText);
    messagesContainer.appendChild(mess);
    Array.from(mess.getElementsByTagName('code')).forEach(e => hljs.highlightElement(e));
    messageInput.value = '';
    messagesContainer.scrollTop = messagesContainer.scrollHeight; // Auto-scroll to bottom

    const messagesToSend = selected_msg.sort((a,b) => {
        const sub = a.id-b.id;
        if (sub === 0) return b.type === 'q' ? 1 : -1;
        return sub;
    }).map(m => {
        const q = m.type === 'q';
        return {
            role: q ? 'user' : 'assistant',
            content: (q ? questions : answers)[m.id]
    }});
    messagesToSend.push({role:'user', content: messageText})
    const sysText = systemInput.value.trim();

    const withSysMsg = (sysText ? [{role: 'system', 'content': sysText}] : []).concat(messagesToSend);

    const response = await fetch('/rkllm_chat', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            model: "some model",
            messages: withSysMsg,
            stream: true
        }),
    });
    if (!response.ok) {
        throw new Error('Failed to connect to chat server');
    }

    const reader = response.body.getReader();
    let decoder = new TextDecoder('utf-8');
    //const name = (Math.random() + 1).toString(36).substring(7);
    const message = document.createElement('div');
    message.classList.add('message', 'clearfix');
    message.style.float = 'left';
    messagesContainer.appendChild(message);
    let chunks = '';
    function double_try() {
        function display(n) {
            const ccs = chunks.split(/\n/).filter(e => e !== "");
            const json = JSON.parse(ccs[ccs.length - n]);
            const text = `${json.choices.map((c) => c.delta.content).join('')}`;
            while (cur_idx >= answers.length) answers.push("");
            answers[cur_idx] = text;
            message.innerHTML = renderer.render(parser.parse(`**RKLLM**:\n\n${text}`));
            Array.from(message.getElementsByTagName('code')).forEach(e => hljs.highlightElement(e));
        }
        const at_bottom = Math.abs(messagesContainer.scrollHeight - messagesContainer.clientHeight - messagesContainer.scrollTop) <= 1;;
        console.log(messagesContainer.scrollHeight, messagesContainer.scrollTop, messagesContainer.clientHeight);
        try {
            display(1);
        } catch {
            try {
                display(2);
            } catch (e) { console.error(e, chunks); }
        } finally {
            if (at_bottom) messagesContainer.scrollTop = messagesContainer.scrollHeight;
        }
    }
    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        const chunk = decoder.decode(value, { stream: true });
        chunks += chunk.replace('\r', '');
        double_try();
    }
    double_try();

    message.addEventListener('click', messageListener(message, cur_idx++, 'a'));

}
