<?php

namespace KupShop\KupShopBundle\DependencyInjection\Compiler;

use KupShop\KupShopBundle\Util\KupShopContainer;
use KupShop\KupShopBundle\Util\StringUtil;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Yaml\Yaml;

class KupShopContainerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if (!$container->has(KupShopContainer::class)) {
            return;
        }

        $locator = $container->findDefinition(KupShopContainer::class);

        $kupshopServices = $this->loadServices(
            Yaml::parseFile(__DIR__.'/../../Resources/config/services-kupshop.yml'),
            $container
        );

        $locator->addArgument(ServiceLocatorTagPass::register($container, $kupshopServices));
    }

    public function loadServices(array $parsedFile, ContainerBuilder $container): array
    {
        $services = [];

        // All KupShop services
        foreach ($container->getDefinitions() as $id => $definition) {
            if (!$definition->isAbstract() && (!$definition->isPublic() || $definition->isPrivate())) {
                $this->addService($id, $container, $services);
            }
        }

        foreach ($container->getAliases() as $id => $definition) {
            if (!$definition->isPublic() || $definition->isPrivate()) {
                $this->addService($id, $container, $services);
            }
        }

        // Additional services - for example services that are not part of KupShop project
        foreach ($parsedFile['services'] as $id) {
            if ($container->has($id)) {
                $services[strtolower($id)] = new Reference($id);
            }
        }

        return $services;
    }

    private function addService(string $id, ContainerBuilder $container, array &$services): void
    {
        $lowerId = strtolower($id);
        // only kupshop or shop services
        if ((StringUtil::startsWith($lowerId, 'kupshop')
                || StringUtil::startsWith($lowerId, 'shop')
                || StringUtil::startsWith($lowerId, 'external'))
            && $container->has($id)) {
            $services[$lowerId] = new Reference($id);
        }
    }
}
