#include <pch.hpp>

#include "open_engine/orthographic_camera_controller.hpp"
#include "open_engine/events/application_event.hpp"
#include "open_engine/events/event.hpp"
#include "open_engine/events/mouse_event.hpp"
#include "open_engine/core/time.hpp"
#include "open_engine/input/keycodes.hpp"
#include "open_engine/input/input_system.hpp"
#include "open_engine/orthographic_camera.hpp"

#include <glm/fwd.hpp>

namespace OpenEngine {
    OrthographicCameraController::OrthographicCameraController(float ratio, float zoom = 1.0f)
        : aspect_ratio(ratio), zoom(zoom),
        camera(-aspect_ratio * zoom, aspect_ratio * zoom, -zoom, zoom)
    {
    }

    void OrthographicCameraController::Translate(const glm::vec3& vector)
    {
        float velocity = translation_speed * Time::Get().DeltaTime();
        camera_position += vector * velocity;
    }

    void OrthographicCameraController::Rotate(float speed)
    {
        float multiple = rotation_speed * Time::Get().DeltaTime();
        camera_rotation += speed * multiple;
    }

    void OrthographicCameraController::OnUpdate()
    {
        if (Input::IsKeyPressed(OE_KEY_W))
            Translate({0, -1, 0});
        if (Input::IsKeyPressed(OE_KEY_A))
            Translate({1, 0, 0});
        if (Input::IsKeyPressed(OE_KEY_S))
            Translate({0, 1, 0});
        if (Input::IsKeyPressed(OE_KEY_D))
            Translate({-1, 0, 0});

        if (rotation) {
            if (Input::IsKeyPressed(OE_KEY_Q))
                Rotate(10);
            if (Input::IsKeyPressed(OE_KEY_E))
                Rotate(-10);

            camera.SetRotation(camera_rotation);
        }

        camera.SetPosition(camera_position);
    }
    void OrthographicCameraController::OnEvent(Event& e)
    {
        EventDispatcher dispatcher(e);
        dispatcher.Dispatch<MouseScrolledEvent>(BIND_EVENT_FN(OrthographicCameraController::OnMouseScrolled));
        dispatcher.Dispatch<WindowResizeEvent>(BIND_EVENT_FN(OrthographicCameraController::OnWindowResized));
    }

    bool OrthographicCameraController::OnMouseScrolled(MouseScrolledEvent& e)
    {
        zoom -= e.GetYOffset() * 0.25f;
		zoom = std::max(zoom, 0.25f);
		camera.SetProjection(-aspect_ratio * zoom, aspect_ratio * zoom, -zoom, zoom);

        return false;
    }
    bool OrthographicCameraController::OnWindowResized(WindowResizeEvent& e)
    {
        aspect_ratio = (float)e.GetWidth() / (float)e.GetHeight();
        camera.SetProjection(-aspect_ratio * zoom, aspect_ratio * zoom, -zoom, zoom);

        return false;
    }
}
