//
// Created by 46944 on 25-4-1.
//

#include "freetype_interface.h"

#include "freetype/ftglyph.h"
#include "interface/image_interface.h"

FT_Library library_;

void freetype_bitmap_deleter(image_heap_t* in_data) {
	if (in_data == nullptr) {
		return;
	}
	if (in_data->data != nullptr) {
		const auto data = (uint8_t*)in_data->data;
		delete[] data;
		in_data->data = nullptr;
	}
	delete in_data;
}

std::string freetype_interface::get_font_name() const {
	if (face_ == nullptr) {
		return "unknown font";
	}
	return face_->family_name ? face_->family_name : "unknown font";
}

std::string freetype_interface::get_font_family() const {
	if (face_ == nullptr) {
		return "unknown font";
	}
	return face_->family_name ? face_->family_name : "unknown font";
}

std::string freetype_interface::get_font_style() const {
	if (face_ == nullptr) {
		return "unknown font";
	}
	return face_->style_name ? face_->style_name : "unknown font";
}

bool freetype_interface::supports_color_emoji() const {
	return FT_HAS_COLOR(face_) || FT_HAS_SBIX(face_) || FT_HAS_SVG(face_);
}

font_v_metrics_t freetype_interface::get_metrics() const {
	font_v_metrics_t metrics{};
	metrics.ascent   = face_->ascender / 64.f;
	metrics.descent  = face_->descender / 64.f;
	metrics.line_gap = (face_->height - (face_->ascender - face_->descender)) / 64.f;
	return metrics;
}

std::shared_ptr<image_heap_t> freetype_interface::get_glyph_image(int32_t in_glyph_id) const {
	if (in_glyph_id == 0) {
		return nullptr;
	}

	// 加载字形
	FT_Load_Glyph(face_, in_glyph_id, FT_LOAD_RENDER);
	if (face_->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
		return nullptr;
	}

	// 创建位图
	// 这里使用了一个自定义的删除器来释放位图数据
	std::shared_ptr<image_heap_t> image(new image_heap_t(), freetype_bitmap_deleter);
	image->width        = face_->glyph->bitmap.width;
	image->height       = face_->glyph->bitmap.rows;
	image->pixel_format = SG_PIXELFORMAT_R8;
	image->data         = new uint8_t[image->width * image->height];
	std::memcpy(image->data, face_->glyph->bitmap.buffer, image->width * image->height);

	return image;
}

std::shared_ptr<image_heap_t> freetype_interface::get_emoji_image(int32_t in_glyph_id) const {
	if (in_glyph_id == 0) {
		return nullptr;
	}

	// 加载字形
	FT_Load_Glyph(face_, in_glyph_id, FT_LOAD_COLOR);
	if (face_->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
		return nullptr;
	}

	// 创建位图
	// 这里使用了一个自定义的删除器来释放位图数据
	std::shared_ptr<image_heap_t> image(new image_heap_t(), freetype_bitmap_deleter);
	image->width        = face_->glyph->bitmap.width;
	image->height       = face_->glyph->bitmap.rows;
	image->pixel_format = SG_PIXELFORMAT_RGBA8;
	image->data         = new uint8_t[image->width * image->height * 4];
	std::memcpy(image->data, face_->glyph->bitmap.buffer, image->width * image->height);
	return image;
}

uint32_t freetype_interface::find_glyph_index(uint32_t in_unicode_codepoint) const {
	return FT_Get_Char_Index(face_, in_unicode_codepoint);
}

float freetype_interface::get_kerning(uint32_t in_first_glyph_id, uint32_t in_second_glyph_id) const {
	FT_Vector kerning;
	if (FT_Get_Kerning(face_, in_first_glyph_id, in_second_glyph_id, FT_KERNING_DEFAULT, &kerning) != 0) {
		return 0.0f;
	}
	return static_cast<float>(kerning.x) / 64.0f; // FreeType返回的单位是1/64像素
}

glyph_shaped_t freetype_interface::shape_glyph(uint32_t in_glyph_id) const {
	glyph_shaped_t out{};

	FT_Load_Glyph(face_, in_glyph_id, FT_LOAD_NO_BITMAP);
	FT_Glyph glyph;
	if (FT_Get_Glyph(face_->glyph, &glyph) != 0) {
		return out;
	}
	FT_Done_Glyph(glyph);

	out.glyph_index = in_glyph_id;
	out.advance.x() = static_cast<float>(face_->glyph->advance.x) / 64.0f;
	out.advance.y() = static_cast<float>(face_->glyph->advance.y) / 64.0f;
	out.offset.x() = static_cast<float>(face_->glyph->metrics.horiBearingX) / 64.0f;
	out.offset.y() = static_cast<float>(face_->glyph->metrics.horiBearingY) / 64.0f;
	out.rect.set_position({ face_->glyph->metrics.horiBearingX / 64.f,
	                        face_->glyph->metrics.horiBearingY / 64.f });
	out.rect.set_size({ face_->glyph->metrics.width / 64.f,
	                    face_->glyph->metrics.height / 64.f });

	return out;
}

bool freetype_interface::on_load() {
	return FT_New_Memory_Face(library_, font_data_->get_u8(), font_data_->get_size(), 0, &face_) == 0;
}

void freetype_interface::on_set_font_size(float in_size) {
	font_face_interface::on_set_font_size(in_size);
	FT_Set_Pixel_Sizes(face_, 0, static_cast<FT_UInt>(in_size));
}

bool init_font_system() {
	if (FT_Init_FreeType(&library_)) {
		return false;
	}
	return true;
}

void destroy_font_system() {
	FT_Done_FreeType(library_);
}

std::shared_ptr<font_face_interface> create_font_face(const std::filesystem::path& in_path) {
	auto font_face = std::make_shared<freetype_interface>();
	if (!font_face->load(in_path)) {
		return nullptr;
	}
	return font_face;
}
