<?php

namespace WordpressModels\DependencyInjection\Metabox;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Compiler pass to register metaboxes.
 *
 * Skipped in non-admin requests, as metaboxes are not used in the frontend.
 *
 * The following steps are performed:
 * - Find all services tagged with 'metabox'
 * - Register the service as an alias for each screen it is tagged for
 * - Add the service to the MetaboxRegistry via addMetabox method call
 */
class MetaboxCompilerPass implements CompilerPassInterface
{

    public function process(ContainerBuilder $container)
    {
        if (!is_admin() || !$container->has(MetaboxRegistry::class)) {
            // prevent pointless instantiation for non-admin requests
            return;
        }

        $registry = $container->getDefinition(MetaboxRegistry::class);

        $taggedServices = $container->findTaggedServiceIds('metabox');
        foreach ($taggedServices as $id => $tags) {
            foreach ($tags as $tag) {
                // create the alias Id
                $alias = MetaboxRegistry::getMetaboxServiceId($tag['id'], $tag['screen']);

                // check if the alias is already in use
                if ($container->hasAlias($alias)) {
                    $aliasDef = $container->getDefinition($alias);
                    throw new \InvalidArgumentException(sprintf('The service alias "%s" is already in use by class "%s".', $alias, $aliasDef->getClass()));
                }
                // alias the service
                $container->setAlias($alias, $id)
                    ->setPublic(true);

                // add the method call
                $reference = new Reference($id);
                $registry->addMethodCall('addMetabox', [
                    $tag['id'],
                    $tag['title'],
                    [$reference, 'renderMetabox'],
                    $tag['context'],
                    $tag['priority'],
                    $tag['screen'],
                ]);
            }
        }
    }
}