var comal_div = document.getElementById("comal_terminal")

const kterm_width = 132
const kterm_height = 32

var comal_buffer = []
var comal_x = 0
var comal_y = 0

for (var r = 0; r < kterm_height; r++) {
    var row = document.createElement("div")
    var span = document.createElement("span")

    row.style.backgroundColor = "black"
    row.style.width = 1000

    span.style.color = "white"
    span.style.fontFamily = "monospace"
    span.style.fontSize = "15px"
    span.textContent = ""
    span.style.whiteSpace = "pre"

    row.appendChild(span)
    comal_div.appendChild(row)

    comal_buffer.push([])
}

function term_refresh() {
    for (var r = 0; r < kterm_height; r++) {
        var s = ""

        for (var c = 0; c < kterm_width; c++) {
            if (c >= comal_buffer[r].length) {
                break
            }

            const k = comal_buffer[r][c]
            s += k === undefined ? " " : k
        }

        if (s.length === 0) {
            comal_div.children[r].children[0].innerHTML = "&nbsp;"
        } else {
            comal_div.children[r].children[0].textContent = s
        }
    }
}

function term_scroll() {
    for (var r = 1; r < kterm_height; r++) {
        comal_buffer[r - 1] = comal_buffer[r]
    }

    comal_buffer[kterm_height - 1] = []
    comal_y = kterm_height - 1
}

function term_page() {
    for (var r = 0; r < kterm_height; r++) {
        comal_buffer[r] = []
    }

    comal_y = 0
    comal_x = 0

    term_refresh()
}

function term_print(s) {
    for (const c of s) {
        if (comal_y === kterm_height) {
            term_scroll()
        }

        if (c === '\n') {
            comal_x = 0
            comal_y++
            continue
        }

        comal_buffer[comal_y][comal_x] = c
        comal_x++

        if (comal_x === kterm_width) {
            comal_y++
            comal_x = 0
        }
    }

    term_refresh()
}

var comal_escape = document.getElementById("comal_escape")
var comal_escaped = false

comal_escape.addEventListener("click", (ev) => {
    comal_escaped = true
    comal_escape.disabled = true
})

function term_escape() {
    var ret = comal_escaped
    comal_escaped = false
    comal_escape.disabled = false
    return ret
}

function term_cursor(x, y) {
    comal_x = x - 1
    comal_y = y - 1

    if (comal_x < 0) comal_x = 0
    if (comal_y < 0) comal_y = 0
    if (comal_x >= kterm_width) comal_x = kterm_width - 1
    if (comal_y >= kterm_width) comal_y = kterm_height - 1
}

var comal_kb = document.getElementById("comal_kb")
var comal_prompt = document.getElementById("comal_prompt")

async function term_read(line, prompt) {
    term_print(prompt)

    const promise = new Promise(function (resolve, reject) {
        function handleChange(event) {
            comal_kb.removeEventListener("change", handleChange)
            comal_escape.removeEventListener("change", handleChange)
            const s = comal_kb.value
            comal_kb.value = ""
            comal_kb.disabled = true
            comal_prompt.innerText = ""
            resolve(s)
        }

        comal_kb.disabled = false
        comal_kb.focus()
        comal_kb.value = line
        comal_prompt.innerText = prompt
        comal_kb.addEventListener("change", handleChange)
        comal_escape.addEventListener("click", handleChange)
    })

    const s = await promise;

    if (term_escape()) {
        return ""
    }

    term_print(s)
    term_print("\n")

    return s
}

var comal_inkey = document.getElementById("comal_inkey")

async function term_inkey(delay) {
    const s = comal_inkey.value

    if (s || delay === 0) {
        comal_inkey.value = ""
        return s
    }

    const promise = new Promise(function (resolve, reject) {
        function handleInput(event) {
            comal_inkey.removeEventListener("input", handleInput)
            const s = comal_inkey.value

            if (s) {
                comal_inkey.value = ""
            }

            resolve(s)
        }

        comal_inkey.addEventListener("input", handleInput)
        comal_inkey.focus()

        if (delay > 0) {
            setTimeout(handleInput, delay * 1000)
        }
    })

    return await promise
}
