<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\DocStoreBundle\DependencyInjection\Compiler;

use Chill\DocStoreBundle\AsyncUpload\Driver\LocalStorage\TempUrlLocalStorageGenerator;
use Chill\DocStoreBundle\AsyncUpload\Driver\OpenstackObjectStore\ConfigureOpenstackObjectStorageCommand;
use Chill\DocStoreBundle\AsyncUpload\Driver\OpenstackObjectStore\TempUrlOpenstackGenerator;
use Chill\DocStoreBundle\AsyncUpload\TempUrlGeneratorInterface;
use Chill\DocStoreBundle\Controller\StoredObjectContentToLocalStorageController;
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class StorageConfigurationCompilerPass implements CompilerPassInterface
{
    private const SERVICES_OPENSTACK = [
        \Chill\DocStoreBundle\AsyncUpload\Driver\OpenstackObjectStore\StoredObjectManager::class,
        TempUrlOpenstackGenerator::class,
        ConfigureOpenstackObjectStorageCommand::class,
    ];

    private const SERVICES_LOCAL_STORAGE = [
        \Chill\DocStoreBundle\AsyncUpload\Driver\LocalStorage\StoredObjectManager::class,
        TempUrlLocalStorageGenerator::class,
        StoredObjectContentToLocalStorageController::class,
    ];

    public function process(ContainerBuilder $container)
    {
        $config = $container
            ->getParameterBag()
            ->resolveValue($container->getParameter('chill_doc_store'));

        if (array_key_exists('local_storage', $config) && !array_key_exists('openstack', $config)) {
            $driver = 'local_storage';
            $this->checkUseDriverConfiguration($config['use_driver'] ?? null, $driver);
        } elseif (!array_key_exists('local_storage', $config) && array_key_exists('openstack', $config)) {
            $driver = 'openstack';
            $this->checkUseDriverConfiguration($config['use_driver'] ?? null, $driver);
        } elseif (array_key_exists('openstack', $config) && array_key_exists('local_storage', $config)) {
            $driver = $config['use_driver'] ?? null;
            if (null === $driver) {
                throw new InvalidConfigurationException('There are multiple drivers configured for chill_doc_store, set the one you want to use with the variable use_driver');
            }
        } else {
            throw new InvalidConfigurationException('No driver defined for storing document. Define one in chill_doc_store configuration');
        }

        if ('local_storage' === $driver) {
            foreach (self::SERVICES_OPENSTACK as $service) {
                $container->removeDefinition($service);
            }

            $container->setAlias(StoredObjectManagerInterface::class, \Chill\DocStoreBundle\AsyncUpload\Driver\LocalStorage\StoredObjectManager::class);
            $container->setAlias(TempUrlGeneratorInterface::class, TempUrlLocalStorageGenerator::class);
        } else {
            foreach (self::SERVICES_LOCAL_STORAGE as $service) {
                $container->removeDefinition($service);
            }

            $container->setAlias(StoredObjectManagerInterface::class, \Chill\DocStoreBundle\AsyncUpload\Driver\OpenstackObjectStore\StoredObjectManager::class);
            $container->setAlias(TempUrlGeneratorInterface::class, TempUrlOpenstackGenerator::class);
        }
    }

    private function checkUseDriverConfiguration(?string $useDriver, string $driver): void
    {
        if (null === $useDriver) {
            return;
        }

        if ($useDriver !== $driver) {
            throw new InvalidConfigurationException(sprintf('The "use_driver" configuration require a driver (%s) which is not configured. Configure this driver in order to use it.', $useDriver));
        }
    }
}
