#!/usr/bin/env raku

use Termbox;

#static int curCol = 0;
#static int curRune = 0;
#static struct tb_cell *backbuf;
#static int bbw = 0, bbh = 0;

#static const uint32_t runes[] = {
#    0x20, // ' '
#    0x2591, // '░'
#    0x2592, // '▒'
#    0x2593, // '▓'
#    0x2588, // '█'
#};

##define len(a) (sizeof(a)/sizeof(a[0]))

#static const uint16_t colors[] = {
#    TB_BLACK,
#    TB_RED,
#    TB_GREEN,
#    TB_YELLOW,
#    TB_BLUE,
#    TB_MAGENTA,
#    TB_CYAN,
#    TB_WHITE,
#};

#void updateAndDrawButtons(int *current, int x, int y, int mx, int my, int n, void (*attrFunc)(int, uint32_t*, uint16_t*, uint16_t*)) {
#    int lx = x;
#    int ly = y;
#    for (int i = 0; i < n; i++) {
#        if (lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1) {
#            *current = i;
#        }
#        uint32_t r;
#        uint16_t fg, bg;
#        (*attrFunc)(i, &r, &fg, &bg);
#                tb_change_cell(lx+0, ly+0, r, fg, bg);
#                tb_change_cell(lx+1, ly+0, r, fg, bg);
#                tb_change_cell(lx+2, ly+0, r, fg, bg);
#                tb_change_cell(lx+3, ly+0, r, fg, bg);
#                tb_change_cell(lx+0, ly+1, r, fg, bg);
#                tb_change_cell(lx+1, ly+1, r, fg, bg);
#                tb_change_cell(lx+2, ly+1, r, fg, bg);
#                tb_change_cell(lx+3, ly+1, r, fg, bg);
#                lx += 4;
#    }
#    lx = x;
#    ly = y;
#        for (int i = 0; i < n; i++) {
#                if (*current == i) {
#                        uint16_t fg = TB_RED | TB_BOLD;
#                        uint16_t bg = TB_DEFAULT;
#                        tb_change_cell(lx+0, ly+2, '^', fg, bg);
#                        tb_change_cell(lx+1, ly+2, '^', fg, bg);
#                        tb_change_cell(lx+2, ly+2, '^', fg, bg);
#                        tb_change_cell(lx+3, ly+2, '^', fg, bg);
#                }
#                lx += 4;
#        }
#}

#void runeAttrFunc(int i, uint32_t *r, uint16_t *fg, uint16_t *bg) {
#    *r = runes[i];
#    *fg = TB_DEFAULT;
#    *bg = TB_DEFAULT;
#}

#void colorAttrFunc(int i, uint32_t *r, uint16_t *fg, uint16_t *bg) {
#    *r = ' ';
#    *fg = TB_DEFAULT;
#    *bg = colors[i];
#}

sub update-and-redraw-all ( Termbox::cell @buffer, Int $x, Int $y ) {
    tb_clear();

#    if (mx != -1 && my != -1) {
#        backbuf[bbw*my+mx].ch = runes[curRune];
#        backbuf[bbw*my+mx].fg = colors[curCol];
#    }
#    memcpy(tb_cell_buffer(), backbuf, sizeof(struct tb_cell)*bbw*bbh);
#    int h = tb_height();
#    updateAndDrawButtons(&curRune, 0, 0, mx, my, len(runes), runeAttrFunc);
#    updateAndDrawButtons(&curCol, 0, h-3, mx, my, len(colors), colorAttrFunc);

    tb_present();
}

sub realloc-back-buffer ( Int $w, Int $h --> List ) {
    do for ^( $w * $h ) { Termbox::cell.new }
}

sub MAIN () {
    use Termbox :mode, :event, :key;

    if my $ret = tb_init() {
        note "tb_init() failed with error code $ret";
        return -1;
    }

    LEAVE { tb_shutdown() }

    tb_select_input_mode( TB_INPUT_ESC +| TB_INPUT_MOUSE );

    my @buffer = realloc-back-buffer( tb_width(), tb_height() );
    # update-and-redraw-all(-1, -1);

    my $events = Supplier.new;
    start {
        while tb_poll_event( my $ev = Termbox::event.new ) {
            $events.emit: $ev;
        }
    }

    react whenever $events.Supply -> $ev {
        given $ev.type {
            my ( $x, $y ) = ( -1, -1 );

            when -1 {
                note 'termbox poll event error';
                done;
            }
            when TB_EVENT_KEY {
                given $ev.key {
                    when TB_KEY_ESC { done }
                }
            }
            when TB_EVENT_RESIZE {
                @buffer = realloc-back-buffer( $ev.w, $ev.y );
            }
            when TB_EVENT_MOUSE {
                given $ev.key {
                    when TB_KEY_MOUSE_LEFT {
                        ( $x, $y ) = ( $ev.x, $ev.y );
                    }
                }
            }
        }

        # update-and-redraw-all( $x, $y );
    }
}
