/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "FontAtlasType.hpp"
#include "Math/Math.hpp"
#include "Data/Containers/Array.hpp"
#include "Scene/Texture.hpp"
#include <map>
#include <filesystem>

namespace OpenVulkano::Scene
{
	struct GlyphInfo
	{
		//GlyphGeometry geometry;
		//GlyphBox glyphBox;
		Math::Vector2f_SIMD pos[4] = {};
		Math::Vector2f_SIMD uv[4] = {};
		double advance = 0;
	};

	class FontAtlas
	{
		struct Metadata
		{
			double lineHeight = 0;
			FontAtlasType atlasType = FontAtlasType::UNKNOWN;
		};

		std::map<uint32_t, GlyphInfo> m_glyphs;
		Metadata m_metadata;
		Array<uint8_t> m_imgData;
		Texture m_texture;

		void LoadLegacy(std::span<char> data);
		void LoadNew(std::span<char> data);
		void LoadImage(std::span<char> data);

		Array<char> SerializeMetadata() const;
		void DeserializeMetadata(const std::span<char>& data);

	public:
		using Ptr = std::shared_ptr<FontAtlas>;

		FontAtlas() = default;
		FontAtlas(const Math::Vector2ui textureResolution, const double lineHeight, const FontAtlasType atlasType,
		          DataFormat dataFormat)
		{
			Init(textureResolution, lineHeight, atlasType, dataFormat);
		}
		FontAtlas(const std::filesystem::path& path);
		FontAtlas(const std::span<char> data) { Load(data); }

		void Init(Math::Vector2ui textureResolution, double lineHeight, FontAtlasType atlasType, DataFormat dataFormat);

		void Save(const std::filesystem::path& path) const;
		void Load(std::span<char> data);

		[[nodiscard]] operator bool() const { return !m_glyphs.empty() && m_texture.textureBuffer; }

		[[nodiscard]] Texture* GetTexture() { return &m_texture; }
		[[nodiscard]] decltype(m_glyphs)& GetGlyphs() { return m_glyphs; }
		[[nodiscard]] decltype(Metadata::lineHeight) GetLineHeight() const { return m_metadata.lineHeight;}
		[[nodiscard]] FontAtlasType GetAtlasType() const { return m_metadata.atlasType;}
	};
}