#include <stdio.h>
#include <sys/ksys.h>

#include "render.h"


int gwBuf(char *buf)
{
    return *((int*)buf);
}


char* pixelBuf(char *buf, int x, int y)
{
    return buf + 8 + (y * gwBuf(buf) + x) * 4;
}


void render_Rect(int color, char *buf, int pos_x, int pos_y, int len_x, int len_y)
{
	for (int x = pos_x; x < pos_x + len_x; x++)
	{
		for (int y = pos_y; y < pos_y + len_y; y++)
		{
			*(pixelBuf(buf, x, y) + 0) = (color      ) & 0xFF;
			*(pixelBuf(buf, x, y) + 1) = (color >>  8) & 0xFF;
			*(pixelBuf(buf, x, y) + 2) = (color >> 16) & 0xFF;
			*(pixelBuf(buf, x, y) + 3) = (color >> 24) & 0xFF;
		}
	}
}


void render_DrawChar(pen_t *pen, char *buf, int buf_width, char ch)
{
	if (pen->pos.x > (buf_width - PADDING * 8))
	{
		// return;
		pen->pos.x = PADDING;
		pen->pos.y += 16 * pen->mul;
	}
	// printf("len = %d\n", len);
	int mul_int = (int)pen->mul - 1 + 0x8;
	asm_inline(
		"int $0x40"
		:
		: "a"(4),
		  "b"((pen->pos.x << 16) | pen->pos.y),
		  "c"((mul_int << 24) | 0x10000000 | (pen->color & 0x00FFFFFF)),
		  "d"(&ch),
		  "S"(1),
		  "D"(buf)
		: "memory"
	);
	if (pen->bold)
	{
		asm_inline(
			"int $0x40"
			:
			: "a"(4),
			  "b"(((pen->pos.x + 1) << 16) | pen->pos.y),
			  "c"((mul_int << 24) | 0x10000000 | (pen->color & 0x00FFFFFF)),
			  "d"(&ch),
			  "S"(1),
			  "D"(buf)
			: "memory"
		);
		pen->pos.x += pen->mul;
	}
	if (pen->strike)
	{
		if (pen->bold)
		{
			render_Rect(
				pen->color, buf,
				pen->pos.x, pen->pos.y + 8,
				(8 + 1) * pen->mul, 1 * pen->mul
			);
		}
		else
		{
			render_Rect(
				pen->color, buf,
				pen->pos.x, pen->pos.y + 8,
				8 * pen->mul, 1 * pen->mul
			);
		}
	}
	if (pen->italic)
	{
		int heights[3] = {6 * pen->mul, 3 * pen->mul, 7 * pen->mul};
		int shifts[3]  = {1 * pen->mul, 0 * pen->mul, 0 * pen->mul};

		int stripe_start = pen->pos.y;

		for (int stripe = 0; stripe < 3; stripe++)
		{
			int stripe_height = heights[stripe];
			int stripe_shift  = shifts[stripe];

			// int stripe_start = pen->pos.y + stripe * (8 * pen->mul);
			int stripe_end = stripe_start + stripe_height;

			for (int x = pen->pos.x + 8 * pen->mul; x >= pen->pos.x; x--)
			{
				for (int y = stripe_start; y < stripe_end; y++)
				{
					char *dst_pix = pixelBuf(buf, x, y);
					char *src_pix = pixelBuf(buf, x - stripe_shift, y);

					dst_pix[0] = src_pix[0];
					dst_pix[1] = src_pix[1];
					dst_pix[2] = src_pix[2];
					dst_pix[3] = src_pix[3];

					/*render_Rect(
						0xF2EFEC, buf,
						pen->pos.x, pen->pos.y,
						stripe_shift * pen->mul, stripe_height
					);*/
				}
			}
			stripe_start = stripe_end;
		}
	}
	pen->pos.x += 8 * pen->mul;
}


void render_DrawLen(pen_t *pen, char *buf, char *text, int len)
{
	int buf_width = gwBuf(buf);
	for (int i = 0; i < len; i++)
	{
		render_DrawChar(pen, buf, buf_width, text[i]);
	}
}


/*void render_DrawText(pen_t *pen, char *buf, char *text)
{
	render_DrawLen(pen, buf, text, countUTF8Z(text, -1));
	//_ksys_draw_text(text, pen->pos.x, pen->pos.y, 32, pen->color);
}*/


void render_NewLn(pen_t *pen, char *buf)
{
	if (pen->mode == quote)
	{
		render_Rect(
			0x00000000, buf,
			PADDING + 2, pen->pos.y,
			pen->font_size.x * pen->mul - 4, pen->font_size.y * pen->mul
		);
		pen->pos.x = PADDING + pen->font_size.x * pen->mul * 2;
	}
	else
	{
		pen->pos.x = PADDING;
	}
	pen->pos.y += (int)(pen->mul * 16);
}
