<?php
/**
 * ESSB Hybrid Autoloader Class
 * Handles both class autoloading and on-demand function loading
 */

class ESSB_Autoloader {
    
    /**
     * Class map - prefix => file path
     * @var array
     */
    private static $class_map = array(
        'ESSB_Post_Meta' => 'lib/classes/class-post-meta.php',
        'ESSB_Cached_Share_Counters' => 'lib/classes/share-button/class-cached-share-counters.php',
        'ESSB_Factory_Loader' => 'lib/classes/class-factory-loader.php',
        'ESSB_Plugin_Options' => 'lib/classes/class-plugin-options.php',
        'ESSB_Runtime_Cache' => 'lib/classes/class-runtime-cache.php',
        'ESSB_Plugin_Loader' => 'lib/classes/class-plugin-loader.php',
        'ESSB_Post_Information' => 'lib/classes/share-information/class-abstract-post-information.php',
        'ESSB_Single_Post_Information' => 'lib/classes/share-information/class-single-post-information.php',
        'ESSB_Site_Share_Information' => 'lib/classes/share-information/class-site-share-information.php',
        'ESSB_Share_Networks_Helper' => 'lib/classes/networks/class-share-networks-helper.php',
        // Assets
        'ESSB_Dynamic_JS_Builder' => 'lib/classes/assets/class-dynamic-js-builder.php',
        'ESSB_Dynamic_CSS_Builder' => 'lib/classes/assets/class-dynamic-css-builder.php',
        'ESSB_Runtime_CSS_Builder' => 'lib/classes/assets/class-runtime-css-builder.php',
        'ESSB_Static_CSS_Loader' => 'lib/classes/assets/class-static-css-loader.php',
        'ESSB_Plugin_Assets' => 'lib/classes/assets/class-plugin-assets.php',
        'ESSB_Module_Assets' => 'lib/classes/assets/class-module-assets.php',
        'ESSB_Ajax' => 'lib/classes/class-ajax.php',
        'ESSBPrecompiledResources' => 'lib/classes/cache/class-plugin-assets-cache.php',
        'ESSB_Precompiled_Cache' => 'lib/classes/cache/class-plugin-assets-cache.php',
        'ESSB_Dynamic_Cache' => 'lib/classes/cache/class-dynamic-cache.php'
    );
    
    /**
     * Function map - function_name => file path
     * @var array
     */
    private static $function_map = array(
    );
    
    /**
     * Track loaded files to prevent multiple includes
     * @var array
     */
    private static $loaded_files = array();
    
    /**
     * Initialize the autoloader
     */
    public static function init() {
        // Register class autoloader
        spl_autoload_register( array( __CLASS__, 'autoload_classes' ) );
    }
    
    /**
     * Autoload classes based on class map
     * 
     * @param string $class Class name
     */
    public static function autoload_classes( $class ) {
        // Only handle classes with our prefix
        if ( strpos( $class, 'ESSB_' ) !== 0 ) {
            return;
        }
        
        // Direct array access - no filter for maximum performance
        if ( isset( self::$class_map[ $class ] ) ) {
            $file_path = ESSB3_PLUGIN_ROOT . self::$class_map[ $class ];
            
            if ( file_exists( $file_path ) ) {
                require_once $file_path;
                self::$loaded_files[] = self::$class_map[ $class ];
            }
        }
    }
    
    /**
     * Load a function file on-demand
     * Call this before using any function from the map
     * 
     * @param string $function_name The function to load
     * @return bool True if loaded successfully, false otherwise
     */
    public static function load_function( $function_name ) {
        // Check if function already exists
        if ( function_exists( $function_name ) ) {
            return true;
        }
        
        // Direct array access - no filter for maximum performance
        if ( isset( self::$function_map[ $function_name ] ) ) {
            $file = self::$function_map[ $function_name ];
            
            // Use load_file to handle the actual loading
            return self::load_file( $file );
        }
        
        return false;
    }
    
    /**
     * Load multiple files at once
     * Perfect for priority loading or loading groups of related files
     * 
     * @param array $files Array of relative file paths
     * @return array Array of results (file path => bool success)
     */
    public static function load_files( $files ) {
        $results = array();
        
        foreach ( $files as $file ) {
            $results[ $file ] = self::load_file( $file );
        }
        
        return $results;
    }
    
    /**
     * Load any file under the plugin root if not already loaded
     * 
     * @param string $file_path Relative path to file (from plugin root)
     * @return bool True if file loaded successfully or already loaded, false if file doesn't exist
     */
    public static function load_file( $file_path ) {
        // Normalize path (remove leading slashes)
        $file_path = ltrim( $file_path, '/' );
        
        // Check if already loaded
        if ( in_array( $file_path, self::$loaded_files ) ) {
            return true;
        }
        
        // Construct full path
        $full_path = ESSB3_PLUGIN_ROOT . $file_path;
        
        // Check if file exists
        if ( file_exists( $full_path ) ) {
            require_once $full_path;
            self::$loaded_files[] = $file_path;
            return true;
        }
        
        return false;
    }
    
    /**
     * Check if a file has already been loaded
     * 
     * @param string $file_path Relative path to file
     * @return bool
     */
    public static function is_file_loaded( $file_path ) {
        return in_array( ltrim( $file_path, '/' ), self::$loaded_files );
    }
    
    /**
     * Get list of all loaded files
     * 
     * @return array
     */
    public static function get_loaded_files() {
        return self::$loaded_files;
    }
    
    /**
     * Preload multiple functions at once
     * Useful for bulk operations
     * 
     * @param array $functions Array of function names
     * @return array Array of results (function name => bool success)
     */
    public static function preload_functions( $functions ) {
        $results = array();
        
        foreach ( $functions as $function ) {
            $results[ $function ] = self::load_function( $function );
        }
        
        return $results;
    }
    
    /**
     * Load priority files that are needed for every request
     * This is a helper method to load critical files early
     * 
     * @param array $priority_files Array of file paths to load
     * @return array Results of load_files()
     */
    public static function load_priority( $priority_files ) {
        return self::load_files( $priority_files );
    }
    
    /**
     * Add a class to the map dynamically (for addons)
     * 
     * @param string $class_name
     * @param string $file_path
     */
    public static function add_class( $class_name, $file_path ) {
        self::$class_map[ $class_name ] = ltrim( $file_path, '/' );
    }
    
    /**
     * Add a function to the map dynamically (for addons)
     * 
     * @param string $function_name
     * @param string $file_path
     */
    public static function add_function( $function_name, $file_path ) {
        self::$function_map[ $function_name ] = ltrim( $file_path, '/' );
    }
    
    /**
     * Get the current class map (with filter only for external viewing)
     * 
     * @return array
     */
    public static function get_class_map() {
        return apply_filters( 'essb_class_map', self::$class_map );
    }
    
    /**
     * Get the current function map (with filter only for external viewing)
     * 
     * @return array
     */
    public static function get_function_map() {
        return apply_filters( 'essb_function_map', self::$function_map );
    }
    
    /**
     * Clear loaded files list (useful for testing)
     */
    public static function reset_loaded_files() {
        self::$loaded_files = array();
    }
}

// Initialize the autoloader
ESSB_Autoloader::init();