<?php

namespace Lc\SovBundle\Doctrine;

use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\EntityManager as DoctrineEntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * class EntityManager.
 *
 * @author La clic !!!!
 */
class EntityManager extends EntityManagerDecorator
{
    protected EventDispatcherInterface $eventDispatcher;

    protected DoctrineEntityManager $entityManager;


    public function __construct(EntityManagerInterface $wrapped, EventDispatcherInterface $eventDispatcher)
    {
        $this->eventDispatcher = $eventDispatcher;
        parent::__construct($wrapped);
    }

    public function createQueryBuilder()
    {
        return new QueryBuilder($this);
    }

    public function getRepository($className)
    {
        return $this->wrapped->getRepository($this->getEntityName($className));
    }

    public function new($className)
    {
        $entityName = $this->getEntityName($className);

        return new $entityName;
    }

    public function create(EntityInterface $entity, bool $dispatchEvent = true): self
    {
        if($dispatchEvent) {
            $this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::PRE_CREATE_EVENT);
        }
        $this->persist($entity);
        if($dispatchEvent) {
            $this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::POST_CREATE_EVENT);
        }
        return $this;
    }

    public function update(EntityInterface $entity, bool $dispatchEvent = true): self
    {
        if($dispatchEvent){
            $this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::PRE_UPDATE_EVENT);
        }
        $this->persist($entity);
        if($dispatchEvent) {
            $this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::POST_UPDATE_EVENT);
        }
        return $this;
    }

    public function delete(EntityInterface $entity, bool $dispatchEvent = true): self
    {
        if($dispatchEvent) {
            $this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::PRE_DELETE_EVENT);
        }
        $this->remove($entity);
        if($dispatchEvent) {
            $this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::POST_DELETE_EVENT);
        }
        return $this;
    }

    public function flush($entity = null): self
    {
        $this->wrapped->flush($entity);

        return $this;
    }

    public function clear($objectName = null): self
    {
        $this->wrapped->clear($objectName);

        return $this;
    }

    public function refresh($object): self
    {
        $this->wrapped->refresh($object);

        return $this;
    }

    public function persist($entity)
    {
        $this->wrapped->persist($entity);
    }

    public function getClassMetadata($className)
    {
        return $this->wrapped->getClassMetadata($className);
    }

    public function getEntityName($className)
    {
        if (substr($className, -9) === 'Interface') {
            return $this->wrapped->getClassMetadata($className)->getName();
        } else {
            return $className;
        }
    }
}
