#include "crDevCamera.h"

#include <imgui.h>

#include "crApp.h"
#include "crCamera.h"
#include "crInputSystem.h"
#include "crMath.h"
#include "crScreenRef.h"

void crDevCamera::Init( crApp* app )
{
    _app = app;
}
void crDevCamera::Cleanup()
{
    _app = nullptr;
}

void crDevCamera::TryRenderPanel()
{
    if( enabled == false )
        return;

    crCamera* camera = _app->camera;

    ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 4.0f, 0.0f ) );
    ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 8.0f, 2.0f ) );

    ImGui::SetNextWindowPos( ImVec2( 10.0f, 50.0f ), ImGuiCond_FirstUseEver );
    ImGui::SetNextWindowSize( ImVec2( 360.0f, 0.0f ), ImGuiCond_FirstUseEver );
    ImGui::SetNextWindowCollapsed( true, ImGuiCond_FirstUseEver );

    if( ImGui::Begin( "Camera", nullptr, ImGuiWindowFlags_NoSavedSettings ) )
    {
        ImGui::Checkbox( "free camera", &_app->inputSys->devCamera );   // mouse orbit / pan / dolly + RMB fly
        ImGui::Separator();

        const float3 eye    = camera->EyePosition();
        const float3 fwd    = camera->Forward();
        const float3 target = camera->Target();
        const float  toDeg  = 180.0f / crMath::PI;

        // pose is what renders; the rig block under it can be stale after SetWorldTransform
        ImGui::Text( "eye      %7.2f %7.2f %7.2f", eye.x, eye.y, eye.z );
        ImGui::Text( "fwd      %7.2f %7.2f %7.2f", fwd.x, fwd.y, fwd.z );

        ImGui::Separator();

        ImGui::Text( "target   %7.2f %7.2f %7.2f", target.x, target.y, target.z );
        ImGui::Text( "yaw      %7.2f deg", camera->Yaw() * toDeg );
        ImGui::Text( "pitch    %7.2f deg", camera->Pitch() * toDeg );

        ImGui::Separator();

        float rollDeg = ( camera->Roll() * toDeg );
        if( ImGui::SliderFloat( "roll (deg)", &rollDeg, -180.0f, 180.0f, "%.1f" ) )
            camera->SetRoll( rollDeg / toDeg );

        float distance = camera->Distance();
        if( ImGui::SliderFloat( "distance", &distance, crCamera::DISTANCE_MIN, crCamera::DISTANCE_MAX, "%.1f", ImGuiSliderFlags_Logarithmic ) )
            camera->SetDistance( distance );

        float fovDeg = ( camera->FovY() * toDeg );
        if( ImGui::SliderFloat( "fov (deg)", &fovDeg, ( crCamera::FOV_Y_MIN * toDeg ), ( crCamera::FOV_Y_MAX * toDeg ), "%.1f" ) )
            camera->SetFovY( fovDeg / toDeg );

        // the reference is compile-time (crScreenRef) — resizing the window is what exercises the fit
        const int2  vp   = camera->Viewport();
        const float grow = crMath::AspectGrowth( ( static_cast<float>( vp.x ) / static_cast<float>( vp.y ) ), crScreenRef::ASPECT );

        ImGui::Text( "ref      %d x %d  (%s)", crScreenRef::WIDTH, crScreenRef::HEIGHT, crScreenRef::OrientationName() );
        ImGui::Text( "grow     %7.2f", grow );
        ImGui::Text( "fov eff  %7.2f deg", camera->EffectiveFovY() * toDeg );

        float clipNear = camera->NearPlane();
        float clipFar  = camera->FarPlane();
        if( ImGui::DragFloatRange2( "clip", &clipNear, &clipFar, 1.0f, 0.01f, 5000.0f, "%.2f" ) )
            camera->SetClip( clipNear, clipFar );

        ImGui::Text( "viewport %d x %d", vp.x, vp.y );
    }
    ImGui::End();

    ImGui::PopStyleVar( 2 );
}
