#ifndef RENDER_SCENE_H
#define RENDER_SCENE_H

#include <DirectXMath.h>
#include <render_type_def.h>

#include "render_object.h"
#include "shared_model.h"

class Shader;
class Scene {
public:
    struct SceneState {
        float yaw = 0.0f;
        float pitch = 0.2f;
        float nearPlane = 0.1f;
        float farPlane = 500.0f;
        float fovY = DirectX::XM_PIDIV4;
        float aspectRatio = 2.0f;
        DirectX::XMFLOAT3 cameraPos{0.0f, 1.0f, -10.0f};
        DirectX::XMFLOAT3 lightDir{-1.0f, -1.0f, 1.0f};

        //[add]
        DirectX::XMFLOAT3 lightColor{1.0f, 1.0f, 1.0f};
        float lightIntensity = 5.0f;

        // [ADD] IBL 接入前的临时环境项。
        DirectX::XMFLOAT3 ambientColor{1.0f, 1.0f, 1.0f};
        float ambientIntensity = 0.03f;

        // [ADD] HDR 光照计算后的曝光参数。
        float exposure = 1.0f;

        // DirectX::XMFLOAT4 baseColor; //[sub] base color属于材质,不再属于scene
    };
    struct alignas(16) SceneData {
        DirectX::XMFLOAT4X4 view;
        DirectX::XMFLOAT4X4 proj;
        DirectX::XMFLOAT4 cameraPos;
        DirectX::XMFLOAT4 lightDirection;
        // DirectX::XMFLOAT4 baseColor; //[sub]
        DirectX::XMFLOAT4 lightColorIntensity;    // [ADD] xyz=color, w=intensity。
        DirectX::XMFLOAT4 ambientColorIntensity;
        DirectX::XMFLOAT4 renderParams; // x=exposure
    };
    static_assert(sizeof(SceneData) % 16 == 0);

public:
    // 场景常数
    explicit Scene(ID3D11Device &device);
    [[nodiscard]] const SceneState *GetSceneState() const { return &m_state; }
    void UpdateCBuffer(ID3D11DeviceContext *ctx);

    // 相机状态
    void SetCameraPos(const DirectX::XMFLOAT3 &pos) noexcept { m_state.cameraPos = pos; }
    void SetCameraYaw(float yaw) noexcept { m_state.yaw = yaw; }
    void SetCameraPitch(float pitch) noexcept {
        if (pitch > 1.5707f) { pitch = 1.5707f; } else if (pitch < -1.5707f) { pitch = -1.5707f; }
        m_state.pitch = pitch;
    }
    void SetCameraAspectRatio(float aspectRatio) noexcept {
        m_state.aspectRatio = aspectRatio;
    }

    [[nodiscard]] DirectX::XMFLOAT3 GetCameraForward() const;
    [[nodiscard]] DirectX::XMMATRIX GetCameraView() const;
    [[nodiscard]] DirectX::XMMATRIX BuildShadowCameraProj(float distance) const; // 计算阴影proj矩阵


    void MoveCameraPos(DirectX::XMFLOAT3 dir, float deltaTime);

    // 场景资源 (RenderObj)
    std::vector<RenderObject *> &GetRenderObjects() noexcept { return ar_RenderObj; }
    int AddRenderObj(SharedModel *model, ID3D11Device *device);

    void SetRenderObjMatrix(int id, const DirectX::XMFLOAT4X4 &matrix) const;
    bool SetRenderObjMaterial(int objId, int meshId, Material *mat) const;

    // [ADD] 光照参数入口。
    void SetDirectionalLight(const DirectX::XMFLOAT3 &direction,
                             const DirectX::XMFLOAT3 &color, float intensity) noexcept;
    void SetAmbientLight(const DirectX::XMFLOAT3 &color, float intensity) noexcept;
    void SetExposure(float exposure) noexcept { m_state.exposure = exposure; }

private:
    bool InitGpuResources(ID3D11Device *device);
    void ComputeCurSceneCB();
    void ComputeViewMatrix(DirectX::XMFLOAT4X4 *pViewMatrix_out) const;
    void ComputeProjMatrix(DirectX::XMFLOAT4X4 *pProjMatrix_out) const;

private:
    DirectX::XMFLOAT3 m_moveForward{}; //以当前摄像机+z为前方的移动速度
    SceneState m_state{}; //本地状态
    SceneData m_CB_Data{}; //GPU资源映射
    Microsoft::WRL::ComPtr<ID3D11Buffer> m_CBuffer{}; //绑到shader的 b0

    // render objects
    std::vector<RenderObject *> ar_RenderObj{}; //场景内被渲染的物体,下标为返回给APP的ID
};




















#endif //RENDER_SCENE_H
