/******************************************************************************
*	File		-	glText.h
*	Author		-	Joey Pollack
*	Date		-	2021/09/07 (y/m/d)
*	Mod Date	-	2021/09/07 (y/m/d)
*	Description	-	Used to load and manage fonts. Renders text using freetype
*                   and openGL.
******************************************************************************/

#ifndef GL_TEXT_H_
#define GL_TEXT_H_

#include <map>
#include <vector>
#include <string>
#include <glad/gl.h>
#include "glShader.h"
#include <utils/opRes.h>
#include <utils/types.h>
#include <glm/glm.hpp>

struct FT_LibraryRec_;
typedef struct FT_LibraryRec_ * FT_Library;

struct FT_FaceRec_;
typedef struct FT_FaceRec_*  FT_Face;

namespace lunarium
{
    class glText
    {
    public:

        OpRes Initialize();
        int LoadFont(const char* fontFile, const char* name, float size = 12.0f, int weight = 400);
		int LoadFont(const unsigned char* fontData, int dataSize, const char* name, float size = 12.0f, int weight = 400);
        void DrawString(int fontID, const char* text, glm::vec2 position, Color color, float scale, glm::mat4 projection);
		void DrawString(int fontID, const char* text, glm::vec2 topLeft, glm::vec2 botRight, Color color, float scale, glm::mat4 projection);

    private:

        struct Character
		{
			unsigned int    TextureID;  // ID handle of the glyph texture
			Sizef			Size;       // Size of glyph
			glm::vec2		Bearing;    // Offset from baseline to left/top of glyph
			int				DownShift;	// Size/Amount of glyph below the baseline
			unsigned int	Advance;    // Offset to advance to next glyph
		};

		struct Font
		{
			std::string Name;
			// The tallest character that does not go below the base line
			// This is also the distance from the string Y position to the baseline
			unsigned int MaxHeight;

			// This is the max distance a char will go below the baseline
			unsigned int MaxDownShift;
			std::map<char, Character> CharSet;
			Font() : MaxHeight(0), MaxDownShift(0)
			{}
		};

		std::vector<Font> mFonts;

        GLuint mTextVAO;
		GLuint mTextVBO;
		glShader mTextShader;

	private: // HELPERS
		int CreateFont(const char* name, FT_Library ft, FT_Face face, float size = 12.0f, int weight = 400);

    private:    // SHADER CODE
    		const char* VertShader = "#version 450 core\n\
			layout(location = 0) in vec4 vertex; \
			out vec2 TexCoords;\
	\
			uniform mat4 projection;\
	\
			void main()\
			{\
				gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);\
				TexCoords = vertex.zw;\
			} ";

		const char* FragShader = "#version 450 core\n\
			in vec2 TexCoords;\
			out vec4 color;\
	\
			uniform sampler2D text;\
			uniform vec4 textColor;\
	\
			void main()\
			{\
				vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);\
				color = vec4(textColor) * sampled;\
			}";
    };
}

#endif // GL_TEXT_H_