#include "font_class.h"

font_class::font_class()
{
    LOG_INIT("Initializing font class constructor");
    m_Font = 0;
    m_Texture = 0;
    LOG_INIT("Font class constructor initialized");
}


font_class::font_class(const font_class& other)
{
}


font_class::~font_class()
{
    LOG_SHUTDOWN("Font class destructor called");
}

bool font_class::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext, int fontChoice)
{
    LOG_INIT("Initializing font class");

    char fontFilename[128];
    char fontTextureFilename[128];
    bool result;

    // Choose one of the available fonts, and default to the first font otherwise.
    switch (fontChoice)
    {
    case 0:
    {
        strcpy_s(fontFilename, "font01.txt");
        strcpy_s(fontTextureFilename, "font01.tga");
        m_fontHeight = 32.0f;
        m_spaceSize = 3;
        break;
    }
    default:
    {
        strcpy_s(fontFilename, "font01.txt");
        strcpy_s(fontTextureFilename, "font01.tga");
        m_fontHeight = 32.0f;
        m_spaceSize = 3;
        break;
    }
    }

    // Load in the text file containing the font data.
    result = LoadFontData(fontFilename);
    if (!result)
    {
        LOG_ERROR("Failed to load font data");
        R_FALSE
    }

    // Load the texture that has the font characters on it.
    result = LoadTexture(device, deviceContext, fontTextureFilename);
    if (!result)
    {
        LOG_ERROR("Failed to load font texture");
        R_FALSE
    }

    LOG_INIT("Font class initialized");

    R_TRUE
}

void font_class::Shutdown()
{
    LOG_SHUTDOWN("Shutting down font class");
    // Release the font texture.
    ReleaseTexture();

    // Release the font data.
    ReleaseFontData();
    LOG_SHUTDOWN("Font class shut down");

    return;
}

bool font_class::LoadFontData(char* filename)
{
    LOG_INFO("Loading font data from " + std::string(filename));

    std::ifstream fin;
    int i;
    char temp;

    // Create the font spacing buffer.
    m_Font = new FontType[95];

    // Read in the font size and spacing between chars.
    fin.open(filename);
    if (fin.fail())
    {
        LOG_ERROR("Failed to open font file");
        R_FALSE
    }

    // Read in the 95 used ascii characters for text.
    for (i = 0; i < 95; i++)
    {
        fin.get(temp);
        while (temp != ' ')
        {
            fin.get(temp);
        }
        fin.get(temp);
        while (temp != ' ')
        {
            fin.get(temp);
        }

        fin >> m_Font[i].left;
        fin >> m_Font[i].right;
        fin >> m_Font[i].size;
    }

    // Close the file.
    fin.close();

    LOG_INFO("Font data loaded");

    R_TRUE
}

void font_class::ReleaseFontData()
{
    LOG_SHUTDOWN("Releasing font data");
    // Release the font data array.
    if (m_Font)
    {
        LOG_SHUTDOWN("Releasing font array");
        delete[] m_Font;
        m_Font = 0;
        LOG_SHUTDOWN("Font array released");
    }

    LOG_SHUTDOWN("Font data released");

    return;
}

bool font_class::LoadTexture(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename)
{
    LOG_INFO("Loading font texture from " + std::string(filename));

    bool result;


    // Create and initialize the font texture object.
    m_Texture = new texture_class;

    result = m_Texture->Initialize(device, deviceContext, filename);
    if (!result)
    {
        LOG_ERROR("Failed to initialize font texture");
        R_FALSE
    }

    LOG_INFO("Font texture loaded");

    R_TRUE
}

void font_class::ReleaseTexture()
{
    LOG_SHUTDOWN("Releasing font texture");
    // Release the texture object.
    if (m_Texture)
    {
        LOG_SHUTDOWN("Releasing texture object");
        m_Texture->Shutdown();
        delete m_Texture;
        m_Texture = 0;
        LOG_SHUTDOWN("Texture object released");
    }

    LOG_SHUTDOWN("Font texture released");

    return;
}

ID3D11ShaderResourceView* font_class::GetTexture()
{
    return m_Texture->GetTexture();
}

void font_class::BuildVertexArray(void* vertices, char* sentence, float drawX, float drawY)
{
    VertexType* vertexPtr;
    int numLetters, index, i, letter;


    // Coerce the input vertices into a VertexType structure.
    vertexPtr = (VertexType*)vertices;

    // Get the number of letters in the sentence.
    numLetters = (int)strlen(sentence);

    // Initialize the index to the vertex array.
    index = 0;

    // Draw each letter onto a quad.
    for (i = 0; i < numLetters; i++)
    {
        letter = ((int)sentence[i]) - 32;

        // If the letter is a space then just move over three pixels.
        if (letter == 0)
        {
            drawX = drawX + m_spaceSize;
        }
        else
        {
            // First triangle in quad.
            vertexPtr[index].position = XMFLOAT3(drawX, drawY, 0.0f);  // Top left.
            vertexPtr[index].texture = XMFLOAT2(m_Font[letter].left, 0.0f);
            index++;

            vertexPtr[index].position = XMFLOAT3((drawX + m_Font[letter].size), (drawY - m_fontHeight), 0.0f);  // Bottom right.
            vertexPtr[index].texture = XMFLOAT2(m_Font[letter].right, 1.0f);
            index++;

            vertexPtr[index].position = XMFLOAT3(drawX, (drawY - m_fontHeight), 0.0f);  // Bottom left.
            vertexPtr[index].texture = XMFLOAT2(m_Font[letter].left, 1.0f);
            index++;

            // Second triangle in quad.
            vertexPtr[index].position = XMFLOAT3(drawX, drawY, 0.0f);  // Top left.
            vertexPtr[index].texture = XMFLOAT2(m_Font[letter].left, 0.0f);
            index++;

            vertexPtr[index].position = XMFLOAT3(drawX + m_Font[letter].size, drawY, 0.0f);  // Top right.
            vertexPtr[index].texture = XMFLOAT2(m_Font[letter].right, 0.0f);
            index++;

            vertexPtr[index].position = XMFLOAT3((drawX + m_Font[letter].size), (drawY - m_fontHeight), 0.0f);  // Bottom right.
            vertexPtr[index].texture = XMFLOAT2(m_Font[letter].right, 1.0f);
            index++;

            // Update the x location for drawing by the size of the letter and one pixel.
            drawX = drawX + m_Font[letter].size + 1.0f;
        }
    }

    return;
}

int font_class::GetSentencePixelLength(char* sentence)
{
    int pixelLength, numLetters, i, letter;


    pixelLength = 0;
    numLetters = (int)strlen(sentence);

    for (i = 0; i < numLetters; i++)
    {
        letter = ((int)sentence[i]) - 32;

        // If the letter is a space then count it as three pixels.
        if (letter == 0)
        {
            pixelLength += m_spaceSize;
        }
        else
        {
            pixelLength += (m_Font[letter].size + 1);
        }
    }

    return pixelLength;
}

int font_class::GetFontHeight()
{
    return (int)m_fontHeight;
}
