<?php
namespace App\Listener;
/*
 * kohinos_cooperatic
 * Copyright (C) 2019-2020  ADML63
 * Copyright (C) 2020- Cooperatic
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 

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_ADMIN_SIEGE');
                        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_ADMIN_SIEGE');
                        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);
                        }
                    }
                }
            }
        }
    }
}
