#include "textinputnode.h"

#include <iostream>

#include "SparrowInput/input.h"

#include "engine.h"
#include "tools/font.h"
#include "resourcemanager.h"

TextInputNode::TextInputNode(glm::vec2 dimension):
    m_dimension(dimension),
    m_hasFocus(false),
    m_font_size(16.f),
    m_text_mesh(nullptr),
    m_text(""),
    m_text_updated(false),
    m_text_color(glm::vec3(1,1,1)),
    m_cursor_mesh(nullptr),
    m_cursor_pos(0),
    m_cursor_pos_updated(false),
    m_move_cursor_left(NO_ACTION),
    m_move_cursor_right(NO_ACTION),
    m_callback(nullptr),
    m_tab_callback(nullptr)
{
  //  Font *shellfont = RESOURCE_GET(Font,"shellfont");
    Mesh* mesh = new Mesh();
    mesh->addRectangle2D(glm::vec2(0),glm::vec2(2, m_font_size));
    PBRMaterial* mat = new PBRMaterial();
    mat->albedo = glm::vec3(1,1,1);
    mesh->setMaterial(mat);
    mesh->setDepth(30);
    mesh->initGL();
    m_cursor_mesh = new MeshNode(mesh,false);
    addChild(m_cursor_mesh);
}

void TextInputNode::update()
{
    if(!m_hasFocus) return;

    std::wstring text = getEngine().getInput()->getText();

    auto input = getEngine().getInput();
    for(auto action : input->getActions()){
        if (action.action == m_move_cursor_left){
            if (m_cursor_pos > 0){
                m_cursor_pos--;
                m_cursor_pos_updated=true;
            }
        }
        else if(action.action == m_move_cursor_right){
            if(m_cursor_pos < m_text.length()){
                m_cursor_pos++;
                m_cursor_pos_updated=true;
            }
        }
    }

    for(unsigned int i = 0 ; i < text.length() ; i++){
        char c = text[i];
        switch(c){
        case 8:
            if(m_cursor_pos > 0)
                m_text.erase(--m_cursor_pos,1);
            m_text_updated = true;
            m_cursor_pos_updated=true;
            break;
        case 13:
            if (!m_text.empty())
            {
                if(m_callback)
                    m_callback->exec();
                m_text_updated = true;
                m_cursor_pos = 0;
                m_cursor_pos_updated=true;
            }
            break;
        case 9:
            if (!m_text.empty())
            {
                if(m_tab_callback)
                    m_tab_callback->exec();
                m_text_updated = true;
                m_cursor_pos_updated=true;
            }
            break;
        case 127:
            m_text.erase(m_cursor_pos,1);
            m_text_updated = true;
            break;
        default:
            m_text.insert(m_cursor_pos++,std::string(1,c));
            m_text_updated = true;
            m_cursor_pos_updated=true;
        }
    }
    if(m_cursor_pos_updated)
        updateCursorMesh();

    if(m_text_updated)
        updateTextMesh();

    GUINode::update();
}

void TextInputNode::updateCursorMesh(){
    Font *shellfont = RESOURCE_GET(Font,"shellfont");
    m_cursor_mesh->moveTo2D(glm::vec2(m_cursor_pos*shellfont->getXAdvance()*(m_font_size/shellfont->getLineHeight()),0));
    m_cursor_pos_updated = false;
}

void TextInputNode::updateTextMesh(){
    Font *shellfont = RESOURCE_GET(Font,"shellfont");
    if(m_text_mesh){
        this->removeChild(m_text_mesh);
        delete(m_text_mesh);
    }
    m_text_mesh = shellfont->getTextNode(m_text,m_text_color,m_font_size,false);
    if(m_text_mesh){
        m_text_mesh->setTransform(glm::mat4());
        m_text_mesh->setDepth(15);
        this->addChild(m_text_mesh);
        m_text_mesh->setVisible(true);
    }
    m_text_updated = false;
}

void TextInputNode::setFocus(bool focus)
{
    m_hasFocus = focus;
    m_cursor_mesh->setVisible(focus);
}

void TextInputNode::setText(std::string text){
    m_text = text;
    m_text_updated = true;
    m_cursor_pos = text.length();
    m_cursor_pos_updated = true;
}

void TextInputNode::setTextColor(glm::vec3 color)
{
    m_text_color = color;
}

std::string TextInputNode::getText()
{
    return m_text;
}

