<?php declare(strict_types=1);

namespace Newland\ToubizWidgetRendering;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Configuration\Exception\InvalidConfigurationException;
use Neos\Flow\ObjectManagement\Exception\InvalidObjectException;
use Neos\Flow\ObjectManagement\ObjectManager;
use Newland\ToubizWidgetRendering\Renderer\FallbackStack;
use Newland\ToubizWidgetRendering\Renderer\PrecompiledClientRenderer;
use Newland\ToubizWidgetRendering\Renderer\ServerSideRenderer;
use Newland\ToubizWidgetRendering\Renderer\ToubizWidgetRenderer;

class RendererFactory
{

    /**
     * @var array
     * @Flow\InjectConfiguration()
     */
    protected $settings;

    /**
     * @var ObjectManager
     * @Flow\Inject
     */
    protected $objectManager;

    /**
     * @var array<string, class-string<ToubizWidgetRenderer>>
     */
    protected $alias = [
        'precompiledClient' => PrecompiledClientRenderer::class,
        'serverSide' => ServerSideRenderer::class,
        'fallbackStack' => FallbackStack::class,
    ];

    public function get(): ToubizWidgetRenderer
    {
        return $this->initialize($this->settings['renderer'], $this->settings['rendererConfiguration'] ?? []);
    }

    public function initialize(string $renderer, array $configuration): ToubizWidgetRenderer
    {
        $renderer = $this->alias[$renderer] ?? $renderer;

        if (!class_exists($renderer)) {
            throw new InvalidConfigurationException(sprintf(
                'Toubiz widget renderer `%s` does not exist. Must be one of [%s] or fully qualified class name.',
                $renderer,
                implode(', ', array_keys($this->alias))
            ));
        }

        $instance = $this->objectManager->get($renderer);
        if (!($instance instanceof ToubizWidgetRenderer)) {
            throw new InvalidObjectException(sprintf(
                'Toubiz widget renderer must implement `%s` but `%s` does not.',
                ToubizWidgetRenderer::class,
                get_debug_type($instance)
            ));
        }

        $instance->setConfiguration($configuration);
        return $instance;
    }
}
