//
// LDASTools - Logger Manager for Explicit Lifetime Control
// 
// Copyright (C) 2025 California Institute of Technology
//
// Following Peter Muldoon's "Retiring the Singleton Pattern" principles:
// - Explicit dependency injection
// - Controlled object lifetimes 
// - No global/static state
//

#ifndef LDASTOOLSAL_LOGGERMANAGER_HH
#define LDASTOOLSAL_LOGGERMANAGER_HH

#include <string>
#include <unordered_map>
#include <memory>
#include <mutex>
#include "ldastoolsal/SimpleLogger.hh"
#include "ldastoolsal/LoggerRegistry.hh"
#include "ldastoolsal/DebugLevelManager.hh"

// Forward declaration to avoid including boost headers in LoggerManager
namespace boost {
namespace log {
namespace sinks {
class sink;
}
}
}

namespace LDASTools {
namespace AL {

/**
 * @brief Manager for logger instances with explicit lifetime control
 * 
 * This class replaces the static get_channel_logger() pattern with 
 * dependency injection following Muldoon's principles:
 * 
 * - Explicit lifetime management (created/destroyed in main())
 * - No global/static state 
 * - Testable (easy to inject mocks)
 * - Thread-safe
 * 
 * @example Basic Usage
 * @code
 * int main() {
 *     auto logger_mgr = std::make_unique<LoggerManager>();
 *     
 *     // Use logger manager
 *     SimpleLogger* logger = logger_mgr->getLogger("app.component");
 *     
 *     // Explicit cleanup before main() returns
 *     logger_mgr->shutdown();
 *     return 0;
 * }
 * @endcode
 */
class LoggerManager {
public:
    /**
     * @brief Default constructor
     */
    LoggerManager() = default;
    
    /**
     * @brief Constructor with custom sink injection
     * @param custom_sink Custom boost::log sink to use instead of default console sink
     * @note Following Muldoon's dependency injection principles - explicit injection via constructor
     */
    LoggerManager(boost::shared_ptr<boost::log::sinks::sink> custom_sink);
    
    /**
     * @brief Destructor - calls shutdown() automatically
     */
    ~LoggerManager();
    
    // Disable copy/move to prevent accidental duplication
    LoggerManager(const LoggerManager&) = delete;
    LoggerManager& operator=(const LoggerManager&) = delete;
    LoggerManager(LoggerManager&&) = delete;
    LoggerManager& operator=(LoggerManager&&) = delete;
    
    /**
     * @brief Get or create a logger for a specific channel
     * @param channel Channel name (e.g., "framecpp.frtoc.data") 
     * @return Pointer to logger (owned by LoggerManager), or nullptr if debug level is 0
     * @note PERFORMANCE OPTIMIZATION: Returns nullptr for channels with debug level 0
     *       to eliminate all runtime overhead when debugging is disabled
     * @thread_safety Thread-safe
     */
    SimpleLogger* getLogger(const std::string& channel);
    
    /**
     * @brief Sync all managed loggers with current debug levels
     * 
     * This should be called after debug levels are changed via
     * DebugLevelManager to ensure all cached loggers are updated.
     * 
     * @note PERFORMANCE OPTIMIZATION: Automatically sets loggers to nullptr
     *       for channels with debug level 0, and creates actual loggers when
     *       levels change from 0 to non-zero
     * @thread_safety Thread-safe
     */
    void syncAllLoggers();
    
    /**
     * @brief Explicitly shut down all loggers
     * 
     * This clears all cached loggers and should be called before
     * the LoggerManager is destroyed to ensure clean shutdown.
     * Called automatically by destructor.
     * 
     * @thread_safety Thread-safe
     */
    void shutdown();
    
    /**
     * @brief Get count of managed loggers (for testing/debugging)
     * @return Number of loggers currently managed
     * @thread_safety Thread-safe
     */
    size_t getLoggerCount() const;

private:
    mutable std::mutex mutex_;
    std::unordered_map<std::string, SimpleLogger*> loggers_;
    bool shutdown_called_ = false;
    boost::shared_ptr<boost::log::sinks::sink> custom_sink_;
    bool sink_configured_ = false;
};

} // namespace AL
} // namespace LDASTools

#endif // LDASTOOLSAL_LOGGERMANAGER_HH