/*
 * 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

#if __has_include("msdfgen.h")

#include "FontAtlasGeneratorBase.hpp"
#include <msdfgen.h>
#include <msdf-atlas-gen/msdf-atlas-gen.h>
#include <string>
#include <optional>
#include <map>
#include <variant>
#define MSDFGEN_AVAILABLE 1

namespace OpenVulkano::Scene
{

	struct SdfFontAtlasGeneratorConfig
	{
		static SdfFontAtlasGeneratorConfig sdfDefaultConfig;
		static SdfFontAtlasGeneratorConfig msdfDefaultConfig;
		int glyphSize;
		double miterLimit;
		msdfgen::Range pixelRange;
	};

	template<int Channels>
	class SdfFontAtlasGeneratorGeneric final : public FontAtlasGeneratorBase
	{
	private:
		using SdfGenerator = msdf_atlas::ImmediateAtlasGenerator<float, 1, msdf_atlas::sdfGenerator,
		                                                         msdf_atlas::BitmapAtlasStorage<msdfgen::byte, 1>>;
		using MsdfGenerator = msdf_atlas::ImmediateAtlasGenerator<float, 3, msdf_atlas::msdfGenerator,
		                                                          msdf_atlas::BitmapAtlasStorage<msdfgen::byte, 3>>;
	public:
		using Generator = std::conditional<Channels == 1, SdfGenerator, MsdfGenerator>::type;
		using Config = SdfFontAtlasGeneratorConfig;
		static constexpr int channelsCount = (Channels == 1 ? 1 : 4);
		SdfFontAtlasGeneratorGeneric();
		void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
		                   const std::optional<std::string>& pngOutput = std::nullopt) override;
		void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
		                   const std::optional<std::string>& pngOutput = std::nullopt) override;
		void GenerateAtlas(const std::string& fontFile, const msdf_atlas::Charset& charset = msdf_atlas::Charset::ASCII,
		                   const std::optional<std::string>& pngOutput = std::nullopt);
		void GenerateAtlas(const msdfgen::byte* fontData, int length,
		                   const msdf_atlas::Charset& charset = msdf_atlas::Charset::ASCII,
		                   const std::optional<std::string>& pngOutput = std::nullopt);
		void SetGeneratorConfig(const Config& config) { m_config = config; }
		Config& GetGeneratorConfig() { return m_config; }
	private:
		void InitFreetypeFromFile(msdfgen::FreetypeHandle*& ft, msdfgen::FontHandle*& font, const std::string& file);
		void InitFreetypeFromBuffer(msdfgen::FreetypeHandle*& ft, msdfgen::FontHandle*& font,
		                            const msdfgen::byte* fontData, int length);
		void Generate(msdfgen::FreetypeHandle* ft, msdfgen::FontHandle* font, const msdf_atlas::Charset& chset,
		              const std::optional<std::string>& pngOutput);
	private:
		Config m_config;
	};
	using SdfFontAtlasGenerator = SdfFontAtlasGeneratorGeneric<1>;
	using MsdfFontAtlasGenerator = SdfFontAtlasGeneratorGeneric<3>;
}
#endif
