<?php

namespace SCF\Core;

class DI {
    /**
     * @var $instance
     */
    private static $instance;

    /**
     * @var array $container
     */
    private $container = [];

    /**
     * DI constructor.
     */
    private function __construct()
    {

    }

    /**
     *
     */
    private function __clone()
    {

    }

    /**
     * @return DI
     */
    public static function getInstance()
    {
        if(self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * @param $name
     * @param $classDefinition
     * @param bool $shared
     */
    public function set($name, $classDefinition, $shared = false)
    {
        $this->container[$name] = (object)['def' => $classDefinition, 'shared' => $shared, 'instance' => null];
    }

    /**
     * @param $name
     * @return mixed
     */
    public function get($name)
    {
        if(!isset($this->container[$name])) {
            throw new \RuntimeException('Angeforderter Service '. $name .' nicht definiert');
        }

        $service = $this->container[$name];

        if(!$service->shared) {
            return $this->createInstance($service->def, false);
        }

        if($service->instance === null) {
            $service->instance = $this->createInstance($service->def, true);
        }

        return $service->instance;
    }

    /**
     * @param $definition
     * @param $shared
     * @return mixed
     */
    private function createInstance($definition, $shared)
    {
        if(is_callable($definition)) {
            return $definition();
        }

        if(is_string($definition)) {
            return new $definition;
        }

        if(is_object($definition)) {
            if($shared) {
                return $definition;
            } else {
                return new $definition;
            }
        }

        throw new  \RuntimeException('Malformed service definition!');
    }

}