<?php


namespace AutoAdmin\Bundle\Content\DependencyInjection\Compiler;

use AutoAdmin\Bundle\Content\Configuration\ConfigManager;
use AutoAdmin\Bundle\Content\Context\ContentContext;
use AutoAdmin\Bundle\Content\Controller\AbstractContentController;
use Doctrine\ORM\EntityManagerInterface;
use LogicException;
use ReflectionClass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

class ControllerCompilerPass implements CompilerPassInterface
{
    /**
     * @inheritDoc
     */
    public function process(ContainerBuilder $container)
    {
        $definitions = $container->findTaggedServiceIds('content.controller');

        foreach ($definitions as $id => $config) {
            $definition = $container->getDefinition($id);

            $refl = new ReflectionClass($id);
            if (!$refl->isSubclassOf(AbstractContentController::class)) {
                throw new LogicException(
                    sprintf(
                        'Service "%s" must extend base content controller class "%s"',
                        $id,
                        AbstractContentController::class
                    )
                );
            }

            $definition = $this->handle($definition);
            $container->setDefinition($id, $definition);
        }
    }

    private function handle(Definition $definition): Definition
    {
        $definition
            ->addMethodCall('setContentContext', [new Reference(ContentContext::class)])
            ->addMethodCall('setConfigManager', [new Reference(ConfigManager::class)])
            ->addMethodCall('setEntityManager', [new Reference(EntityManagerInterface::class)]);

        if (!$definition->hasTag('controller.service_arguments')) {
            $definition->addTag('controller.service_arguments');
        }

        if (!$definition->hasTag('content.controller')) {
            $definition->addTag('content.controller');
        }

        $definition->setAutowired(true);
        $definition->setPublic(true);

        return $definition;
    }
}
