<?php
/**
 * Autoloader Class.
 *
 * A basic PSR-4 autoloader for theme developers.
 *
 * @author    WPTRT <themes@wordpress.org>
 * @copyright 2019 WPTRT
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0-or-later
 * @link      https://github.com/WPTRT/autoload
 */

namespace WPTRT\Autoload;

class Expert_Mechanic_Loader {
	/**
	 * Array of loaders.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @var    array
	 */
	protected $loaders = [];
	/**
	 * Adds a new prefix and path to load.
	 *
	 * @since  1.0.0
	 * @access public
	 * @param  string        $prefix   Namespace prefix.
	 * @param  array|string  $paths    Absolute path(s) where to look for classes.
	 * @return void
	 */
	public function expert_mechanic_add( $prefix, $paths ) {

		foreach ( (array) $paths as $path ) {
			$this->loaders[ $prefix ][] = $path;
		}
	}
	/**
	 * Removes a loader by prefix or prefix + path.
	 *
	 * @since  1.0.0
	 * @access public
	 * @param  string  $prefix   Namespace prefix.
	 * @param  string  $path     Absolute path.
	 * @return void
	 */
	public function expert_mechanic_remove( $prefix, $path = '' ) {
		// Remove specific loader if both the prefix and path are provided.
		if ( $path ) {
			if ( $this->has( $prefix, $path ) ) {
				$key = array_search( $path, $this->loaders[ $prefix ], true );
				unset( $this->loaders[ $prefix ][ $key ] );
			}
			return;
		}
		// Remove all loaders for a prefix if no path is provided.
		if ( $this->has( $prefix ) ) {
			unset( $this->loaders[ $prefix ] );
		}
	}
	/**
	 * Checks if a loader is already added.
	 *
	 * @since  1.0.0
	 * @access public
	 * @param  string  $prefix   Namespace prefix.
	 * @param  string  $path     Absolute path.
	 * @return bool
	 */
	public function expert_mechanic_has( $prefix, $path = '' ) {
		if ( $path ) {
			return isset( $this->loaders[ $prefix ] ) && in_array( $path, $this->loaders[ $prefix ], true );
		}
		return isset( $this->loaders[ $prefix ] );
	}
	/**
	 * Registers all loaders.
	 *
	 * @since  1.0.0
	 * @access public
	 * @return void
	 */
	public function expert_mechanic_register() {

		if ( $this->loaders ) {

			spl_autoload_register( function( $class ) {

				$this->expert_mechanic_load( $class );
			}, true, true );
		}
	}
	/**
	 * Loads a class if it's within the given namespace.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @param  string  $class  Fully-qualified class name.
	 * @return void
	 */
	protected function expert_mechanic_load( $class ) {
		foreach ( $this->loaders as $prefix => $paths ) {
			// Continue if the class is not in our namespace.
			if ( 0 !== strpos( $class, $prefix ) ) {
				continue;
			}
			// Build a class filename to append to the path.
			$suffix = ltrim( str_replace( $prefix, '', $class ), '\\' );
			$suffix = DIRECTORY_SEPARATOR . str_replace( '\\', DIRECTORY_SEPARATOR, $suffix ) . '.php';
			// Loop through the paths to see if we can find the file
			// for the class.
			foreach ( $paths as $path ) {
				// Load the class file if it exists and return.
				if ( file_exists( $file = realpath( $path ) . $suffix ) ) {
					include $file;
					return;
				}
			}
		}
	}
}