//#include <stdio.h>
#include <curses.h>
#define CLAY_IMPLEMENTATION
#include "../../clay.h"

#define HPIXELS_PER_CHAR 5 //these are used to convert between Clay pixel space and terminal character locations
#define VPIXELS_PER_CHAR 8

void Clay_textui_Render(WINDOW * win, Clay_RenderCommandArray renderCommands);

void Clay_textui_Render(WINDOW * win, Clay_RenderCommandArray renderCommands){
    short color_pair = 1; //increment on use, 0 is reserved
    short color = 10; //get passed reserved colors
    //maybe keep a list of Clay colors and only init a new color if required.
    //clear the screen/window
    clear();//sets cursor to 0,0
    for(int i = 0; i < renderCommands.length; i++){
        //handle every command
        switch (renderCommands.internalArray[i].commandType){
            case CLAY_RENDER_COMMAND_TYPE_NONE:
                continue;
            case CLAY_RENDER_COMMAND_TYPE_RECTANGLE:
                Clay_RectangleElementConfig *rectangle_config = renderCommands.internalArray[i].config.rectangleElementConfig;
                init_color(color, rectangle_config->color.r, rectangle_config->color.g, rectangle_config->color.b);
                init_pair(color_pair, color, color);
                attr_on(color_set(color_pair,0),0);
                for(int j = 0; j < renderCommands.internalArray[i].boundingBox.height/VPIXELS_PER_CHAR; j++){
                    mvhline(renderCommands.internalArray[i].boundingBox.y/VPIXELS_PER_CHAR + j, renderCommands.internalArray[i].boundingBox.x/HPIXELS_PER_CHAR, '#', renderCommands.internalArray[i].boundingBox.width/HPIXELS_PER_CHAR);
                }
                attr_off(color_set(color_pair,0),0);
                color_pair++;
                color++;
                //TODO render radius corners
                break;
            case CLAY_RENDER_COMMAND_TYPE_BORDER:
                Clay_BorderElementConfig *border_config = renderCommands.internalArray[i].config.borderElementConfig;
                //just get a border on there for now
                if(border_config->top.width > 0){
                    init_color(color, border_config->top.color.r, border_config->top.color.g, border_config->top.color.b);
                    init_pair(color_pair, color, COLOR_CYAN);//TODO get color at target location and init pair with that background
                    attr_on(color_set(color_pair,0),0);
                    mvhline(renderCommands.internalArray[i].boundingBox.y/VPIXELS_PER_CHAR, renderCommands.internalArray[i].boundingBox.x/HPIXELS_PER_CHAR + 1, '-', renderCommands.internalArray[i].boundingBox.width/HPIXELS_PER_CHAR - 2);
                    attr_off(color_set(color_pair,0),0);
                    color_pair++; //can we just check of the color requested is already there?
                    color++;
                }
                if(border_config->bottom.width > 0){
                    init_color(color, border_config->bottom.color.r, border_config->bottom.color.g, border_config->bottom.color.b);
                    init_pair(color_pair, color, COLOR_CYAN);//TODO get color at target location and init pair with that background
                    attr_on(color_set(color_pair,0),0);
                    mvhline(renderCommands.internalArray[i].boundingBox.y/VPIXELS_PER_CHAR + renderCommands.internalArray[i].boundingBox.height/VPIXELS_PER_CHAR, renderCommands.internalArray[i].boundingBox.x/HPIXELS_PER_CHAR + 1, '-', renderCommands.internalArray[i].boundingBox.width/HPIXELS_PER_CHAR - 2);
                    attr_off(color_set(color_pair,0),0);
                    color_pair++;
                    color++;
                }
                if(border_config->left.width > 0){
                    init_color(color, border_config->left.color.r, border_config->left.color.g, border_config->left.color.b);
                    init_pair(color_pair, color, COLOR_CYAN);//TODO get color at target location and init pair with that background
                    attr_on(color_set(color_pair,0),0);
                    mvvline(renderCommands.internalArray[i].boundingBox.y/VPIXELS_PER_CHAR + 1, renderCommands.internalArray[i].boundingBox.x/HPIXELS_PER_CHAR, '|', renderCommands.internalArray[i].boundingBox.height/VPIXELS_PER_CHAR - 1);
                    attr_off(color_set(color_pair,0),0);
                    color_pair++;
                    color++;
                }
                if(border_config->right.width > 0){
                    init_color(color, border_config->right.color.r, border_config->right.color.g, border_config->right.color.b);
                    init_pair(color_pair, color, COLOR_CYAN);//TODO get color at target location and init pair with that background
                    attr_on(color_set(color_pair,0),0);
                    mvvline(renderCommands.internalArray[i].boundingBox.y/VPIXELS_PER_CHAR + 1, renderCommands.internalArray[i].boundingBox.x/HPIXELS_PER_CHAR + renderCommands.internalArray[i].boundingBox.width/HPIXELS_PER_CHAR - 1, '|', renderCommands.internalArray[i].boundingBox.height/VPIXELS_PER_CHAR - 1);
                    attr_off(color_set(color_pair,0),0);
                    color_pair++;
                    color++;
                }
                break;
            case CLAY_RENDER_COMMAND_TYPE_TEXT:
                Clay_TextElementConfig *text_config = renderCommands.internalArray[i].config.textElementConfig;
                attr_on(color_set(0,0),0);
                int x = renderCommands.internalArray[i].boundingBox.x/HPIXELS_PER_CHAR;
                int y = renderCommands.internalArray[i].boundingBox.y/VPIXELS_PER_CHAR; //text is referenced from bottom corner?
                int w = renderCommands.internalArray[i].boundingBox.width/HPIXELS_PER_CHAR;
                int h = renderCommands.internalArray[i].boundingBox.height/VPIXELS_PER_CHAR;
                int line = 0;
                int column = 0;
                for (int k = 0; k < renderCommands.internalArray[i].text.length; k++) {
                    if (column >= w) {
                        column = 0;
                        line += 1;
                    }
                    mvaddch(y + line, x + column, renderCommands.internalArray[i].text.chars[k]);
                    column += 1;
                }
                break;
            case CLAY_RENDER_COMMAND_TYPE_IMAGE:
            case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START:
            case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END:
            case CLAY_RENDER_COMMAND_TYPE_CUSTOM:
            default: continue;
        }
    }
    attr_on(color_set(0,0),0);
    mvwprintw(win, 0, 0, "Number of color pairs used: %i", color_pair);
    refresh();//update the screen/window
}


//written by EmmanuelMess: https://github.com/nicbarker/clay/pull/91/commits/7ce74ba46c01f32e4517032e9da76bf54ecf7a43
static inline Clay_Dimensions Textui_MeasureText(Clay_String *text, Clay_TextElementConfig *config) {
	Clay_Dimensions textSize = { 0 };
	float maxTextWidth = 0.0f;
	float lineTextWidth = 0;
	float textHeight = 1;

	for (int i = 0; i < text->length; ++i)
	{
		if (text->chars[i] == '\n') {
			maxTextWidth = maxTextWidth > lineTextWidth ? maxTextWidth : lineTextWidth;
			lineTextWidth = 0;
			textHeight++;
			continue;
		}
		lineTextWidth++;
	}
	maxTextWidth = maxTextWidth > lineTextWidth ? maxTextWidth : lineTextWidth;

	textSize.width = maxTextWidth*HPIXELS_PER_CHAR;
	textSize.height = textHeight*VPIXELS_PER_CHAR;

	return textSize;
}