<?php
namespace App\Listener;

use App\Entity\User;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;

class UnitOfWorkListener implements EventSubscriber
{
    private $em;
    private $serializer;
    private $session;

    public function __construct(EntityManagerInterface $em, SerializerInterface $serializer, Security $security, SessionInterface $session)
    {
        $this->em = $em;
        $this->serializer = $serializer;
        $this->security = $security;
        $this->session = $session;
    }

    public function getSubscribedEvents()
    {
        return array(Events::onFlush);
    }

    public function onFlush(OnFlushEventArgs $args)
    {
        $em  = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        if ($this->security->getUser() != null) {
            // // if (true == true) {
            // if ($this->security->getUser()->hasRole('ROLE_ADMIN')
            //     || $this->security->getUser()->hasRole('ROLE_SUPER_ADMIN')
            //     || $this->security->getUser()->hasRole('ROLE_MODERATEUR')
            // ) {
            //     // ON EDITE LES ENTITES COMME D'HABITUDE ! => pas de changements du UnitOfWork
            // } else {
            // DEBUG
            $debug = false;
            if ($debug) {
                dump("-------------------------------------------------- insert");
                dump($uow->getScheduledEntityInsertions());
                dump("-------------------------------------------------- update");
                dump($uow->getScheduledEntityUpdates());
                foreach ($uow->getScheduledEntityUpdates() as $entity) {
                    dump(get_class($entity).' '.$entity->getId());
                    dump($uow->getEntityChangeSet($entity));
                }
                dump("-------------------------------------------------- delete");
                dump($uow->getScheduledEntityDeletions());
                dump("-------------------------------------------------- col update");
                dump($uow->getScheduledCollectionUpdates());
                dump("-------------------------------------------------- col delete");
                dump($uow->getScheduledCollectionDeletions());
                // exit();
            }
            $updated = $uow->getScheduledEntityUpdates();
            $deleted = $uow->getScheduledEntityDeletions();
            // $colupdated = $uow->getScheduledCollectionUpdates();
            // $coldeleted = $uow->getScheduledCollectionDeletions();

            foreach ($updated as $entity) {
                if ($entity instanceof User) {
                    $userDB = $this->em->getRepository(User::class)->findOneById($entity->getId());
                    $changeSets = $this->em->getUnitOfWork()->getEntityChangeSet($entity);

                    $hasRoleSuperAdmin = false;
                    $hasRoleAdminSiege = false;
                    $hasRemovedRoleSuperAdmin = false;
                    $hasRemovedRoleAdminSiege = false;
                    foreach ($changeSets as $key => $changeSet) {
                        if ($key == 'enabled' && $changeSet[0] == true && $changeSet[1] == false) {
                            if ($entity->hasRole('ROLE_SUPER_ADMIN')) {
                                $hasRemovedRoleSuperAdmin = true;
                            }
                            if ($entity->hasRole('ROLE_ADMIN_SIEGE')) {
                                $hasRemovedRoleAdminSiege = true;
                            }
                        }
                        if ($key == 'roles') {
                            foreach ($changeSet[0] as $key => $role) {
                                if ($role == 'ROLE_SUPER_ADMIN') {
                                    $hasRoleSuperAdmin = true;
                                }
                                if ($role == 'ROLE_ADMIN_SIEGE') {
                                    $hasRoleAdminSiege = true;
                                }
                            }
                            if ($hasRoleSuperAdmin) {
                                $hasRemovedRoleSuperAdmin = true;
                            }
                            if ($hasRoleAdminSiege) {
                                $hasRemovedRoleAdminSiege = true;
                            }
                            foreach ($changeSet[1] as $key => $role) {
                                if ($role == 'ROLE_SUPER_ADMIN') {
                                    $hasRemovedRoleSuperAdmin = false;
                                }
                                if ($role == 'ROLE_ADMIN_SIEGE') {
                                    $hasRemovedRoleAdminSiege = false;
                                }
                            }
                        }
                    }
                    if ($hasRemovedRoleSuperAdmin) {
                        $usersSuperAdmin = $this->em->getRepository(User::class)->findByRole('ROLE_SUPER_ADMIN');
                        if (count($usersSuperAdmin) <= 1) {
                            $this->session->getFlashBag()->add('error', 'Impossible de désactiver ou supprimer le dernier utilisateur SUPER ADMIN, ajoutez en un autre avant !');
                            $uow->detach($entity);
                        }
                    }
                    if ($hasRemovedRoleAdminSiege) {
                        $usersAdminSiege = $this->em->getRepository(User::class)->findByRole('ROLE_SUPER_ADMIN');
                        if (count($usersAdminSiege) <= 1) {
                            $this->session->getFlashBag()->add('error', 'Impossible de désactiver ou supprimer le dernier utilisateur ADMIN SIEGE, ajoutez en un autre avant !');
                            $uow->detach($entity);
                        }
                    }
                }
            }
            foreach ($deleted as $entity) {
                if ($entity instanceof User) {
                    if ($entity->hasRole('ROLE_SUPER_ADMIN')) {
                        $usersSuperAdmin = $this->em->getRepository(User::class)->findByRole('ROLE_SUPER_ADMIN');
                        if (count($usersSuperAdmin) <= 1) {
                            $this->session->getFlashBag()->add('error', 'Impossible de désactiver ou supprimer le dernier utilisateur SUPER ADMIN, ajoutez en un autre avant !');
                            $uow->detach($entity);
                        }
                    }
                    if ($entity->hasRole('ROLE_ADMIN_SIEGE')) {
                        $usersAdminSiege = $this->em->getRepository(User::class)->findByRole('ROLE_SUPER_ADMIN');
                        if (count($usersAdminSiege) <= 1) {
                            $this->session->getFlashBag()->add('error', 'Impossible de désactiver ou supprimer le dernier utilisateur ADMIN SIEGE, ajoutez en un autre avant !');
                            $uow->detach($entity);
                        }
                    }
                }
            }
        }
    }


