// title_scene.hpp - Escena de títol en 3D real
// © 2026 JailDesigner
//
// Clon de `TitleScene` (2D) que substitueix `Graphics::Starfield` per
// `Graphics::Starfield` i `Title::ShipAnimator` per `Title::ShipAnimator`,
// afegint una `Graphics::Camera3D` que projecta l'escena en perspectiva real.
// Tot el bloc d'overlay 2D (logo "ORNI ATTACK!", "PRESS START TO PLAY", peu
// "JAILGAMES + copyright") es manté idèntic.
//

#pragma once

#include <SDL3/SDL.h>

#include <array>
#include <cstdint>
#include <memory>
#include <vector>

#include "core/graphics/camera3d.hpp"
#include "core/graphics/shape.hpp"
#include "core/graphics/starfield.hpp"
#include "core/graphics/vector_text.hpp"
#include "core/input/input_types.hpp"
#include "core/rendering/sdl_manager.hpp"
#include "core/system/game_config.hpp"
#include "core/system/scene.hpp"
#include "core/system/scene_context.hpp"
#include "core/types.hpp"
#include "game/title/ship_animator.hpp"

class TitleScene final : public Scene {
   public:
    explicit TitleScene(SDLManager& sdl, SceneManager::SceneContext& context);
    ~TitleScene() override;

    void handleEvent(const SDL_Event& event) override;
    void update(float delta_time) override;
    void draw() override;
    [[nodiscard]] auto isFinished() const -> bool override;

   private:
    enum class TitleState : std::uint8_t {
        STARFIELD_FADE_IN,
        STARFIELD,
        MAIN,
        PLAYER_JOIN_PHASE,
        BLACK_SCREEN,
    };

    struct LetraLogo {
        std::shared_ptr<Graphics::Shape> shape;
        Vec2 position;
        float ancho;
        float altura;
        float offset_centre;
    };

    SDLManager& sdl_;
    SceneManager::SceneContext& context_;
    GameConfig::MatchConfig match_config_;
    Graphics::VectorText text_;
    std::unique_ptr<Graphics::Camera3D> camera_;
    std::unique_ptr<Graphics::Starfield> starfield_;
    std::unique_ptr<Title::ShipAnimator> ship_animator_;
    TitleState estat_actual_{TitleState::STARFIELD_FADE_IN};
    float temps_acumulat_{0.0F};

    std::vector<LetraLogo> lletres_orni_;
    std::vector<LetraLogo> lletres_attack_;
    float y_attack_dinamica_{0.0F};

    std::vector<LetraLogo> lletres_jailgames_;

    float temps_animacio_{0.0F};
    std::vector<Vec2> posicions_originals_orni_;
    std::vector<Vec2> posicions_originals_attack_;

    float temps_estat_main_{0.0F};
    bool animacio_activa_{false};
    float factor_lerp_{0.0F};

    // Progresos de la intro coreografiada al state MAIN.
    float intro_logo_progress_{0.0F};
    float intro_jailgames_progress_{0.0F};
    float intro_copyright_progress_{0.0F};
    bool press_start_visible_{false};
    bool ships_intro_launched_{false};

    static constexpr float BRIGHTNESS_STARFIELD = 1.2F;
    static constexpr float DURACIO_FADE_IN = 3.0F;
    static constexpr float DURACIO_INIT = 4.0F;
    static constexpr float DURACIO_TRANSITION = 2.5F;
    static constexpr float ESPAI_ENTRE_LLETRES = 10.0F;
    static constexpr float BLINK_FREQUENCY = 3.0F;
    static constexpr float DURACIO_BLACK_SCREEN = 2.0F;
    static constexpr int MUSIC_FADE = 1500;

    static constexpr float ORBIT_AMPLITUDE_X = 4.0F;
    static constexpr float ORBIT_AMPLITUDE_Y = 3.0F;
    static constexpr float ORBIT_FREQUENCY_X = 0.8F;
    static constexpr float ORBIT_FREQUENCY_Y = 1.2F;
    static constexpr float ORBIT_PHASE_OFFSET = 1.57F;

    static constexpr float SHADOW_DELAY = 0.5F;
    static constexpr float SHADOW_BRIGHTNESS = 0.4F;
    static constexpr float SHADOW_OFFSET_X = 2.0F;
    static constexpr float SHADOW_OFFSET_Y = 2.0F;

    static constexpr float DURACIO_LERP = 2.0F;

    // Càmera 3D: FOV vertical en radians.
    static constexpr float CAMERA_FOV_Y_RAD = 1.0472F;  // 60°

    void updateLogoAnimation(float delta_time);
    static auto checkSkipButtonPressed() -> bool;
    auto checkStartGameButtonPressed() -> bool;
    void initTitle();
    void inicialitzarJailgames();
    void dibuixarPeuTitol(float spacing) const;

    void updateStarfieldFadeInState(float delta_time);
    void updateStarfieldState(float delta_time);
    void updateMainState(float delta_time);
    void updatePlayerJoinPhaseState(float delta_time);
    void updateBlackScreenState(float delta_time);
    void handleSkipInput();
    void handleStartInput();
    void triggerExitForJoinedPlayers(bool p1_was_active, bool p2_was_active, const char* log_prefix);
};
