<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\DI\Definition;

use PpPhp\Core\Platform\DI\Contracts\DefinitionInterface;

final class DefinitionRepository
{
    private array $definitions = [];
    private array $aliases = [];

    public function add(DefinitionInterface $definition): void
    {
        $this->definitions[$definition->id()] = $definition;
        foreach ($definition->aliases() as $alias) {
            $this->aliases[$alias] = $definition->id();
        }
    }

    public function has(string $id): bool { return isset($this->definitions[$this->resolveAlias($id)]); }
    public function get(string $id): ?DefinitionInterface { return $this->definitions[$this->resolveAlias($id)] ?? null; }
    public function alias(string $alias, string $target): void { $this->aliases[$alias] = $target; }
    public function resolveAlias(string $id): string { return $this->aliases[$id] ?? $id; }
    public function all(): array { return $this->definitions; }
    public function aliases(): array { return $this->aliases; }

    public function tagged(string $tag): array
    {
        return array_values(array_filter($this->definitions, static fn (DefinitionInterface $definition): bool => array_key_exists($tag, $definition->tags())));
    }

    public function toArray(): array
    {
        return [
            'definitions' => array_map(static fn (DefinitionInterface $definition): array => $definition->toArray(), array_values($this->definitions)),
            'aliases' => $this->aliases,
        ];
    }
}
