#include <object/components/boxcollider.hpp>
#include <object/entity.hpp>
#include <renderer/texture.hpp>

#include <algorithm>

namespace Game::Object::Components {
    BoxCollider::BoxCollider(const BoxCollider& other) : Component(other) {
        LOG("Kopiran BoxCollider komponenta: " << mName);
    }

    BoxCollider& BoxCollider::operator=(const BoxCollider& other) {
        if (this != &other) {
            Component::operator=(other);
        }
        return *this;
    }

    BoxCollider::BoxCollider(BoxCollider&& other) noexcept : Component(std::move(other)) {
        LOG("Premaknjena BoxCollider komponenta: " << mName);
    }

    BoxCollider& BoxCollider::operator=(BoxCollider&& other) noexcept {
        if (this != &other) {
            Component::operator=(std::move(other));
        }
        return *this;
    }

    BoxCollider::~BoxCollider() = default;

    void BoxCollider::start(Object::Entity* thisEntity) {
        // Initialization code for the box collider can go here
    }

    void BoxCollider::update(float deltaTime, Object::Entity* thisEntity) {
        // Collision detection and response logic can go here
        (void)deltaTime;

        if (!thisEntity) {
            return;
        }

        // Make box bounds
        Transform* transform = thisEntity->getTransform();
        if (!transform) {
            return;
        }

        float width = 1.f;
        float height = 1.f;
        if (const auto tex = thisEntity->getTexture()) {
            width = tex->getWidth() * transform->scaleX * UNIVERSAL_SCALE_COEFFICIENT * mScale;
            height = tex->getHeight() * transform->scaleY * UNIVERSAL_SCALE_COEFFICIENT * mScale;
        } else {
            width = transform->scaleX * UNIVERSAL_SCALE_COEFFICIENT * mScale;
            height = transform->scaleY * UNIVERSAL_SCALE_COEFFICIENT * mScale;
        }
        width = std::max(1.f, width);
        height = std::max(1.f, height);

        // Entity rendering uses top-left transform coordinates; collider must match that space.
        float left = transform->x;
        float right = transform->x + width;
        float top = transform->y;
        float bottom = transform->y + height;

        mBounds = {left, right, top, bottom};

        // Check for collisions with other entities that have box colliders
        // For simplicity, just check each
        std::unordered_set<Entity*> currentCollisions;
        std::vector<Entity*> entities = State::GameState::getInstance().getEntitiesSnapshot();
        for (Entity* other : entities) {
            if (!other || other == thisEntity || !other->isActive()) continue; // Don't check collision with self/inactive entities
            BoxCollider* otherCollider = other->getComponent<BoxCollider>();
            if (!otherCollider || !otherCollider->isActive()) continue; // No active collider, skip
            BoxColliderBounds otherBounds = otherCollider->getBounds();
            bool isOverlapping = left < otherBounds.right && right > otherBounds.left && top < otherBounds.bottom && bottom > otherBounds.top;
            if (isOverlapping) {
                currentCollisions.insert(other);
                // Collision detected
                if (!mCollidingWith.contains(other)) {
                    thisEntity->onCollisionEnter(other);
                    if (!thisEntity->isActive()) {
                        return;
                    }
                    //other->onCollisionEnter(thisEntity);
                } else {
                    thisEntity->onCollisionStay(other);
                    if (!thisEntity->isActive()) {
                        return;
                    }
                    //other->onCollisionStay(thisEntity);
                }
            }
        }

        for (Entity* wasColliding : mCollidingWith) {
            if (!currentCollisions.contains(wasColliding)) {
                thisEntity->onCollisionExit(wasColliding);
                //wasColliding->onCollisionExit(thisEntity);
            }
        }

        mCollidingWith = std::move(currentCollisions);
    }
}