#define STB_TRUETYPE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define STB_RECT_PACK_IMPLEMENTATION

#include "stb_rect_pack.h"
#include "stb_truetype.h"
#include "stb_image_write.h"
#include "load_entire_file.h"
#include "log.h"
#include "defer.h"
#include "glyphs.h"

struct Glyph {
	int x_off;
	int y_off;
	char* data;
};

Glyph_Coord glyph_coords[512];

int main() {
	stbtt_fontinfo font_info;
	stbrp_context packer_context;
	stbrp_node packer_nodes[600];
	stbrp_rect packer_rects[100];

	Glyph glyphs[512];

	String font_file = load_entire_file("../assets/fonts/Lexend-Regular.ttf");

	if (!font_file.length) {
		log_error("Loading font file has failed.");
		return 1;
	}
	
	if (!stbtt_InitFont(&font_info, (unsigned char*)font_file.data, 0)) {
		log_error("Init Font has failed.");
		return 1;
	}

	float font_scale = stbtt_ScaleForPixelHeight(&font_info, 48);

	stbrp_init_target(&packer_context, 512, 512, packer_nodes, sizeof(packer_nodes) / sizeof(*packer_nodes));
	int rect_number = 0;
	for (int i = ' '; i <= '~'; i++) {
		int glyph_width;
		int glyph_height;
		int glyph_offset_x;
		int glyph_offset_y;
		glyphs[rect_number].data = (char*) stbtt_GetCodepointBitmap(&font_info, font_scale, font_scale, i, &glyph_width, &glyph_height, &glyph_offset_x, &glyph_offset_y);
		glyphs[rect_number].x_off = glyph_offset_x;
		glyphs[rect_number].y_off = glyph_offset_y;
		
		packer_rects[rect_number].id = i;
		packer_rects[rect_number].w = glyph_width;
		packer_rects[rect_number].h = glyph_height;
		rect_number++;
	}

	stbrp_pack_rects(&packer_context, packer_rects, rect_number);
	char* glyph_atlas = (char*) malloc(512 * 512);
	for (int x = 0; x < 512; x++) {
		for (int y = 0; y < 512; y++) {
			glyph_atlas[y * 512 + x] = 0;
		}
	}


	for (int i = 0; i < rect_number; i++) {
		glyph_coords[i].x = packer_rects[i].x / 512.0f;
		glyph_coords[i].y = packer_rects[i].y / 512.0f;
		glyph_coords[i].width = packer_rects[i].w / 512.0f;
		glyph_coords[i].height = packer_rects[i].h / 512.0f;
		for (int x = 0; x < packer_rects[i].w; x++) {
			for (int y = 0; y < packer_rects[i].h; y++) {
				glyph_atlas[(y + packer_rects[i].y) * 512 + x + packer_rects[i].x] = glyphs[i].data[y * packer_rects[i].w + x];
			}
		}
	}

	FILE* file = fopen("../assets/fonts/glyph_coords_lexend.co", "wb");

	if (!file) {
		log_error("Glyph coords file creation has failed.");
		return 1;
	}
	defer(fclose(file));

	if (fwrite(glyph_coords, sizeof(*glyph_coords) * rect_number, 1, file) != 1) {
		log_error("fwrite for glyph_coords has failed.");
		return 1;
	}
	
	if (!stbi_write_bmp("../assets/fonts/glyph_atlas_lexend.bmp", 512, 512, 1, glyph_atlas)) {
		log_error("stbi_write_bmp has failed.");
		return 1;
	}

	return 0;
}