#ifndef CONTROL_HUB_INCLUDED
#define CONTROL_HUB_INCLUDED

#include <controls/cam_control.hpp>
#include <controls/obj_control.hpp>
#include <edit/scene.hpp>
#include <osi/keyboard.hpp>
#include <osi/mouse.hpp>
#include <osi/timer.hpp>
#include <osi/window.hpp>
#include <utils/math.hpp>

#include <memory>

using cam_control_ptr = std::shared_ptr<CameraController>;
using obj_control_ptr = std::shared_ptr<ObjectController>;
using scene_ptr = std::shared_ptr<Scene>;

class ControlHub
{
    std::vector<cam_control_ptr> cam_controls;
    std::vector<obj_control_ptr> obj_controls;

    cam_control_ptr active_camera_type;
    obj_control_ptr object_ctrl_type;

public:
    ControlHub();

    obj_control_ptr getActiveObjCtrl() { return object_ctrl_type; }
    cam_control_ptr getActiveCamCtrl() { return active_camera_type; }

    void addCamController(cam_control_ptr cam_controller);
    void addObjController(obj_control_ptr obj_controller);

    void bindCamera(node_ptr node);
    void bindObject(node_ptr node);

    void processInput(const scene_ptr &scene, 
                      const osi::Keyboard &keyboard, 
                      const osi::Timer &timer, 
                      const osi::Window &window);
                      
    void processMouse(const osi::Mouse &mouse, 
                      const osi::Window &window, 
                      bool &editor_running);

    /* Methods for manual in-code control */
    void rotate_cam(glm::vec3 rotation);
    void rotate_obj(glm::vec3 rotation);

    void teleport_cam(glm::vec3 position);
    void teleport_obj(glm::vec3 position);    
};

#endif