<?php

namespace WPSN\Core;

use RuntimeException;

defined('ABSPATH') || exit;

/**
 * Extremely small dependency container / service-locator.
 *
 * - set(id, factory)
 * - get(id) lazy-loads and caches instance
 */
final class Container
{
    /** @var array<string, callable(self):mixed> */
    private array $factories = [];

    /** @var array<string, mixed> */
    private array $instances = [];

    public function set(string $id, callable $factory): void
    {
        $this->factories[$id] = $factory;
        unset($this->instances[$id]);
    }

    public function has(string $id): bool
    {
        return array_key_exists($id, $this->factories) || array_key_exists($id, $this->instances);
    }

    /**
     * @return mixed
     */
    public function get(string $id)
    {
        if (array_key_exists($id, $this->instances)) {
            return $this->instances[$id];
        }

        if (!array_key_exists($id, $this->factories)) {
            throw new RuntimeException('Service not found: ' . $id);
        }

        $this->instances[$id] = ($this->factories[$id])($this);

        return $this->instances[$id];
    }
}
