<?php
/**
 * IoC container
 * @author Jérôme Brilland
 * @version 1.0
 * @since 3.0
 * @copyright (c) 2021, Jérôme Brilland
 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License
 */
class Ioc {

    protected static $registry = [];

    /**
     * Add a new resolver to the registry array
     * @param string $name the id
     * @param Closure $resolve Closure that create instance
     * @param boolean $shared Declare the object as unique
     * @return void
     * @access public
     * @static
     */
    public static function register( $name, Closure $resolve, $shared = false ) {
        if ( $shared ) {
            static::$registry[$name] = self::asShared( $resolve );
        } else {
            static::$registry[$name] = $resolve;
        }
    }

    /**
     * Create the instance
     * @param string $name the id
     * @return mixed
     * @access public
     * @static
     */
    public static function resolve( $name ) {
        if ( static::registered( $name ) ) {
            $resolve = static::$registry[$name];
            return $resolve();
        }
        throw new LogicException( 'Nothing registered with that name.' );
    }

    /**
     * Determine whether the id is registered
     * @param string $name the id
     * @return boolean Whether the id exists or not
     * @access public
     * @static
     */
    public static function registered( $name ) {
        return array_key_exists( $name, static::$registry );
    }

    /**
     * Return a closure that store the result of the given closure, for use as a shared instance
     * @param Closure $resolve Closure that create instance
     * @return void
     * @access public
     * @static
     */
    public static function asShared( Closure $resolve ) {
        return function() use ( $resolve ) {
            static $object = null;
            if ( is_null( $object ) ) {
                $object = $resolve();
            }
            return $object;
        };
    }
}
