#pragma once

#include "../Config.h"
#include "../../states/State.h"
#include "../container/ServiceContainer.h"
#include <memory>
#include <string>

// Forward declarations
class RenderManager;
class InputManager;
class StateManager;
class AssetManager;
class Game;
class ScoreManager;
class Starfield;
class Starfield3D;
class FontAtlas;
class LineEffect;
class CoopGame;

// Forward declare state classes (top-level, defined under src/states)
class LoadingState;
class MenuState;
class OptionsState;
class LevelSelectorState;
class PlayingState;

/**
 * ApplicationManager - Central coordinator for the entire application lifecycle
 * 
 * Responsibilities:
 * - Initialize and shutdown all subsystems
 * - Coordinate the main application loop
 * - Manage high-level application state
 * - Provide clean separation between main() and application logic
 */
class ApplicationManager {
public:
    ApplicationManager();
    ~ApplicationManager();

    // Core lifecycle methods
    bool initialize(int argc, char* argv[]);
    void run();
    void shutdown();

    // Application state
    bool isRunning() const { return m_running; }
    void requestShutdown() { m_running = false; }

    // Access to managers (for now, will be replaced with dependency injection later)
    RenderManager* getRenderManager() const { return m_renderManager.get(); }
    InputManager* getInputManager() const { return m_inputManager.get(); }
    AssetManager* getAssetManager() const { return m_assetManager.get(); }
    StateManager* getStateManager() const { return m_stateManager.get(); }

    // Service container access
    ServiceContainer& getServiceContainer() { return m_serviceContainer; }

private:
    // Helper used by setupStateHandlers (defined in cpp)
    static void renderLoading(ApplicationManager* app, RenderManager& renderer);
    // Initialization methods
    bool initializeSDL();
    bool initializeManagers();
    bool initializeGame();
    void setupStateHandlers();
    void registerServices();
    
    // Main loop methods
    void processEvents();
    void update(float deltaTime);
    void render();
    
    // Cleanup methods
    void cleanupManagers();
    void cleanupSDL();

    // Core managers
    std::unique_ptr<RenderManager> m_renderManager;
    std::unique_ptr<InputManager> m_inputManager;
    std::unique_ptr<AssetManager> m_assetManager;
    std::unique_ptr<StateManager> m_stateManager;

    // Dependency injection container
    ServiceContainer m_serviceContainer;
    
    // Visual effects
    std::unique_ptr<Starfield3D> m_starfield3D;
    std::unique_ptr<Starfield> m_starfield;

    // Menu / UI state pieces mirrored from main.cpp
    bool m_musicEnabled = true;
    int m_startLevelSelection = 0;
    int m_hoveredButton = -1;
    bool m_showSettingsPopup = false;
    bool m_showHelpOverlay = false;
    bool m_showExitConfirmPopup = false;
    int m_exitPopupSelectedButton = 1; // 0 = YES, 1 = NO
    bool m_isFullscreen = false;
    std::string m_playerName = "PLAYER";
    uint64_t m_loadStartTicks = 0;
    bool m_musicStarted = false;
    bool m_musicLoaded = false;
    int m_currentTrackLoading = 0;
    int m_totalTracks = 0;

    // Persistence (ScoreManager declared at top-level)
    std::unique_ptr<ScoreManager> m_scoreManager;
    // Gameplay pieces
    std::unique_ptr<Game> m_game;
    std::unique_ptr<CoopGame> m_coopGame;
    std::unique_ptr<LineEffect> m_lineEffect;
    
    // DAS/ARR movement timing (from original main.cpp)
    bool m_leftHeld = false;
    bool m_rightHeld = false;
    double m_moveTimerMs = 0.0;
    static constexpr double DAS = 170.0;  // Delayed Auto Shift
    static constexpr double ARR = 40.0;   // Auto Repeat Rate

    // Coop DAS/ARR per player
    bool m_p1LeftHeld = false;
    bool m_p1RightHeld = false;
    bool m_p2LeftHeld = false;
    bool m_p2RightHeld = false;
    double m_p1MoveTimerMs = 0.0;
    double m_p2MoveTimerMs = 0.0;

    // State context (must be a member to ensure lifetime)
    StateContext m_stateContext;
    
    // State objects (mirror main.cpp pattern)
    std::unique_ptr<LoadingState> m_loadingState;
    std::unique_ptr<MenuState> m_menuState;
    std::unique_ptr<OptionsState> m_optionsState;
    std::unique_ptr<LevelSelectorState> m_levelSelectorState;
    std::unique_ptr<PlayingState> m_playingState;
    // Application state
    bool m_running = false;
    bool m_initialized = false;
    
    // Timing
    uint64_t m_lastFrameTime = 0;
    
    // Configuration
    int m_windowWidth = Config::Window::DEFAULT_WIDTH;
    int m_windowHeight = Config::Window::DEFAULT_HEIGHT;
    std::string m_windowTitle = Config::Window::DEFAULT_TITLE;
    
    // Animation state
    float m_logoAnimCounter = 0.0f;
    bool m_helpOverlayPausedGame = false;

    // Intro video playback (in-process via FFmpeg)
    bool m_introStarted = false;
    std::string m_introPath = "assets/videos/spacetris_intro.mp4";
    std::unique_ptr<class VideoPlayer> m_videoPlayer;

    // Gameplay background (per-level) with fade, mirroring main.cpp behavior
    SDL_Texture* m_levelBackgroundTex = nullptr;
    SDL_Texture* m_nextLevelBackgroundTex = nullptr; // used during fade transitions
    float m_levelFadeAlpha = 0.0f; // 0..1 blend factor
    float m_levelFadeElapsed = 0.0f; // ms
    int m_cachedBgLevel = -1; // last loaded background level index
};
