#pragma once

#include <string>
#include <utils.hpp>
#include <object/transform.hpp>
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <utility>
#include <memory>
#include <renderer/renderer.hpp>

namespace Game::Renderer {
    class Renderer;
    class Texture;
}

namespace Game::Object {
    class Entity {
        public:
            Entity(std::string name, std::shared_ptr<Game::Renderer::Texture> tex, Transform transform) : mName(name), mTex(tex), mTransform(transform), mIsActive(true) { LOG("Created Entity: " << mName); }
            // I will define the copy and move constructors later - just deleted for now
            Entity(const Entity&);
            Entity& operator=(const Entity&);
            Entity(Entity&&) noexcept;
            Entity& operator=(Entity&&) noexcept;
            virtual ~Entity() = 0; // Destructor

            // Start is called when the entity is spawned
            virtual void start() = 0;
            // Update is called every update cycle; deltaTime is the time (in seconds) since the last update call
            virtual void update(float deltaTime) = 0;
            virtual void onWindowResized(int newWidth, int newHeight) {} // Called when the window is resized, with the new width and height in pixels
            virtual void destroyed() {}; // Pre-destruction call
            void render(Game::Renderer::Renderer* renderer, Game::Renderer::RendererConfig config);

            // Setters and getters
            void setTexture(std::shared_ptr<Game::Renderer::Texture> tex) { mTex = tex; }
            void setName(const std::string& name) { mName = name; }
            void setTransform(const Transform& transform) { mTransform = transform; }
            void setActive(bool active) { mIsActive = active; }
            std::shared_ptr<Game::Renderer::Texture> getTexture() { return mTex; }
            std::string getName() { return mName; }
            Transform* getTransform() { return &mTransform; }
            bool isActive() { return mIsActive; }
            int getZIndex() const { return mZIndex; }

        protected:
            std::string mName;
            std::shared_ptr<Game::Renderer::Texture> mTex;
            Transform mTransform;
            bool mIsActive;
            int mZIndex = 0; // For rendering order; higher zIndex renders on top of lower zIndex
            float mTiledScale = 1.f; // Only used if the texture is tiled, to determine how much to scale the texture when rendering (since the entire texture is rendered as a single tile, this is necessary to be able to have different sized tiles)
        private:
    };
}