<?php
/**
 * PSR-4-style SPL autoloader for the RewindBrevoFormBridge namespace.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge;

defined( 'ABSPATH' ) || exit;

/**
 * Maps RewindBrevoFormBridge\Sub\ClassName to
 * includes/Sub/{class|interface|abstract}-class-name.php.
 *
 * @since 0.1.0
 */
class Autoloader {

	/**
	 * Namespace prefix this autoloader owns.
	 *
	 * @var string
	 */
	const PREFIX = 'RewindBrevoFormBridge\\';

	/**
	 * Register the autoloader with SPL.
	 *
	 * @since 0.1.0
	 * @return void
	 */
	public static function register(): void {
		spl_autoload_register( array( __CLASS__, 'autoload' ) );
	}

	/**
	 * Attempt to load a class in our namespace.
	 *
	 * @since 0.1.0
	 * @param string $class Fully qualified class name.
	 * @return void
	 */
	public static function autoload( string $class ): void {
		if ( 0 !== strpos( $class, self::PREFIX ) ) {
			return;
		}

		$relative = substr( $class, strlen( self::PREFIX ) );
		$segments = explode( '\\', $relative );
		$name     = array_pop( $segments );
		$dir      = RBFB_PATH . 'includes/';

		if ( count( $segments ) > 0 ) {
			$dir .= implode( '/', $segments ) . '/';
		}

		$slug = self::slug( $name );

		// WordPress file-naming convention: try class-, then interface-, then abstract-.
		$candidates = array( 'class-' . $slug, 'interface-' . $slug, 'abstract-' . $slug );

		// An "AbstractFoo" class lives in abstract-foo.php per WP convention.
		if ( 0 === strpos( $name, 'Abstract' ) && strlen( $name ) > 8 ) {
			$candidates[] = 'abstract-' . self::slug( substr( $name, 8 ) );
		}

		foreach ( $candidates as $candidate ) {
			$file = $dir . $candidate . '.php';
			if ( is_readable( $file ) ) {
				require_once $file;
				return;
			}
		}
	}

	/**
	 * Convert a class name to its kebab-case file slug.
	 *
	 * @since 0.1.0
	 * @param string $name Bare class name, e.g. "ListTable".
	 * @return string Kebab-case slug, e.g. "list-table".
	 */
	private static function slug( string $name ): string {
		$name = str_replace( '_', '-', $name );
		$name = preg_replace( '/(?<!^)[A-Z]/', '-$0', $name );

		return strtolower( $name );
	}
}
