<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\DI\Compiler\Pipeline;

use PpPhp\Core\Platform\DI\Compiler\CompilerContext;
use PpPhp\Core\Platform\DI\Compiler\CompilerStageInterface;
use PpPhp\Core\Platform\DI\Compiler\Stages\DefinitionCompilationStage;
use PpPhp\Core\Platform\DI\Compiler\Stages\FactoryGenerationStage;

final class CompilerPipeline
{
    private array $stages = [];

    public static function default(): self
    {
        $pipeline = new self();
        $pipeline->add(new DefinitionCompilationStage());
        $pipeline->add(new FactoryGenerationStage());
        return $pipeline;
    }

    public function add(CompilerStageInterface $stage): void { $this->stages[] = $stage; }
    public function stages(): array { return $this->stages; }
    public function stageNames(): array { return array_map(static fn (CompilerStageInterface $stage): string => $stage->name(), $this->stages); }

    public function run(CompilerContext $context): CompilerPipelineAudit
    {
        $audit = new CompilerPipelineAudit();
        foreach ($this->stages as $stage) {
            $start = microtime(true);
            $stage->process($context);
            $audit->record($stage->name(), (microtime(true) - $start) * 1000);
        }
        $context->setMetadata('pipelineAudit', $audit->toArray());
        return $audit;
    }
}
