#include <stdio.h>

#include "../Tests.h"
#include "core/Logger.h"
#include "core/Terminal.h"
#include "core/Utility.h"

#define KEY_CASE(key)           \
    case key: puts(#key); break

void testTerminal(bool tty) {
    IntVector2 size = getTerminalSize();
    if(tty) {
        TEST_TRUE(size.x > 0);
        TEST_TRUE(size.y > 0);
        TEST_FALSE(enterRawTerminal());
        TEST_FALSE(leaveRawTerminal());
    } else {
        TEST_INT(0, size.x);
        TEST_INT(0, size.y);
    }

    enterAlternativeTerminal();
    clearTerminal();
    resetCursor();
    LOG_ERROR("Not visible!");
    leaveAlternativeTerminal();

    LOG_ERROR("Not visible!");
    moveCursorUp(2);
    moveCursorDown(1);
    moveCursorLeft(3);
    moveCursorRight(3);
    clearTerminalLine();

    hideCursor();
    showCursor();

    u64 u = TERMINAL_KEY_F5 | TERMINAL_KEY_SHIFT;
    TEST_TRUE(isSpecialChar(u));
    SpecialChar s = convertToSpecialChar(u);
    TEST_U64(TERMINAL_KEY_F5, s.key);
    TEST_FALSE(s.alt);
    TEST_FALSE(s.control);
    TEST_TRUE(s.shift);
}

void testInteractiveTerminal(void) {
    enterAlternativeTerminal();

    resetCursor();
    hideCursor();
    puts("Hi there");
    LOG_WARNING("This is a test");
    IntVector2 v = getTerminalSize();
    printf("%d %d\n", v.x, v.y);
    clearTerminal();
    resetCursor();
    showCursor();
    puts("the final!!!");
    sleepMillis(500);

    enterRawTerminal();

    while(true) {
        u64 c = getRawChar();
        if(c == 'q') {
            break;
        } else if(c == 0) {
            continue;
        } else if(isSpecialChar(c)) {
            SpecialChar sc = convertToSpecialChar(c);
            if(sc.shift) {
                printf("SHIFT + ");
            }
            if(sc.control) {
                printf("CTRL + ");
            }
            if(sc.alt) {
                printf("ALT + ");
            }
            switch(sc.key) {
                KEY_CASE(TERMINAL_KEY_ARROW_LEFT);
                KEY_CASE(TERMINAL_KEY_ARROW_RIGHT);
                KEY_CASE(TERMINAL_KEY_ARROW_UP);
                KEY_CASE(TERMINAL_KEY_ARROW_DOWN);
                KEY_CASE(TERMINAL_KEY_DELETE);
                KEY_CASE(TERMINAL_KEY_F1);
                KEY_CASE(TERMINAL_KEY_F2);
                KEY_CASE(TERMINAL_KEY_F3);
                KEY_CASE(TERMINAL_KEY_F4);
                KEY_CASE(TERMINAL_KEY_F5);
                KEY_CASE(TERMINAL_KEY_F6);
                KEY_CASE(TERMINAL_KEY_F7);
                KEY_CASE(TERMINAL_KEY_F8);
                KEY_CASE(TERMINAL_KEY_F9);
                KEY_CASE(TERMINAL_KEY_F10);
                KEY_CASE(TERMINAL_KEY_F11);
                KEY_CASE(TERMINAL_KEY_F12);
                KEY_CASE(TERMINAL_KEY_PAGE_UP);
                KEY_CASE(TERMINAL_KEY_PAGE_DOWN);
                KEY_CASE(TERMINAL_KEY_HOME);
                KEY_CASE(TERMINAL_KEY_END);
                default: printf("%lu\n", sc.key); break;
            }
        } else {
            printf("%lu\n", c);
        }
    }

    leaveRawTerminal();

    leaveAlternativeTerminal();
}