#include "pch.h"
#include "log.h"
#include "node_text.h"
#include "shader.h"

Node* NodeText::clone_instantiate() const
{
    return new NodeText();
}

void NodeText::clone_copy(Node* dest) const
{
    Node::clone_copy(dest);
    NodeText* n = static_cast<NodeText*>(dest);
    n->m_text_mesh.max_width = m_text_mesh.max_width;
    n->m_text_mesh.create();
    n->m_text_mesh.update(font_id, m_text.c_str());
    n->m_text = m_text;
    n->m_font = m_font;
    n->m_color = m_color;
    n->m_font_size = m_font_size;
    n->font_id = font_id;
}

void NodeText::create()
{
    Node::create();
    if (!m_font.empty())
    {
        char font[64];
        sprintf(font, "%s-%d", m_font.c_str(), m_font_size);
        font_id = (kFont)const_hash(font);
        m_text_mesh.create();
        m_text_mesh.update(font_id, m_text.c_str());
        SetSize(m_text_mesh.bb);
    }
}

void NodeText::set_font(kFont fontID)
{
    font_id = fontID;
    m_text_mesh.create();
    m_text_mesh.update(font_id, m_text.c_str());
    SetSize(m_text_mesh.bb);
}

void NodeText::restore_context()
{
    Node::restore_context();
    create();
}

void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
{
    Node::parse_attributes(ka, attr);
    switch (ka)
    {
    case kAttribute::TextWrapWidth:
        m_text_mesh.max_width = attr->IntValue();
        break;
    case kAttribute::Text:
        m_text = unescape(attr->Value());
        break;
    case kAttribute::FontFace:
        m_font = attr->Value();
        break;
    case kAttribute::FontSize:
        m_font_size = attr->IntValue();
        break;
    case kAttribute::Color:
    {
        glm::vec4 pad;
        int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
        if (n == 1)
            m_color = glm::vec4(pad.x);
        else
            m_color = pad;
        break;
    }
    default:
        break;
    }
}

void NodeText::set_text(const char* s)
{
    m_text = s;
    m_text_mesh.update(font_id, s);
    SetSize(m_text_mesh.bb);
}

void NodeText::set_text_format(const char* fmt, ...)
{
    static char buffer[4096];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buffer, sizeof(buffer), fmt, args);
    va_end(args);
    m_text = buffer;
    m_text_mesh.update(font_id, buffer);
    SetSize(m_text_mesh.bb);
}

void NodeText::draw()
{
    glm::mat4 pos = glm::translate(glm::vec3(glm::floor(m_pos), 0));
    m_mvp = m_proj * pos;
    ShaderManager::use(kShader::Font);
    ShaderManager::u_int(kShaderUniform::Tex, 0);
    ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
    ShaderManager::u_vec4(kShaderUniform::Col, m_color);
    glEnable(GL_BLEND);
    m_text_mesh.draw();
    glDisable(GL_BLEND);
}
