#ifndef ENGINE_H
#define ENGINE_H

#include <iostream>
#include <vector>
#include <filesystem>   // C++17 filesystem
#include <string>
#include <fstream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_glfw.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Components/Component.h"
#include "Components/Camera.h"

// Forward declaration of Entity.
class Entity;

class Engine {
public:
    // Main window.
    static GLFWwindow* window;

    // Initializes GLFW, GLEW, and sets up the main window and offscreen framebuffer.
    static bool Init();
    // Returns the main GLFW window.
    static GLFWwindow* GetWindow();
    static GLuint GetShader();

    // Clean up resources and shutdown GLFW.
    static void Shutdown();

    // Offscreen render function that uses the provided camera parameters and renders the scene
    // (with entities) offscreen. Returns its color attachment as an ImTextureID.
    static ImTextureID RenderScene(const glm::mat4 &view, const glm::mat4 &projection, const glm::vec3 &viewPos, const std::vector<Entity*>& entities);

    // Resizes the offscreen framebuffer to the given dimensions.
    static void ResizeFramebuffer(int width, int height);

    // Retrieves the final rendered texture.
    static ImTextureID GetFinalRenderingTexture();

private:
    // Offscreen framebuffer and its attachments.
    static GLuint framebuffer;
    static GLuint colorTexture;
    static GLuint depthRenderbuffer;
    // Shader program used for rendering the scene.
    static GLuint shaderProgram;

    static GLuint skyboxShaderProgram;
    static GLuint skyboxVAO, skyboxVBO, skyboxEBO;
    static GLuint skyboxCubemap;

    // Rotation angle (if needed for animated models).
    static float rotationAngle;
    // Current offscreen framebuffer dimensions.
    static int fbWidth;
    static int fbHeight;



    // Helper function to compile and link shaders.
    static GLuint CompileShader(const char* vertexSrc, const char* fragmentSrc);
    // Sets up common scene resources (e.g. loading the scene shader).
    static bool SetupScene();
};

#endif // ENGINE_H