#include <controls/control_hub.hpp>

ControlHub::ControlHub()
{
    auto orbit_cam = std::make_shared<OrbitCameraController>();
    auto free_cam = std::make_shared<FreeFlyCameraController>();

    cam_controls.emplace_back(orbit_cam);
    cam_controls.emplace_back(free_cam);

    obj_controls.emplace_back(std::make_shared<ObjectController>());

    active_camera_type = cam_controls[0];
    object_ctrl_type = obj_controls[0];
}

void ControlHub::addCamController(cam_control_ptr cam_controller)
{
    cam_controls.emplace_back(cam_controller);
}
void ControlHub::addObjController(obj_control_ptr obj_controller)
{
    obj_controls.emplace_back(obj_controller);
}
void ControlHub::bindCamera(node_ptr node)
{
    active_camera_type->setNode(node);
}
void ControlHub::bindObject(node_ptr node)
{
    object_ctrl_type->setNode(node);
}
/* Object movement now works only for one object */
void ControlHub::processInput(const scene_ptr &scene, const osi::Keyboard &keyboard, const osi::Timer &timer, const osi::Window &window)
{
    if (!window.has_keyboard_focus())
        return;

    if (keyboard.down().contains("T") && scene->getSelection())
    {
        for (auto &controller : obj_controls)
        {
            controller->setup(timer.dt(), scene->getSelection());
            controller->keyboardMove(keyboard.down(), keyboard.just_released());
        }
    }
    else
    {
        active_camera_type->setStep(timer.dt());
        active_camera_type->keyboardMove(keyboard.down(), keyboard.just_pressed());

        auto selection = scene->getSelection();
        if (selection && keyboard.just_pressed().contains("C"))
            active_camera_type->setTarget(selection);
    }

    if (keyboard.just_pressed().contains("V"))
        scene->getActiveCameras()[0].lock()->setPerspective(!scene->getActiveCameras()[0].lock()->isPerspective());
}
void ControlHub::processMouse(const osi::Mouse &mouse, const osi::Window &window, bool &editor_running)
{
    if (window.is_minimized()
        || !window.is_mouse_in_window())
        return;

    active_camera_type->mouseMove(mouse, window, editor_running);
}

void ControlHub::rotate_cam(glm::vec3 rotation)
{
    active_camera_type->rotate(rotation);
}

void ControlHub::rotate_obj(glm::vec3 rotation)
{
    object_ctrl_type->rotate(rotation);
}

void ControlHub::teleport_cam(glm::vec3 position)
{
    active_camera_type->teleport(position);
}

void ControlHub::teleport_obj(glm::vec3 position)
{
    object_ctrl_type->teleport(position);
}
