#include "Controllable.hpp"

Controllable::Controllable(GLFWwindow *window, const InputMap& inputs, const Controllable::options& opt): position(), window(window), inputs(inputs),  o(opt){ }
Controllable::~Controllable() { }

Controllable::axis Controllable::getAxis() const {
    Controllable::axis a;
    // Direction : Spherical coordinates to Cartesian coordinates conversion
    a.direction = getDirection();

    // Right vector
    a.right = glm::vec3(sin(HorizontalAngle - 3.14f / 2.0f), 0, cos(HorizontalAngle - 3.14f / 2.0f));

    // Up vector
    a.up = glm::cross(a.right, a.direction);
    return a;
}

void Controllable::capture(bool captureMouse, bool captureKeys, float deltaTime) {
	// Get mouse position
	if(captureMouse) {
		int viewportX, viewportY;
		glfwGetWindowSize(window, &viewportX, &viewportY);
		if(capturingMouse) {
			double xPos, yPos;
			glfwGetCursorPos(window, &xPos, &yPos);

			// Compute new orientation
			HorizontalAngle += o.sensibility * 0.0001f * float(viewportX / 2 - xPos);
			VerticalAngle += o.sensibility * 0.0001f * float(viewportY / 2 - yPos);
		} else {
			glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
			capturingMouse = true;
		}
		// Reset mouse position for next frame
		glfwSetCursorPos(window, viewportX / 2, viewportY / 2);
	} else if (capturingMouse) {
		glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
		capturingMouse = false;
	}

    const auto axis = getAxis();

    velocity = glm::vec3(0);
    if(captureKeys) {
		// Move forward
		if (inputs.isDown(Input::Forward)) {
			velocity += axis.direction;
		}
		// Move backward
		if (inputs.isDown(Input::Backward)) {
            velocity -= axis.direction;
        }
		// Strafe right
		if (inputs.isDown(Input::Right)) {
            velocity += axis.right;
        }
		// Strafe left
		if (inputs.isDown(Input::Left)) {
            velocity -= axis.right;
        }
		// Move up
		if (inputs.isDown(Input::Up)) {
            velocity += axis.up;
        }
		// Move down
		if (inputs.isDown(Input::Down)) {
            velocity -= axis.up;
        }
        if(velocity != glm::vec3(0)) {
		    velocity = glm::normalize(velocity) * deltaTime * o.speed;
        }
	}
}