<?php

declare(strict_types=1);

namespace Gls\GlsPoland\Configuration\Initializer;

use Doctrine\Common\EventManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Events;
use Gls\GlsPoland\Doctrine\ORM\EntityListener\PrefixTableListener;
use Symfony\Bridge\Doctrine\ContainerAwareEventManager;

/**
 * @internal
 */
final class DoctrineListenersInitializer implements ConfigurationInitializerInterface
{
    private $entityManager;
    private $dbPrefix;
    private $instantiate;

    public function __construct(EntityManagerInterface $entityManager, string $dbPrefix = null, bool $instantiate = false)
    {
        $this->entityManager = $entityManager;
        $this->dbPrefix = $dbPrefix;
        $this->instantiate = $instantiate;
    }

    public function init(): void
    {
        $eventManager = $this->entityManager->getEventManager();

        if ($this->hasListener($eventManager)) {
            return;
        }

        if ($this->instantiate || !$eventManager instanceof ContainerAwareEventManager) {
            $listener = new PrefixTableListener($this->dbPrefix ?? (string) constant('_DB_PREFIX_'));

            $eventManager->addEventListener(Events::loadClassMetadata, $listener);
        } else {
            $eventManager->addEventListener(Events::loadClassMetadata, PrefixTableListener::class);
        }
    }

    private function hasListener(EventManager $eventManager): bool
    {
        if (!$eventManager->hasListeners(Events::loadClassMetadata)) {
            return false;
        }

        foreach ($eventManager->getListeners(Events::loadClassMetadata) as $listener) {
            if ($listener instanceof PrefixTableListener || PrefixTableListener::class === $listener) {
                return true;
            }
        }

        return false;
    }
}
