#pragma once

#include <Core/Application/IApplication.h>
#include <Core/HAL/Display/Display.h>
#include <Core/HAL/DynLib/DynamicLibrary.h>
#include <Core/HotReload/HotReload.h>
#include <Graphics/GraphicsPipeline.h>

namespace Juliet
{
    struct Mesh;
    struct GraphicsTransferBuffer;
    struct GraphicsBuffer;
    struct GraphicsDevice;
    struct Window;
} // namespace Juliet

class JulietApplication : public Juliet::IApplication
{
  protected:
    void Init(Juliet::NonNullPtr<Juliet::Arena> arena) override;
    void Shutdown() override;
    void Update() override;
    bool IsRunning() override;

    Juliet::Window*         GetPlatformWindow() override { return MainWindow; }
    Juliet::GraphicsDevice* GetGraphicsDevice() override { return GraphicsDevice; }

    // Render Lifecycle
    void                            OnPreRender(Juliet::CommandList* cmd) override;
    void                            OnRender(Juliet::RenderPass* pass, Juliet::CommandList* cmd) override;
    Juliet::ColorTargetInfo         GetColorTargetInfo(Juliet::Texture* swapchainTexture) override;
    Juliet::DepthStencilTargetInfo* GetDepthTargetInfo() override;
    Juliet::Camera                  GetDebugCamera() override;

  public:
    void SetAutoCloseFrameCount(int count) { AutoCloseFrameCount = count; }
    int  GetAutoCloseFrameCount() const { return AutoCloseFrameCount; }

  private:
    Juliet::Window*           MainWindow       = {};
    Juliet::GraphicsDevice*   GraphicsDevice   = {};
    Juliet::HotReloadCode     GameCode         = {};
    Juliet::GraphicsPipeline* GraphicsPipeline = {};
    Juliet::Texture*          DepthBuffer      = {};
    Juliet::Arena*            GameArena        = nullptr;
    Juliet::Arena*            GameScratchArena = nullptr;

    int   AutoCloseFrameCount = -1;
    bool  Running             = false;
    float CameraTime          = 0.0f;
};

JulietApplication& GetEditorApplication();
