#ifndef CORE_TERMINAL_H
#define CORE_TERMINAL_H

#include "core/Vector.h"

#define ESC "\33["
#define TERMINAL_RESET ESC "0m"
#define TERMINAL_BOLD ESC "1m"

#define TERMINAL_BLACK ESC "30m"
#define TERMINAL_RED ESC "31m"
#define TERMINAL_GREEN ESC "32m"
#define TERMINAL_YELLOW ESC "33m"
#define TERMINAL_BLUE ESC "34m"
#define TERMINAL_MAGENTA ESC "35m"
#define TERMINAL_CYAN ESC "36m"
#define TERMINAL_WHITE ESC "37m"
#define TERMINAL_BRIGHT_BLACK ESC "90m"
#define TERMINAL_BRIGHT_RED ESC "91m"
#define TERMINAL_BRIGHT_GREEN ESC "92m"
#define TERMINAL_BRIGHT_YELLOW ESC "93m"
#define TERMINAL_BRIGHT_BLUE ESC "94m"
#define TERMINAL_BRIGHT_MAGENTA ESC "95m"
#define TERMINAL_BRIGHT_CYAN ESC "96m"
#define TERMINAL_BRIGHT_WHITE ESC "97m"

#define TERMINAL_FG_BLACK TERMINAL_BLACK
#define TERMINAL_FG_RED TERMINAL_RED
#define TERMINAL_FG_GREEN TERMINAL_GREEN
#define TERMINAL_FG_YELLOW TERMINAL_YELLOW
#define TERMINAL_FG_BLUE TERMINAL_BLUE
#define TERMINAL_FG_MAGENTA TERMINAL_MAGENTA
#define TERMINAL_FG_CYAN TERMINAL_CYAN
#define TERMINAL_FG_WHITE TERMINAL_WHITE
#define TERMINAL_FG_BRIGHT_BLACK TERMINAL_BRIGHT_BLACK
#define TERMINAL_FG_BRIGHT_RED TERMINAL_BRIGHT_RED
#define TERMINAL_FG_BRIGHT_GREEN TERMINAL_BRIGHT_GREEN
#define TERMINAL_FG_BRIGHT_YELLOW TERMINAL_BRIGHT_YELLOW
#define TERMINAL_FG_BRIGHT_BLUE TERMINAL_BRIGHT_BLUE
#define TERMINAL_FG_BRIGHT_MAGENTA TERMINAL_BRIGHT_MAGENTA
#define TERMINAL_FG_BRIGHT_CYAN TERMINAL_BRIGHT_CYAN
#define TERMINAL_FG_BRIGHT_WHITE TERMINAL_BRIGHT_WHITE

#define TERMINAL_BG_BLACK ESC "40m"
#define TERMINAL_BG_RED ESC "41m"
#define TERMINAL_BG_GREEN ESC "42m"
#define TERMINAL_BG_YELLOW ESC "43m"
#define TERMINAL_BG_BLUE ESC "44m"
#define TERMINAL_BG_MAGENTA ESC "45m"
#define TERMINAL_BG_CYAN ESC "46m"
#define TERMINAL_BG_WHITE ESC "47m"
#define TERMINAL_BG_BRIGHT_BLACK ESC "100m"
#define TERMINAL_BG_BRIGHT_RED ESC "101m"
#define TERMINAL_BG_BRIGHT_GREEN ESC "102m"
#define TERMINAL_BG_BRIGHT_YELLOW ESC "103m"
#define TERMINAL_BG_BRIGHT_BLUE ESC "104m"
#define TERMINAL_BG_BRIGHT_MAGENTA ESC "105m"
#define TERMINAL_BG_BRIGHT_CYAN ESC "106m"
#define TERMINAL_BG_BRIGHT_WHITE ESC "107m"
// keycodes
#define TERMINAL_KEY_UNKNOWN 0x1'0000'0000lu
// default keycodes
#define TERMINAL_KEY_ARROW_LEFT 0x1'0000'0001lu
#define TERMINAL_KEY_ARROW_RIGHT 0x1'0000'0002lu
#define TERMINAL_KEY_ARROW_UP 0x1'0000'0003lu
#define TERMINAL_KEY_ARROW_DOWN 0x1'0000'0004lu
#define TERMINAL_KEY_DELETE 0x1'0000'0005lu
#define TERMINAL_KEY_F1 0x1'0000'0006lu
#define TERMINAL_KEY_F2 0x1'0000'0007lu
#define TERMINAL_KEY_F3 0x1'0000'0008lu
#define TERMINAL_KEY_F4 0x1'0000'0009lu
#define TERMINAL_KEY_F5 0x1'0000'000Alu
#define TERMINAL_KEY_F6 0x1'0000'000Blu
#define TERMINAL_KEY_F7 0x1'0000'000Clu
#define TERMINAL_KEY_F8 0x1'0000'000Dlu
#define TERMINAL_KEY_F9 0x1'0000'000Elu
#define TERMINAL_KEY_F10 0x1'0000'000Flu
#define TERMINAL_KEY_F11 0x1'0000'0010lu
#define TERMINAL_KEY_F12 0x1'0000'0011lu
#define TERMINAL_KEY_PAGE_UP 0x1'0000'0012lu
#define TERMINAL_KEY_PAGE_DOWN 0x1'0000'0013lu
#define TERMINAL_KEY_HOME 0x1'0000'0014lu
#define TERMINAL_KEY_END 0x1'0000'0015lu
// key modifiers
#define TERMINAL_KEY_CTRL 0x2'0000'0000lu
#define TERMINAL_KEY_SHIFT 0x4'0000'0000lu
#define TERMINAL_KEY_ALT 0x8'0000'0000lu

void enterAlternativeTerminal();
void leaveAlternativeTerminal();
IntVector2 getTerminalSize();
void clearTerminal();
void clearTerminalLine();

void hideCursor();
void showCursor();
void resetCursor();
void moveCursorLeft(int i);
void moveCursorRight(int i);
void moveCursorUp(int i);
void moveCursorDown(int i);

bool enterRawTerminal();
bool leaveRawTerminal();
u64 getRawChar();
bool isSpecialChar(u64 u);

typedef struct {
    u64 key;
    bool control;
    bool shift;
    bool alt;
} SpecialChar;

SpecialChar convertToSpecialChar(u64 u);

#endif