#include "CTextTexture.hpp"

CTextTexture::CTextTexture(ETextureType type, std::string filePath, std::string text, unsigned int fontSize, glm::vec3 fontColor, glm::bvec4 fontStyle) :
    CAbstractTexture(type),
    m_fontFilePath(filePath),
    m_renderText(text),
    m_fontSize(fontSize),
    m_fontColor(fontColor),
    m_fontStyle(fontStyle) {
}

std::string CTextTexture::getFontFilePath(void) {
    return m_fontFilePath;
}

void CTextTexture::setFontFilePath(std::string filePath) {
    m_fontFilePath = filePath;
}

std::string CTextTexture::getText(void) {
    return m_renderText;
}

void CTextTexture::setText(std::string text) {
    m_renderText = text;
}

void CTextTexture::init(void) {
    // Read the font file.
    TTF_Font* font = TTF_OpenFont(m_fontFilePath.c_str(), m_fontSize);

    SDL_Color color;
    color.r = m_fontColor.x / 255u;
    color.g = m_fontColor.y / 255u;
    color.b = m_fontColor.z / 255u;

    int style = TTF_STYLE_NORMAL;
    if (m_fontStyle.x) {
        style |= TTF_STYLE_BOLD;
    }
    if (m_fontStyle.y) {
        style |= TTF_STYLE_ITALIC;
    }
    if (m_fontStyle.z) {
        style |= TTF_STYLE_UNDERLINE;
    }
    if (m_fontStyle.z) {
        style |= TTF_STYLE_STRIKETHROUGH;
    }
    TTF_SetFontStyle(font, style);

    SDL_Surface* sdlSurface = TTF_RenderText_Blended(font, m_renderText.c_str(), color);

    if (sdlSurface == NULL) {
        throw CLibException(std::string("Can not render the text : ") + std::string(SDL_GetError()));
    }

    // Create the id.
    unsigned int id;
    glGenTextures(1, &id);
    setId(id);

    // Image format.
    GLenum internalFormat(0);
    GLenum externalFormat(0);

    if (sdlSurface->format->BytesPerPixel == 3) {
        // We use RGB as internal format.
        internalFormat = GL_RGB;

        // Choose the external format.
        if (sdlSurface->format->Rmask == 0xff)
            externalFormat = GL_RGB;
        else
            externalFormat = GL_BGR;
    }
    else if (sdlSurface->format->BytesPerPixel == 4) {
        // We use RGBA as internal format.
        internalFormat = GL_RGBA;

        // Choose the external format.
        if (sdlSurface->format->Rmask == 0xff)
            externalFormat = GL_RGBA;
        else
            externalFormat = GL_BGRA;
    }
    else {
        SDL_FreeSurface(sdlSurface);
        throw CRuntimeException("Unknow image internal format.");
    }

    // Lock the texture to use it.
    glBindTexture(GL_TEXTURE_2D, getId());

    // Fill the GL texture.
    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, sdlSurface->w, sdlSurface->h, 0, externalFormat, GL_UNSIGNED_BYTE, sdlSurface->pixels);

    // Set filters : the near texture have a linear filter.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // The far texture have a nearest filter, meaning no filter.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	// Unlock the texture.
	glBindTexture(GL_TEXTURE_2D, 0);

    // Free the font.
    TTF_CloseFont(font);

    // Free the surface.
    SDL_FreeSurface(sdlSurface);
}