#include "basicEditorCamera.hpp"
#include "elements/Transformable.hpp"
#include "utils/Time.hpp"
#include "BehaviourScripts/Camera.hpp"
#include <cmath>

void TSE::EDITOR::basicEditorCamera::OnUpdate()
{
    auto euler = baseObject->GetEuler();
    auto finalrot = rotDelta * rotationMultiplier * Time::deltaTime();
    rotDelta = Vector2::zero;
    if(mouseInputEnabled)
    {
        euler.y += finalrot.x;  
        euler.x += finalrot.y;
    }
    baseObject->SetEuler(euler);

    Vector3 move;

    if(keyInputEnabled && SceneView::IsHovered)
        delta = delta + keydelta * keyMultiplier;

    move = baseObject->right() * delta.x;
    move = move + baseObject->up() * delta.y;
    move = move + baseObject->forward() * delta.z;

    delta = Vector3::zero;

    
    move = move * movementMultiplier * Time::deltaTime();

    baseObject->position = baseObject->position + move;
}

void TSE::EDITOR::basicEditorCamera::Start()
{
    ICursorHandler::Enable();
    IKeyInputHandler::Enable();
}

void TSE::EDITOR::basicEditorCamera::OnKeyDown(const Key &key, const Modifier &mods)
{
    switch (key)
    {
    case Key::LeftShift:
        isShiftPressed = true;
        break;
    case Key::W:
        keydelta = keydelta + Vector3::forward * keyMultiplier;
        break;
    case Key::A:
        keydelta = keydelta + Vector3::left * keyMultiplier;
        break;
    case Key::S:
        keydelta = keydelta + Vector3::back * keyMultiplier;
        break;
    case Key::D:
        keydelta = keydelta + Vector3::right * keyMultiplier;
        break;
    case Key::E:
        keydelta = keydelta + Vector3::up * keyMultiplier;
        break;
    case Key::Q:
        keydelta = keydelta + Vector3::down * keyMultiplier;
        break;
    
    default:
        return;
    }
}

void TSE::EDITOR::basicEditorCamera::OnKeyUp(const Key &key, const Modifier &mods)
{
    switch (key)
    {
    case Key::LeftShift:
        isShiftPressed = false;
        break;
    case Key::W:
        keydelta = keydelta - Vector3::forward * keyMultiplier;
        break;
    case Key::A:
        keydelta = keydelta - Vector3::left * keyMultiplier;
        break;
    case Key::S:
        keydelta = keydelta - Vector3::back * keyMultiplier;
        break;
    case Key::D:
        keydelta = keydelta - Vector3::right * keyMultiplier;
        break;
    case Key::E:
        keydelta = keydelta - Vector3::up * keyMultiplier;
        break;
    case Key::Q:
        keydelta = keydelta - Vector3::down * keyMultiplier;
        break;
    
    default:
        return;
    }
}

void TSE::EDITOR::basicEditorCamera::OnMouseButtonDown(const MouseBtn &btn, const Modifier &mods)
{
    if(!mouseInputEnabled) return;
    switch (btn)
    {
    case MouseBtn::RightMouse:
        holdingRightClick = true;
        break;
    case MouseBtn::LeftMouse:
        holdingLeftClick = true;
        break;
    }
}

void TSE::EDITOR::basicEditorCamera::OnMouseButtonUp(const MouseBtn &btn, const Modifier &mods)
{
    if(!mouseInputEnabled) return;
    switch (btn)
    {
    case MouseBtn::RightMouse:
        holdingRightClick = false;
        break;
    case MouseBtn::LeftMouse:
        holdingLeftClick = false;
        break;
    
    default:
        return;
    }
}

void TSE::EDITOR::basicEditorCamera::OnMousePosition(const Vector2 &pos)
{
    if(!mouseInputEnabled || !SceneView::IsHovered) return;
    if(isShiftPressed && holdingLeftClick)
    {
        auto tmp = pos - lastMousepos;
        tmp.x *= -1;
        delta = delta + tmp;
    }
    else if(holdingRightClick)
    {
        rotDelta = rotDelta + (pos - lastMousepos);
    }
    lastMousepos = pos;
}

void TSE::EDITOR::basicEditorCamera::OnMouseScroll(const Vector2 &mdelta)
{
    if(!mouseInputEnabled || !SceneView::IsHovered) return;
    Camera* editorCam = (Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA);
    float scale = editorCam->GetRenderScale();

    scale += mdelta.y * zoomMultiplier;
    scale = std::clamp(scale, zoomMin, zoomMax);

    editorCam->SetRenderScale(scale);
}

void TSE::EDITOR::basicEditorCamera::CustomDraw(const bool &debug)
{
    ImGui::DragFloat("Rotation Speed", &rotationMultiplier, 0.1f);
    ImGui::DragFloat("Movement Speed", &movementMultiplier, 0.1f);
    ImGui::DragFloat("Zoom Speed", &zoomMultiplier, 0.1f);
    ImGui::DragFloat("key Speed", &keyMultiplier, 0.1f);

    ImGui::Checkbox("Keybord Input", &keyInputEnabled);
    ImGui::Checkbox("Mouse Input", &mouseInputEnabled);
}
