#include <unistd.h>

#include "core_runtime_private.h"

enum {
    SYS_STDOUT_FILE_DESCRIPTOR = 1,
    SYS_TERMINAL_SINGLE_BYTE = 1,
    SYS_TERMINAL_SUPPRESSION_INACTIVE = 0,
    SYS_TERMINAL_EMPTY_CURSOR = 0,
    SYS_READ_ERROR = -1,
    SYS_TERMINAL_ERASE_BACKSPACE = '\b',
    SYS_TERMINAL_ERASE_SPACE = ' '
};

void Sys_TTYDrainInput(void)
{
    char input;
    ssize_t readCount;

    /* ORIGINAL_BINARY_BUG: 0x080c83e6..0x080c8404 stops only for -1.
     * A zero-byte EOF therefore spins forever.  Preserved; see
     * original-bugs/engine-tty-eof-handling.md. */
    do {
        readCount = read(SYS_STDIN_FILE_DESCRIPTOR, &input,
                         SYS_TERMINAL_SINGLE_BYTE);
    } while (readCount != SYS_READ_ERROR);
}

void Sys_TTYErasePreviousChar(void)
{
    char output;

    output = SYS_TERMINAL_ERASE_BACKSPACE;
    write(SYS_STDOUT_FILE_DESCRIPTOR, &output, SYS_TERMINAL_SINGLE_BYTE);
    output = SYS_TERMINAL_ERASE_SPACE;
    write(SYS_STDOUT_FILE_DESCRIPTOR, &output, SYS_TERMINAL_SINGLE_BYTE);
    output = SYS_TERMINAL_ERASE_BACKSPACE;
    write(SYS_STDOUT_FILE_DESCRIPTOR, &output, SYS_TERMINAL_SINGLE_BYTE);
}

void Sys_TTYHideInputLine(void)
{
    int index;

    if (sys_ttyOutputSuppressionDepth != SYS_TERMINAL_SUPPRESSION_INACTIVE) {
        sys_ttyOutputSuppressionDepth++;
        return;
    }

    if (sys_ttyCurrentLine.cursor > SYS_TERMINAL_EMPTY_CURSOR) {
        for (index = 0; index < sys_ttyCurrentLine.cursor; index++) {
            Sys_TTYErasePreviousChar();
        }
    }

    sys_ttyOutputSuppressionDepth++;
}

void Sys_TTYShowInputLine(void)
{
    int index;

    sys_ttyOutputSuppressionDepth--;
    if (sys_ttyOutputSuppressionDepth == SYS_TERMINAL_SUPPRESSION_INACTIVE &&
        sys_ttyCurrentLine.cursor != SYS_TERMINAL_EMPTY_CURSOR) {
        for (index = 0; index < sys_ttyCurrentLine.cursor; index++) {
            write(SYS_STDOUT_FILE_DESCRIPTOR, &sys_ttyCurrentLine.text[index],
                  SYS_TERMINAL_SINGLE_BYTE);
        }
    }
}
