package io

import prolog.ast.Database.Program
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStream
import java.io.OutputStream

/**
 * Handles input and output from a terminal.
 */
class Terminal(
    inputStream: InputStream = System.`in`,
    outputStream: OutputStream = System.`out`,
    errorStream: OutputStream = System.err
) : IoHandler {
    val input: BufferedReader = inputStream.bufferedReader()
    val output: BufferedWriter = outputStream.bufferedWriter()
    val error: BufferedWriter = errorStream.bufferedWriter()

    override fun prompt(
        message: String,
        hint: () -> String,
        check: (String) -> Boolean,
    ): String {
        say("$message ")
        var input: String = readLine().trim()
        while (!check(input)) {
            say(hint(), error)
            input += readLine().trim()
        }
        return input.trim()
    }

    override fun say(message: String) {
        output.write(message)
        output.flush()
    }

    fun say(message: String, writer: BufferedWriter = output) {
        writer.write(message)
        writer.flush()
    }

    /**
     * Reads a line from the input stream.
     */
    fun readLine(reader: BufferedReader = input): String {
        val line = reader.readLine()
        if (line == null) {
            Logger.info("End of stream reached")
            cleanup()
        }
        return line

    }

    fun cleanup() {
        Logger.info("Closing terminal streams")
        input.close()
        output.close()
        error.close()
        System.exit(0)
    }

    fun checkNewLine() {
        if (Program.storeNewLine) {
            say("\n")
            Program.storeNewLine = false
        }
    }
}
