#include <shade/tty.h>
#include <shade/cansid.h>

// Initialize a new tty_t object with the specified driver
tty_t tty_new(tty_driver_t driver) {
    tty_t tty;
    tty.active = false;
    tty.cansid = cansid_init();
    tty.cols = driver.max_cols;
    tty.cursor_col = 0;
    tty.cursor_row = 0;
    tty.driver = driver;
    tty.rows = driver.max_rows;
    return tty;
}

void tty_switch(int index);

// private function: print the contents of a tty's output buffer to the screen
void _tty_flip(int tty, bool clear) {
    // clear the screen if required (used in tty_switch)
    if (clear) tty_clr(tty);
    // iterate over every (known) character in the tty output buffer
    for (int x = 0; x < ttys[tty].cols; x++) {
        for (int y = 0; y < ttys[tty].rows; y++) {
            // get the tty_ochar_t
            tty_ochar_t cr = ttys[tty].output_buffer[x + ttys[tty].cols + y];
            // and print it with the driver
            ttys[tty].driver.putchar(cr.character, x, y, cr.style);
        }
    }
    // and update the real cursor position
    ttys[tty].driver.setcurxy(ttys[tty].cursor_col, ttys[tty].cursor_row);
}

// tty_pchar family
void tty_pchar(int tty, char c) {
    if (c == 0) {
        return;
    }

    if (c == '\n') {
        tty_pnl(tty);
        return;
    }

    if (ttys[tty].cursor_col > ttys[tty].cols) {
        tty_pnl(tty);
    }
    
    color_char ccr = cansid_process(&ttys[tty].cansid, c);

    tty_ochar_t cr;
    cr.character = ccr.ascii;
    cr.style = ccr.style;
    ttys[tty].output_buffer[ttys[tty].cursor_col + ttys[tty].cols * ttys[tty].cursor_row] = cr;

    ttys[tty].cursor_col++;
    tty_setcurxy(tty, ttys[tty].cursor_col, ttys[tty].cursor_row);

    // if tty is selected, flip
    if (tty == active_tty) _tty_flip(tty, false);
}

void tty_mvpchar(int tty, char c, int x, int y) {
    tty_setcurxy(tty, x, y);
    tty_pchar(tty, c);
}

// tty_pnl family
void tty_pnl(int tty) {
    return;
}
void tty_mvpnl(int tty, int x, int y) {
    return;
}

// tty_clr family
void tty_clr(int tty) {
    return;
}
void tty_clrl(int tty, int line) {
    return;
}

void tty_setcurxy(int tty, int x, int y) {
    ttys[tty].cursor_col = x;
    ttys[tty].cursor_row = y;
    ttys[tty].driver.setcurxy(x, y);
}