#include "game/entities/door.hpp"

#include "core/rendering/sprite/animated_sprite.hpp"  // Para AnimatedSprite
#include "core/resources/resource_cache.hpp"          // Para Resource

// Constructor: carga la animación y posiciona la puerta. Si start_opened es
// true, la puerta se crea ya abierta (estado OPENED, animación "opened"); en
// caso contrario, se crea cerrada (estado CLOSED, animación "closed") y
// activa el flag BLOCKS_PLAYER del SolidActor para que los sweeps del
// SolidActorManager la vean como muro.
Door::Door(const Data& data, bool start_opened)
    : sprite_(std::make_shared<AnimatedSprite>(Resource::Cache::get()->getAnimationData(data.animation_path))),
      id_(data.id),
      state_(start_opened ? State::OPENED : State::CLOSED) {
    sprite_->setPosX(data.x);
    sprite_->setPosY(data.y);
    sprite_->setCurrentAnimation(start_opened ? "opened" : "closed");
    aabb_ = sprite_->getRect();
    if (!start_opened) {
        flags_ = BLOCKS_PLAYER;
    }
}

// Pinta la puerta en pantalla
void Door::render() {
    sprite_->render();
}

// Avanza la animación. Solo OPENING anima de verdad; CLOSED y OPENED son
// frames estáticos. Cuando la animación de OPENING termina, transiciona a
// OPENED, fija el frame final, limpia el flag BLOCKS_PLAYER (los sweeps
// del SolidActorManager dejan de verla como muro) y marca just_opened_
// para que el DoorManager persista el estado abierto en DoorTracker.
void Door::update(float delta_time) {
    if (is_paused_) {
        return;
    }

    if (state_ == State::OPENING) {
        sprite_->animate(delta_time);
        if (sprite_->animationIsCompleted()) {
            state_ = State::OPENED;
            sprite_->setCurrentAnimation("opened");
            flags_ = 0;  // Deja de bloquear al Player
            just_opened_ = true;
        }
    }
}

// Posición actual (para registrar el estado abierto en DoorTracker)
auto Door::getPos() const -> SDL_FPoint {
    return SDL_FPoint{.x = sprite_->getX(), .y = sprite_->getY()};
}

// Transición CLOSED → OPENING: cambia el estado y arranca la animación de apertura
void Door::startOpening() {
    if (state_ != State::CLOSED) {
        return;
    }
    state_ = State::OPENING;
    sprite_->setCurrentAnimation("opening");
    sprite_->resetAnimation();
}

// Flag one-shot: devuelve true exactamente una vez después de transicionar a OPENED
auto Door::justOpened() -> bool {
    if (just_opened_) {
        just_opened_ = false;
        return true;
    }
    return false;
}

#ifdef _DEBUG
// Mueve la puerta a la posición indicada (sprite + AABB del SolidActor).
// Usado por el editor; el DoorManager::moveDoor se encarga del bookkeeping
// de registro en el SolidActorManager.
void Door::setPosition(float x, float y) {
    sprite_->setPosX(x);
    sprite_->setPosY(y);
    aabb_ = sprite_->getRect();
}
#endif
