#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "hl.h"

#define ALLOCATION_CHUNK (10UL)

static char * buffer      = NULL;
static size_t buffer_size = 0;

typedef struct {
	int attribute;
	int foreground_color;
	int background_color;
} terminal_hl_t;

void cterm_render_callback(const char * const string,
                           const int          length,
                           void       * const attributes) {
	if(!length){
		putchar(*string);
		return;
	}

	UNUSED(attributes);
	fputs(TERMINAL_STYLE_BOLD, stdout);
	for (int i = 0; i < length; i++) {
		putchar(*(string+i));
	}
	fputs(TERMINAL_RESET, stdout);
}

int main(int      argc,
         char * * argv) {
	UNUSED(argc);
	UNUSED(argv);

	// Buffer init
	buffer = realloc(buffer, ALLOCATION_CHUNK);

	do {
		if (!((buffer_size + 1) % ALLOCATION_CHUNK)) {
			/* Linear incremental reallocation (advanced)!
			 */
			size_t chunks = (buffer_size + 1) / ALLOCATION_CHUNK;
			buffer = realloc(buffer, ++chunks * ALLOCATION_CHUNK);
		}
		buffer[buffer_size] = '\0';
		read(STDIN_FILENO, &buffer[buffer_size], sizeof (*buffer));
		++buffer_size;
	} while (buffer[buffer_size - 1]);

	buffer[buffer_size - 1] = '\0';

	// Highlight init
	const char * c_keywords[] = {
	  "register",     "volatile",     "auto",         "const",        "static",       "extern",       "if",           "else",
	  "do",           "while",        "for",          "continue",     "switch",       "case",         "default",      "break",
	  "enum",         "union",        "struct",       "typedef",      "goto",         "void",         "return",       "sizeof",
	  "char",         "short",        "int",          "long",         "signed",       "unsigned",     "float",        "double",
	  NULL
	};

	const char * preprocessor_keywords[] = {
	  "#include",     "#pragma",      "#define",      "#undef",       "#ifdef",       "#ifndef",      "#elifdef",     "#elifndef",
	  "#if",          "#elif",        "#else",        "#endif",       "#embed",       "#line",        "#error",       "#warning",
	  NULL
	};

	terminal_hl_t my_hl = (terminal_hl_t) {
		.attribute = 1
	};

	display_t * cterm = &(display_t) {
		.key = "cterm",
		.callback = cterm_render_callback
	};
	hl_group_t mygroup = (hl_group_t) {
		.link = NULL
	};
	new_display_mode(cterm);
	new_keyword_tokens(c_keywords, &mygroup);
	new_keyword_tokens(preprocessor_keywords, &mygroup);

	//
	render_string(buffer, "cterm");
	putchar('\n');
	free (buffer);

	return 0;
}