#include "stb_truetype_interface.h"

#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"

#include "font/font_utils.h"
#include "interface/image_interface.h"

void stb_truetype_deleter(image_heap_t* in_data) {
	if (in_data == nullptr) {
		return;
	}
	if (in_data->data != nullptr) {
		stbtt_FreeBitmap((uint8_t*)in_data->data, nullptr);
	}
	delete in_data;
}

std::string stb_font_face_t::get_font_name() const {
	const auto* data = static_cast<const uint8_t*>(font_data_->get_data());
	const int font_offset = stbtt_GetFontOffsetForIndex(data, 0);
	if (font_offset < 0) {
		return "unknown font";
	}

	uint32_t name_offset = font::find_table_offset(data, font_offset, "name");
	if (name_offset == 0) {
		return "unknown font";
	}

	const uint8_t* name_table = data + name_offset;
	const uint16_t count = font::read_u16(name_table + 2);
	const uint16_t string_offset = font::read_u16(name_table + 4);

	for (uint16_t i = 0; i < count; ++i) {
		const uint8_t* record = name_table + 6 + 12 * i;
		const uint16_t name_id = font::read_u16(record + 6);
		if (name_id == 4 || name_id == 1) {
			const uint16_t length = font::read_u16(record + 8);
			const uint16_t offset = font::read_u16(record + 10);
			if (length > 0) {
				const uint8_t* string_data = name_table + string_offset + offset;
				std::string name(reinterpret_cast<const char*>(string_data), length);
				return name;
			}
		}
	}
	return "unknown font";
}

std::string stb_font_face_t::get_font_family() const {
	const auto* data = static_cast<const uint8_t*>(font_data_->get_data());
	const int font_offset = stbtt_GetFontOffsetForIndex(data, 0);
	if (font_offset < 0) {
		return "unknown font";
	}

	uint32_t name_offset = font::find_table_offset(data, font_offset, "name");
	if (name_offset == 0) {
		return "unknown font";
	}

	const uint8_t* name_table = data + name_offset;
	const uint16_t count = font::read_u16(name_table + 2);
	const uint16_t string_offset = font::read_u16(name_table + 4);

	for (uint16_t i = 0; i < count; ++i) {
		const uint8_t* record = name_table + 6 + 12 * i;
		const uint16_t name_id = font::read_u16(record + 6);
		if (name_id == 1) {
			const uint16_t length = font::read_u16(record + 8);
			const uint16_t offset = font::read_u16(record + 10);
			if (length > 0) {
				const uint8_t* string_data = name_table + string_offset + offset;
				std::string name(reinterpret_cast<const char*>(string_data), length);
				return name;
			}
		}
	}
	return "unknown font";
}

std::string stb_font_face_t::get_font_style() const {
	const auto* data = static_cast<const uint8_t*>(font_data_->get_data());
	const int font_offset = stbtt_GetFontOffsetForIndex(data, 0);
	if (font_offset < 0) {
		return "unknown font";
	}

	uint32_t name_offset = font::find_table_offset(data, font_offset, "name");
	if (name_offset == 0) {
		return "unknown font";
	}

	const uint8_t* name_table = data + name_offset;
	const uint16_t count = font::read_u16(name_table + 2);
	const uint16_t string_offset = font::read_u16(name_table + 4);

	for (uint16_t i = 0; i < count; ++i) {
		const uint8_t* record = name_table + 6 + 12 * i;
		const uint16_t name_id = font::read_u16(record + 6);
		if (name_id == 2) {
			const uint16_t length = font::read_u16(record + 8);
			const uint16_t offset = font::read_u16(record + 10);
			if (length > 0) {
				const uint8_t* string_data = name_table + string_offset + offset;
				std::string name(reinterpret_cast<const char*>(string_data), length);
				return name;
			}
		}
	}
	return "unknown font";
}

bool stb_font_face_t::supports_color_emoji() const {
	// stb_truetype不支持彩色表情符号
	return false;
}

font_v_metrics_t stb_font_face_t::get_metrics() const {
	int32_t ascent, descent, line_gap;
    // 尝试使用OS2表中的度量，这通常更准确
    if (!stbtt_GetFontVMetricsOS2(&font_info_, &ascent, &descent, &line_gap)) {
        // 如果失败，使用默认的VMetrics
        stbtt_GetFontVMetrics(&font_info_, &ascent, &descent, &line_gap);
    }

	font_v_metrics_t metrics{};
	metrics.ascent   = static_cast<float>(ascent) * scale_;
	metrics.descent  = static_cast<float>(descent) * scale_;
	metrics.line_gap = static_cast<float>(line_gap) * scale_;
    return metrics;
}

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

	int32_t width, height, xoff, yoff;

	// 获取字形图像
	const auto bitmap = stbtt_GetGlyphBitmap(&font_info_, scale_, scale_, in_glyph_id, &width, &height, &xoff, &yoff);

	// 创建位图
	std::shared_ptr<image_heap_t> image(new image_heap_t(), stb_truetype_deleter);
	image->width        = width;
	image->height       = height;
	image->pixel_format = SG_PIXELFORMAT_R8;
	image->data         = bitmap;

	return image;
}

std::shared_ptr<image_heap_t> stb_font_face_t::get_emoji_image(int32_t in_glyph_id) const {
	return nullptr;
}

uint32_t stb_font_face_t::find_glyph_index(uint32_t in_unicode_codepoint) const {
	return stbtt_FindGlyphIndex(&font_info_, in_unicode_codepoint);
}

float stb_font_face_t::get_kerning(uint32_t in_first_glyph_id, uint32_t in_second_glyph_id) const {
	return (float)stbtt_GetGlyphKernAdvance(&font_info_, in_first_glyph_id, in_second_glyph_id) * scale_;
}

glyph_shaped_t stb_font_face_t::shape_glyph(uint32_t in_glyph_id) const {
	int32_t advance, lsb;
	stbtt_GetGlyphHMetrics(&font_info_, in_glyph_id, &advance, &lsb);
	// 获取字形的边界框
	int32_t x0, y0, x1, y1;
	stbtt_GetGlyphBitmapBox(&font_info_, in_glyph_id, scale_, scale_, &x0, &y0, &x1, &y1);

	glyph_shaped_t out{};
	out.glyph_index = in_glyph_id;
	out.advance.x() = (float)advance * scale_;
	out.advance.y() = 0.0f;
	out.offset.x() = (float)lsb * scale_;
	out.offset.y() = 0.0f;
	out.rect.set_position({ x0, y0 });
	out.rect.set_size({ x1 - x0, y1 - y0 });

	return out;
}

bool stb_font_face_t::on_load() {
	const auto offset = stbtt_GetFontOffsetForIndex(font_data_->get_u8(), 0);
	return stbtt_InitFont(&font_info_, font_data_->get_u8(), offset) != 0;
}

void stb_font_face_t::on_set_font_size(float in_size) {
	font_face_interface::on_set_font_size(in_size);
	scale_ = get_scale_for_pixel_height(in_size);
}

bool init_font_system() {
	// stb_truetype不需要初始化
	return true;
}

void destroy_font_system() {
	// stb_truetype不需要销毁
}

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