    // /**
    //  * Make a snapshot of insert or update entity link to produit
    //  * @param  Versionable  $entity     Versionable entity
    //  * @param  string       $type       'update' or 'new'
    //  */
    // private function _makeSnapshot($entity, $type = 'update', $productId = null)
    // {
    //     $makeSnapshot = true;
    //     $entitySerialized = $this->serializer->serialize($entity, 'json', ['groups' => ['default']]);
        
    //     if ($entity instanceof Document && $type == 'update') {
    //         $classes = array('IndustrielVisuel', 'ProduitVisuel', 'ProduitDoc', 'Produit2D', 'Produit3D', 'ProduitTexture', 'ProduitBIM', 'ProduitSavoirFaireDoc', 'ProduitColorieDoc', 'ProduitColorieVignette');
    //         foreach ($classes as $class) {
    //             $produitVisuel = $this->em->getRepository('AppBundle:'.$class)->findOneBy(array('img' => $entity));
    //             if ($produitVisuel) {
    //                 $entity->setProduit($produitVisuel->getProduit());
    //                 $productId = $produitVisuel->getProduit();
    //                 break;
    //             }
    //         }
    //     }
    //     if ($entity->getId() != null) {
    //         $currentEntity    = $this->em->getRepository(get_class($entity))->find($entity->getId());

    //         if ($type == 'update' && $productId == null) {
    //             $change = $this->em->getUnitOfWork()->getEntityChangeSet($entity);
    //             if (array_key_exists('produit', $change) && count($change['produit']) > 0) {
    //                 $product = $change['produit'][0];
    //                 $this->productid = $product->getId();
    //                 $newProduct = $change['produit'][1];
    //                 if ($newProduct == null or $newProduct->getId() == null) {
    //                     $type = 'delete';
    //                 }
    //             }
    //         }
    //         if (count($this->em->getUnitOfWork()->getEntityChangeSet($entity)) > 0 or $type == 'delete' or $type == 'new') {
    //             $makeSnapshot = true;
    //         } else {
    //             $makeSnapshot = false;
    //         }
    //     }
    //     if ($entity instanceof Document && ($type == 'new' or $type == 'delete')) {
    //         $makeSnapshot = false;
    //     }
    //     if ($makeSnapshot) {
    //         $changeSets = $this->em->getUnitOfWork()->getEntityChangeSet($entity);
    //         if ($type == 'new') {
    //             $resourceVersion = new ResourceVersion($entity, $entitySerialized, $this->security->getUser(), 'new', null, $type, $productId);
    //             $class           = $this->em->getClassMetadata(get_class($resourceVersion));
    //             $this->em->persist($resourceVersion);
    //             $this->em->getUnitOfWork()->computeChangeSet($class, $resourceVersion);
    //         } elseif ($type == 'delete') {
    //             $resourceVersion = new ResourceVersion($currentEntity, $this->serializer->serialize($currentEntity, 'json', ['groups' => ['default']]), $this->security->getUser(), 'delete', null, $type, $this->productid);
    //             $class           = $this->em->getClassMetadata(get_class($resourceVersion));
    //             $this->em->persist($resourceVersion);
    //             $this->em->getUnitOfWork()->computeChangeSet($class, $resourceVersion);
    //         } else { // update
    //             foreach ($changeSets as $key => $changeSet) {
    //                 $resourceVersion = new ResourceVersion($entity, $entitySerialized, $this->security->getUser(), (($type == 'delete') ? 'delete' : $key), (($type == 'delete') ? null : $changeSet), $type, $this->productid);
    //                 $class           = $this->em->getClassMetadata(get_class($resourceVersion));
    //                 $this->em->persist($resourceVersion);
    //                 $this->em->getUnitOfWork()->computeChangeSet($class, $resourceVersion);
    //             }
    //         }
    //     }
    // }
}
