#include "scenepicker.h"

#include "engine.h"
#include "guitools.h"
#include "scene/scenetree.h"
#include "scene/playercharacternode.h"

#include <SparrowRenderer/parametricmesh.h>
#include <SparrowRenderer/pbrmaterial.h>
#include <SparrowRenderer/camera.h>

#include <imgui/imgui.h>

#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <BulletDynamics/Character/btKinematicCharacterController.h>

Mesh* ScenePicker::generateMesh()
{
    SphereGenerator generator;
    PBRMaterial* mat = new PBRMaterial();
    mat->albedo = glm::vec3(1, 0, 0); // red
    mat->emission = glm::vec3(0.3, 0, 0); // emits some red
    mat->metallic = 0.6f;
    mat->roughness = 0.3f; // quite shiny
    Mesh* m = generator.generateGeodesicMesh(mat, 2, 0.3f);
    m->computeNormals();
    m->setName("scenePicker");
    m->initGL();
    return m;
}

ScenePicker::ScenePicker() :
    MeshNode(generateMesh()),
    m_pickSucceeded(false)
{
}

ScenePicker::~ScenePicker()
{
    delete m_geometry.mesh->getMaterial();
    delete m_geometry.mesh;
}

void ScenePicker::update()
{
    pick();

    bool isEnabled = true;
    ImGui::Begin("Picker", &isEnabled);
    if(m_pickSucceeded)
    {
        ImGui::Text("Intersection : ( %.3f, %.3f, %.3f )", m_pickedPos.x, m_pickedPos.y, m_pickedPos.z);
        if(!isVisible()) setVisible(m_pickSucceeded);
    }
    else
    {
        ImGui::Text("No intesection");
        if(isVisible()) setVisible(m_pickSucceeded);
    }
    //        if(ImGui::Button("Teleport"))
        //move player to target coordinate
    ImGui::End();

    if(!isEnabled)
        getEngine().getGuiTools()->togglePicker();
}

void ScenePicker::pick()
{
    FirstPersonCamera* cam = dynamic_cast<FirstPersonCamera*>(getEngine().getScene()->getCamera());
    if(cam != nullptr)
    {
        glm::vec3 dir_cam = cam->getDirection()*100;
        btVector3 start(cam->getEyePosition().x, cam->getEyePosition().y, cam->getEyePosition().z);
        btVector3 end = start;
        end += btVector3(start.x() + dir_cam.x, start.y() + dir_cam.y, start.z() + dir_cam.z);
        btCollisionWorld::ClosestRayResultCallback RayCallback(start, end);
        getEngine().getPhysics()->rayTest(start,end,RayCallback);

        m_pickSucceeded = RayCallback.hasHit();
        if(m_pickSucceeded)
        {
            btVector3 target = RayCallback.m_hitPointWorld;
            m_pickedPos = glm::vec3(target.x(), target.y(), target.z());
            m_geometry.modelMatrix = glm::translate(glm::mat4(), m_pickedPos);
        }
    }
    else
        m_pickSucceeded = false;
}

