<?php
declare(strict_types=1);

namespace App\Framework\DI;

use App\Framework\Core\AttributeCompiler;
use App\Framework\Core\AttributeMapper;

final class AttributeProcessorRegistry
{
    /**
     * @var AttributeMapper[]
     */
    private array $mappers = [];

    /**
     * @var AttributeCompiler[]
     */
    private array $compilers = [];

    public function __construct(private readonly DefaultContainer $container)
    {
    }

    /**
     * Registriert einen AttributeMapper
     */
    public function registerMapper(string $mapperClass): self
    {
        $this->mappers[] = $mapperClass;
        return $this;
    }

    /**
     * Registriert einen AttributeCompiler
     */
    public function registerCompiler(string $compilerClass): self
    {
        $this->compilers[] = $compilerClass;
        return $this;
    }

    /**
     * Verarbeitet alle Attribute mit den registrierten Mappern und Compilern
     */
    public function processAll(array $discoveryResults): array
    {
        $compiledResults = [];
        $mappedByType = [];

        // Mapper-Instanzen erstellen
        $mapperInstances = [];
        foreach ($this->mappers as $mapperClass) {
            $mapper = $this->container->get($mapperClass);
            $mapperInstances[$mapper->getAttributeClass()] = $mapper;
        }

        // Compiler-Instanzen erstellen
        $compilerInstances = [];
        foreach ($this->compilers as $compilerClass) {
            $compiler = $this->container->get($compilerClass);
            $compilerInstances[$compiler->getAttributeClass()] = $compiler;
        }

        // Attribute kompilieren, für die sowohl Mapper als auch Compiler existieren
        foreach ($discoveryResults as $attributeClass => $attributeData) {
            if (isset($mapperInstances[$attributeClass]) && isset($compilerInstances[$attributeClass])) {
                // Wenn ein Compiler vorhanden ist, verwenden wir ihn zur Kompilierung
                $compiledResults[$attributeClass] = $compilerInstances[$attributeClass]->compile($attributeData);
            } elseif (isset($mapperInstances[$attributeClass])) {
                // Ohne Compiler geben wir die gemappten Daten direkt zurück
                $compiledResults[$attributeClass] = $attributeData;
            }
        }

        return $compiledResults;
    }

}
