<?php

namespace AppBundle\Controller;

use AppBundle\Entity\DemandePEE;
use AppBundle\Entity\Module;
use AppBundle\Entity\OperationPEE;
use AppBundle\Entity\User;
use AppBundle\Enum\DemandePEEState;
use AppBundle\Enum\DemandePEEType;
use AppBundle\Enum\OperationPEEState;
use AppBundle\Enum\UserType;
use AppBundle\Form\Type\Front\PEE\ProfDemandePEEStep1Type;
use AppBundle\Form\Type\Front\PEE\ProfDemandePEEStep2Type;
use AppBundle\Form\Type\Front\PEE\ProfDemandePEEStep3Type;
use AppBundle\Helper\OperationHelper;
use AppBundle\Helper\UserHelper;
use AppBundle\Mail\PeeMailer;
use AppBundle\Pdf\PdfGenerator;
use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class OperationPeeController extends Controller
{
    /**
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    /**
     * @var EntityManagerInterface
     */
    private $em;

    /**
     * @var PdfGenerator
     */
    private $pdfGenerator;

    /**
     * @var PeeMailer
     */
    private $peeMailer;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var UserManagerInterface
     */
    private $userManager;

    /**
     * @var SessionInterface
     */
    private $session;

    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * @var RouterInterface
     */
    private $router;

    
    public function __construct(
        EntityManagerInterface $em,
        EventDispatcherInterface $dispatcher,
        PdfGenerator $pdfGenerator,
        PeeMailer $peeMailer,
        TranslatorInterface $translator,
        UserManagerInterface $userManager,
        SessionInterface $session,
        ValidatorInterface $validator,
        RouterInterface $router
    )
    {
        $this->dispatcher = $dispatcher;
        $this->em = $em;
        $this->pdfGenerator = $pdfGenerator;
        $this->peeMailer = $peeMailer;
        $this->translator = $translator;
        $this->userManager = $userManager;
        $this->session = $session;
        $this->router = $router;
        $this->validator = $validator;
    }

    /**
     * Ajout d'une demande PEE
     *
     * @Route(
     *      "/espace-perso/demande-pee",
     *      name = "espace_perso_pee_add"
     * )
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function addAction(Request $request)
    {
        // Récupération des variables $formStep de l'URL
        $formStep = $request->query->getInt('step', 1);

        $url_step0 = $this->getUrlStep0();
        
        $user = $this->getUser();

        // Stock return path in session and redirect to login if user is anonymous
        if (!is_object($user) || !$user instanceof UserInterface) {
            $this->session->set('_return', base64_encode($this->generateUrl($request->get('_route'), $request->get('_route_params'), UrlGeneratorInterface::ABSOLUTE_URL)));

            return $this->redirectToRoute('fos_user_security_login');
        }

        if (UserType::TEACHER !== $user->getType()) {
            //throw $this->createAccessDeniedException();

            $this->addFlash('error', $this->translator->trans(
                'notice.user.access_denied',
                [],
                'notice'
            ));
            return $this->redirectToRoute('espace_perso');
        }

        $ope = new OperationPEE;
       
        $dateMinCniMandatory = null;



        // Mode Edit Demande - Force Opération
        if ($request->get('ope')) {
            $ope = $this->em->getRepository(OperationPEE::class)->find($request->get('ope'));
            $demande = $this->em->getRepository(DemandePEE::class)->findOneBy([
                'operationpee' => $ope,
                'cuser' => $user
            ]);
            $this->session->set('espace_perso_pee_add_operations', null);
        }

        if ($formStep == 3) {
            // On recherche si parmis les opérations sélectionnées une demande d'avoir une CNI
            $oChecked = $this->session->get('espace_perso_pee_add_operations', array());
            
            // Si on modifie notre demande à une opération on récupère l'id de l'ope
            
            if (!is_null($ope->getId())) {
                $oChecked = array($ope->getId());
            }
           
            if (!empty($oChecked)) {
                
                $datesCniMandatory = $this->em->getRepository(OperationPEE::class)->findIsCniIsMandatory($user, $oChecked);
                if (!empty($datesCniMandatory)) {
                    $dateMinCniMandatory = $datesCniMandatory[0];
                } else {
                    $dateMinCniMandatory = false;
                }

                $recto = $this->em->getRepository(User::class)->findOneByIdentityCard1($user);
                if (!empty($recto)) {
                    $CniRectoMandatory = $recto;
                } else {
                    $CniRectoMandatory = false;
                }

                $verso = $this->em->getRepository(User::class)->findOneByIdentityCard2($user);
                if (!empty($verso)) {
                    $CniVersoMandatory = $verso;
                } else {
                    $CniVersoMandatory = false;
                }
            }
        }
       
        $step0Valid = $this->validStep0($request, $ope);
        if ($step0Valid !== true) {
            return $step0Valid;
        }

        //Valid Prev step data
        //if ($request->getMethod() == Request::METHOD_GET) {
        $prevStepValid = $this->validPrevStep($request, $ope);
        if($prevStepValid !== true) {
            return $prevStepValid;
        }
        //}

        // Get Step Form
        $form = $this->getPEEForm($formStep, $ope, [
            'date' => $dateMinCniMandatory, 
            'recto' => $CniRectoMandatory, 
            'verso' => $CniVersooMandatory
        ]);
        
        $form->handleRequest($request);

        $dateInvalide = false;
        if ($dateMinCniMandatory && $formStep === 3) {
            $dateCNI = $request->request->get('prof_demande_pee_step3')['identityCardValidity'];

            $dateCNI = date_create_from_format('d/m/Y', $dateCNI);

            if ($dateCNI === false || $dateCNI < $dateMinCniMandatory['dateVisite']) {
                $dateInvalide = true;
            }
        }

        if ($form->isSubmitted() && $form->isValid() && (empty($dateMinCniMandatory) || !$dateInvalide)) {
            if ($formStep == 1 || $formStep == 2) {
                $event = new FormEvent($form, $request);
                $this->dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_SUCCESS, $event);

                $this->userManager->updateUser($user);

                return $this->redirectToRoute('espace_perso_pee_add', array(
                    'step'=>++$formStep
                ));
            } elseif ($formStep == 3) {

                $event = new FormEvent($form, $request);
                $this->dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_SUCCESS, $event);

                $user->setIsValideInfo(false);

                //$this->userManager->updateUser($user);

                if (!isset($demande) || !($demande instanceOf DemandePEE)) {
                    // @NOTE ONLY NEW REGISTRATION HERE

                    $operations = $this->em->getRepository(OperationPEE::class)->findOpenForApplication($user);

                    $oChecked = $this->session->get('espace_perso_pee_add_operations', array());
                    $oCerpepChecked = $this->session->get('espace_perso_pee_add_operations_cerpep', array());

                    $oAllowedForApplication = array_filter($operations, function(array $o) use ($oChecked) {
                        $o = $o['details'];

                        return in_array($o->getId(), $oChecked);
                    });

                    // Creation of the application and preparation of the mails that will be send to the teacher
                    $mails = array();
                    foreach ($oAllowedForApplication as $operation) {
                        $o = $operation['details'];

                        $demande = new DemandePEE;
                        $demande->setOperationpee($o);
                        $demande->setCuser($user);
                        $pdf = null;

                        if (in_array($o->getId(), $oCerpepChecked)) {
                            $demande->setType(DemandePEEType::CERPEP);
                        }

                        // Si le total des demandes au statut 'Inscrit' ou 'Pré-inscrit'
                        // est inférieur au nombre de places disponibles dans l'opération,
                        // alors la demande du prof a le statut 'Pré-inscrit'.
                        if ($operation['placesTaken'] < $o->getNbPeople()) {
                            $demande->setState(DemandePEEState::PREREGISTERED);
                        } else {
                            $demande->setState(DemandePEEState::WAITING);
                        }
                        $this->em->persist($demande);

                        $mails[] = [
                            'datevisite' => $o->getDateVisite(),
                            'starttime' => $o->getStartTime(),
                            'endtime' => $o->getEndTime(),
                            'company' => $o->getCompany(),
                            'site' => $o->getSite(),
                            'city' => $o->getCity(),
                            'state' => $demande->getState(),
                            'pdf' => $pdf
                        ];
                    }

                    $this->em->flush();

                    $_FILES = array(); // Reset - because error with AbstractMailer
                    // Send email
                    $this->peeMailer->confirmDemandes($user, $mails);

                    // Send flash message
                    // $mail_subject='Venez visiter le site cgenial.org';
                    // $mail_body = str_replace("\n", '%0D%0A', // Required for line break representation in the mailto: URL scheme
                    //     $this->renderView('Front/Mail/invitation.html.twig', array(
                    //         'firstname' => $user->getFirstname(),
                    //         'lastname' => $user->getLastname(),
                    //     ))
                    // );
                }

                $flashBagMessage = '<div class="confirm">';
                $flashBagMessage .= "<p><strong>Votre demande de participation à l'action <em>Professeurs en entreprise</em> a bien été enregistrée.</strong></p>";

                $flashBagMessage .= "<p>Nous nous efforçons de la traiter dans les meilleurs délais. Nous vous enverrons un email pour vous confirmer votre inscription définitive.</p>";

                // $flashBagMessage .= '<p><a class="btn btn-mailto" href="mailto:?subject='.$mail_subject.'&body='.$mail_body.'">Invitez vos amis à visiter notre site en 1 clic !</a></p>';
                $flashBagMessage .= '<div class="professeur" id="yesyoucan">
                <p>Souhaitez-vous participer à une autre opération ?</p>
                <p><a class="btn btn-demande-pee" href="'.$this->generateUrl('espace_perso_pee_add').'">Déposer une demande de participation à <em>Professeurs en entreprise</em></a></p>
                <p><a class="btn btn-demande-itdlc" href="'.$this->generateUrl('espace_perso_prof_itdlc_add').'">Déposer une demande de participation à <em>Ingénieurs et techniciens dans les classes</em></a></p>
                </div>';
                $flashBagMessage .= '</div>';

                $this->addFlash('info', $flashBagMessage);

                if (null === $response = $event->getResponse()) {
                    $response = $this->redirectToRoute('espace_perso_pee_add');
                }

                $this->dispatcher->dispatch(
                    FOSUserEvents::PROFILE_EDIT_COMPLETED,
                    new FilterUserResponseEvent($user, $request, $response)
                );

                $this->session->set('espace_perso_pee_add_operations_cerpep', null);
                $this->session->set('espace_perso_pee_add_operations', null);

                if ($user->getType() == UserType::TEACHER) {
                    return new RedirectResponse($this->generateUrl('espace_perso_pee'));
                }
                elseif ($user->getType() == UserType::ENGINEER) {
                    return new RedirectResponse($this->generateUrl('espace_perso_operations'));
                }

                return new RedirectResponse($this->generateUrl('espace_perso'));
            }
        } else if ($form->isSubmitted()) { // Form submitted but not valid
            $this->addFlash('error', "Votre demande n'a pu être effectuée car certaines informations ont été mal renseignées. Veuillez les vérifier, puis enregistrez à nouveau votre demande.");
        }

        $academies = UserHelper::getAcademyList();

        return $this->render('Front/Demande/PEE/form.html.twig', array(
            'academies' => $academies,
            'form' => $form->createView(),
            'type'=>  'PEE',
            'mode'=>  'add',
            'step'=>  $formStep,
            'dateMinCniMandatory'=> !empty($dateMinCniMandatory) ? $dateMinCniMandatory['dateVisite'] : null,
            'dateInvalide'=> $dateInvalide
        ));
    }

    /**
     * Save Operation from MapPee into session and redirect to addAction
     *
     * @Route(
     *      "/demande-pee/sauvegarder-operations",
     *      name = "espace_perso_pee_add_operations"
     * )
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function saveSessionAction(Request $request)
    {

        $oChecked = $request->get('operation') ?? [] ;
        $oCerpepChecked = $request->get('operation_cerpep') ?? [] ;

        // Save in session
        $this->session->set('espace_perso_pee_add_operations_cerpep', $oCerpepChecked);
        $this->session->set('espace_perso_pee_add_operations', $oChecked);

        if ( !empty($oChecked) ) {
            return $this->redirectToRoute('espace_perso_pee_add');
        }
        else {
            // Select operations first => Redirect to module map pee page

            $this->addFlash('mappee_error', $this->translator->trans(
                'notice.operationPee.registration.selection.empty',
                [],
                'notice'
            ));

            return $this->redirect($this->getUrlStep0());
        }
    }

    /**
     * DEPRECATED:
     * Liste les opérations PEE actives et qui ne sont pas fermées
     *
     * @Route(
     *      "/espace-perso/liste-pee",
     *      name = "espace_perso_pee_list"
     * )
     * @Method({"POST"})
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function listAction(Request $request)
    {
        $user = $this->getUser();
        if (UserType::TEACHER !== $user->getType()) {
            throw $this->createAccessDeniedException();
        }

        $academyName = $request->get('academy_name');

        $filters = array();
        if (!empty($academyName)) {
            $filters['academy'] = $academyName;
        }

        $operations = $this->em->getRepository(OperationPEE::class)->findOpenForApplication($user, $filters);

        $userOperationsQty = OperationHelper::getUserApplicationQty($operations);

        return $this->render('Front/Demande/_component/listPee.html.twig', array(
            'academy_name' => $academyName,
            'operations' => $operations,
            'registeredQty' => $userOperationsQty,
        ));
    }

    /**
     * Generate a printable version of a PEE operation.
     *
     * @Route(
     *      "/operation-pee/{id}/download.{_format}",
     *      name = "operation_pee_download",
     *      requirements = {"_format": "pdf"},
     *      defaults = {"_format": "pdf"}
     * )
     *
     * @param Request $request
     * @param OperationPEE $o
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function downloadAction(Request $request, OperationPEE $o)
    {
        return $this->pdfGenerator->generateOperationPee($o, $request->getRequestFormat());
    }


    /**
     * Get PEE step Form
     *
     * @param int|int $formStep
     * @param OperationPEE $ope
     * @param null $isCniMandatory
     * @return IngeDemandePEEStep1Type|IngeDemandePEEStep2Type|IngeDemandePEEStep3Type|ProfDemandePEEStep1Type|ProfDemandePEEStep2Type|ProfDemandePEEStep3Type
     */
    private function getPEEForm(int $formStep, OperationPEE $ope = null, $cni = null) {
        $user = $this->getUser();

        // if (UserType::TEACHER === $user->getType()) {
            // Get Step Form
        switch ($formStep) {
            case 2:
                $form = $this->createForm(ProfDemandePEEStep2Type::class, $user);
                break;

            case 3:
                $options = array();

                if ($cni) {
                    $options = [
                        'cni_mandatory' => $cni['date'],
                        'cni_recto' => $cni['recto'],
                        'cni_verso' => $cni['verso'],
                    ];
                }

                $form = $this->createForm(ProfDemandePEEStep3Type::class, $user, $options);
                break;
                    
            default:
            case 1:
                $form = $this->createForm(ProfDemandePEEStep1Type::class, $user);
                break;

        }
        // }
        // else {
        //     // Get Step Form
        //     switch($formStep) {
        //         case 2 :
        //                 $form = $this->createForm(IngeDemandePEEStep2Type::class, $user);
        //                 break;
        //         case 3 :
        //                 $form = $this->createForm(IngeDemandePEEStep3Type::class, $user);
        //                 break;
        //         default:
        //         case 1 :
        //                 $form = $this->createForm(IngeDemandePEEStep1Type::class, $user);
        //                 break;

        //     }
        // }

        return $form;
    }

    /**
     * Valid prev data
     *
     * @param Request $request
     * @param OperationPEE $ope
     * @return true|RedirectResponse
     */
    private function validPrevStep(Request $request, OperationPEE $ope = null) {
        
        // Récupération des variables $formStep de l'URL
        $formStep = $request->query->getInt('step', 1);

        while ($formStep > 1) {
            $formStep--;

            $prevForm = $this->getPEEForm($formStep, $ope);
            //$fields = $prevForm->all();

            $options = $prevForm->getConfig()->getOptions();
            
            $prevStepValid = $this->validator->validate($prevForm->getData(), null, $options['validation_groups']);
            
            if (count($prevStepValid) > 0) {
                if ($formStep > 1) {
                    return $this->redirectToRoute($request->get('_route'), array(
                        'step'=>$formStep
                    ));
                }
                else {
                    return $this->redirectToRoute($request->get('_route'));    
                }
                
            } 
        }

        return true;
    }

    /**
     * Valid $oChecked data
     *
     * @param Request $request
     * @param OperationPEE $ope
     * @return true|RedirectResponse
     */
    private function validStep0(Request $request, OperationPEE $ope = null) {
        // Récupération des variables $formStep de l'URL
        $formStep = $request->query->getInt('step', 1);

        $url_step0 = $this->getUrlStep0();
        
        $user = $this->getUser(); 
        OperationHelper::setUser($user);  

        $limit = $this->getParameter('pee.application.max_per_user');
        $operations = $this->em->getRepository(OperationPEE::class)->findOpenForApplication($user);
        
        // Filter the operations with applications (from the connected user, see findOpenForApplication() above)
        $userOperations = OperationHelper::filterByUserApplication($operations);

        // Get the number of user applications
        $userOperationsQty = OperationHelper::getUserApplicationQty($operations);

        $oChecked = $request->get('operation') ?? ( $this->session->get('espace_perso_pee_add_operations') ?? [] );
        $oCerpepChecked = $request->get('operation_cerpep') ?? ( $this->session->get('espace_perso_pee_add_operations_cerpep') ?? [] );

        if ( !empty($oCerpepChecked) && count($oCerpepChecked) > 0 ) {
            //$session->set('espace_perso_pee_add_operations_cerpep', $oCerpepChecked); 
            // foreach ($oCerpepChecked as &$o) {
            //     $o = $this->em->getRepository(OperationPEE::class)->findOneById($o);
            // } 
        }
   
        if ( !empty($oChecked) && count($oChecked) > 0) {
            //$session->set('espace_perso_pee_add_operations', $oChecked);
            // foreach ($oChecked as &$o) {
            //     $o = $this->em->getRepository(OperationPEE::class)->findOneById($o);
            // } 

            // Redirect: the teacher has already reached the limit of applications allowed per teacher
            if ($userOperationsQty >= $limit) {
                $this->addFlash('mappee_error', $this->translator->trans(
                    'notice.operationPee.registration.limit.reached',
                    ['%limit%' => $limit],
                    'notice'
                ));

                //return $this->redirectToRoute('espace_perso_pee_add');
                return $this->redirect($url_step0); 
            }

            // Check if the teacher can apply to the operations he checked:
            // - operation is open for application
            // - teacher does not have an application for the operation OR the application is in a WITHDRAWAL state
            $oAllowedForApplication = array_filter($operations, function(array $o) use ($oChecked,$user) {
                /** @var OperationPEE $o */
                $o = $o['details'];
                
                // return in_array($o->getId(), $oChecked)
                //     && (0 === $o->getDemandepee()->count() || DemandePEEState::WITHDRAWAL === $o->getDemandepee()->first()->getState())
                // ;

                if (in_array($o->getId(), $oChecked)) {
                    $demandesPee = $o->getDemandepee();

                    if ($demandesPee->count() > 0) {
                        foreach ($demandesPee as $demandePee) {
                            if ( $user instanceOf User && $demandePee->getCuser()->getId() == $user->getId() && DemandePEEState::WITHDRAWAL === $demandePee->getState()) {
                                return true;
                            }
                        }
                    }
                    else {
                        return true;
                    }
                }
                
                return false;
            });

            $oAllowedForApplicationQty = count($oAllowedForApplication);

            // Redirect: no operation allowed for application
            if (0 === $oAllowedForApplicationQty) {
                // The teacher did not check any OperationPEE, but checked at least 1 CERPEP option
                if ($oCerpepCheckedQty = count($oCerpepChecked) > 0) { 
                    $this->addFlash('mappee_error', $this->translator->transchoice(
                        'notice.operationPee.registration.cerpep.only',
                        $oCerpepCheckedQty,
                        [],
                        'notice'
                    ));
                }

                // return $this->redirectToRoute('espace_perso_pee_add');
                return $this->redirect($url_step0); 
            }


            // Redirect: the user will overtake the limit of applications per teacher with the number of operations he checked.
            // In that case, $oAllowedForApplicationQty is always > 1,
            // because if = 1, the user has alreaby been redirect by reaching the limit
            if ($userOperationsQty + $oAllowedForApplicationQty > $limit) {
                $remaining = $limit - $userOperationsQty;

                if (0 === $userOperationsQty) {
                    $notice = $this->translator->transchoice(
                        'notice.operationPee.registration.limit.overtake.inOneGo',
                        $limit,
                        ['%limit%' => $limit],
                        'notice'
                    );
                } else {
                    $notice = $this->translator->transchoice(
                        'notice.operationPee.registration.limit.overtake.inSeveralGo',
                        $remaining,
                        ['%remaining%' => $remaining],
                        'notice'
                    ) . ' (' . lcfirst($this->translator->transchoice(
                        'notice.operationPee.registration.limit.status',
                        $userOperationsQty,
                        ['%registered%' => $userOperationsQty],
                        'notice'
                    )) . ').';
                }

                $this->addFlash('mappee_error', $notice);

                // return $this->redirectToRoute('espace_perso_pee_add');
                return $this->redirect($url_step0); 
            }

            // Check that the user doesn't want to apply for several operations the same day.
            // We suppose that the dates of the operations he already applied for are different;
            // so we need to only check the dates he checked in the form.
            // Algorithm behavior:
            // 1. Retrieve operations visit dates for which the user already has an application
            // 2. Add to this list the visit dates of the operations he checked
            // 3. Make the collected dates unique (using array_unique())
            // 4. Compare the number of dates between the full list and the unique list
            $datesTaken = [];
            foreach ($userOperations as $o) {
                if (null !== $o['details']->getDateVisite()) {
                    $datesTaken[] = $o['details']->getDateVisite()->format('Ymd');
                }
            }
            foreach ($oAllowedForApplication as $o) {
                if (null !== $o['details']->getDateVisite()) {
                    $datesTaken[] = $o['details']->getDateVisite()->format('Ymd');
                }
            }
            $datesTakenUnique = array_unique($datesTaken);

            // Redirect: the user want to apply for different operations the same day
            if (count($datesTaken) !== count($datesTakenUnique)) {
                $this->addFlash('mappee_error', nl2br($this->translator->trans(
                    'notice.operationPee.registration.date_identical',
                    array('%mail%' => '<a href="mailto:'.$this->getParameter('cgenial.mail.pee.registration').'">'.$this->getParameter('cgenial.mail.pee.registration').'</a>'),
                    'notice'
                )));

                // return $this->redirectToRoute('espace_perso_pee_add');
                return $this->redirect($url_step0); 
            }

            return true;
        }
        else if ($ope instanceOf OperationPEE and $ope->getId()) {
            // Mode Edit : Just check if User is allowed to edit this operation
            
            $operations = [ $ope ];

            // Check if the teacher can apply to the operations he checked:
            // - operation is open for application
            // - teacher does not have an application for the operation OR the application is in a WITHDRAWAL state
            $oAllowedForApplication = array_filter($operations, function(OperationPEE $o) use ($user) {
                
                $demandesPee = $o->getDemandepee();

                if ($demandesPee->count() > 0) {
                    foreach ($demandesPee as $demandePee) {
                        if ( $user instanceOf User && $demandePee->getCuser()->getId() == $user->getId() && DemandePEEState::WITHDRAWAL !== $demandePee->getState()) {
                            return true;
                        }
                    }
                }

                return false;
            });

            $oAllowedForApplicationQty = count($oAllowedForApplication);

            // Redirect: no operation allowed for application
            if (0 === $oAllowedForApplicationQty) {
                $this->addFlash('mappee_error', $this->translator->trans(
                    'notice.operationPee.registration.not_allowed',
                    ['%mail%' => $this->getParameter('cgenial.mail.pee.registration')],
                    'notice'
                ));

                // return $this->redirectToRoute('espace_perso_pee_add');
                return $this->redirect($url_step0); 
            }

            return true;
        }
        else {
            // Select operations first => Redirect to module map pee page
            
            $this->addFlash('mappee_error', $this->translator->trans(
                'notice.operationPee.registration.selection.empty',
                [],
                'notice'
            ));

            return $this->redirect($url_step0);   
        }
    }

    /**
     * Get page url with map_pee module
     *
     * @return string
     */
    private function getUrlStep0() {
        
        $module = $this->em->getRepository(Module::class)->findOneByType('map_pee');

        if (!empty($module) && !empty($module->getMenu()) && !empty($module->getMenu()[0])) {
            $menu = $module->getMenu()[0];
            $parent = $menu->getParent();
            $parentTop = $parent->getParent();

            if (!empty($menu)) {
                $_route = 'template';
                $routeParams['id'] = $menu->getId();
                $routeParams['title'] = $menu->getSlug();

                if (!empty($parent)) {
                    $_route = 'template_level2';
                    $routeParams['idlevel1'] = $parent->getId();
                    $routeParams['titlelevel1'] = $parent->getSlug();

                    if (!empty($parentTop)) {
                        $_route = 'template_level3';
                        $routeParams['idlevel1'] = $parentTop->getId();
                        $routeParams['titlelevel1'] = $parentTop->getSlug();
                        $routeParams['idlevel2'] = $parent->getId();
                        $routeParams['titlelevel2'] = $parent->getSlug();
                    }
                }
            }
            
            $url = $this->generateUrl($_route, $routeParams);
        }
        else {
            $url = $this->generateUrl('_welcome');
        }

        return $url.'#module-mappee';
    }



    /**
     * Modal : Confirmer annulation Demande
     *
     * @Route(
     *      "/espace-perso/modal-cancel-demande-pee/{demande}",
     *      name = "modal_cancel_demande_pee"
     * )
     *
     * @param Request $request
     * @param DemandePEE $demande
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function modalCancelDemandePEEAction(Request $request, DemandePEE $demande)
    {
        // Check rights here
        $user = $this->getUser();
        
        if ($user === null || $user->getId() !== $demande->getCuser()->getId()) {
            throw $this->createAccessDeniedException();    
        }
        
        return $this->render('Front/Render/Modal/PEE/cancel.demande.html.twig', array(
            'demande' => $demande
        ));
    }


    /**
     * Annulation Demande
     *
     * @Route(
     *      "/espace-perso/cancel-demande-pee/{demande}",
     *      name = "cancel_demande_pee"
     * )
     *
     * @param Request $request
     * @param DemandePEE $demande
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function cancelDemandePEEAction(Request $request, DemandePEE $demande)
    {
        // Check rights here
        $user = $this->getUser();
        
        if ($user === null || $user->getId() !== $demande->getCuser()->getId()) {
            throw $this->createAccessDeniedException();    
        }

        $demande->setState(DemandePEEState::WITHDRAWAL);

        $this->session->getFlashBag()->add('success', $this->translator->trans(
            'notice.demandePEE.user.withdrawal',
            [],
            'notice'
        ));
        
        $this->em->persist($demande);
        $this->em->flush();

        return new JsonResponse(array('result' => true));
    }

    /**
     * Modal : Confirmer annulation Opération
     *
     * @Route(
     *      "/espace-perso/modal-cancel-operation-pee/{ope}",
     *      name = "modal_cancel_operation_pee"
     * )
     *
     * @param Request $request
     * @param OperationPEE $ope
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function modalCancelOperationPEEAction(Request $request, OperationPEE $ope)
    {
        // Check rights here
        $user = $this->getUser();
        
        // if ($user === null || $user->getId() !== $ope->getCuser()->getId()) {
        if ($user === null) {
            throw $this->createAccessDeniedException();    
        }
        
        return $this->render('Front/Render/Modal/PEE/cancel.operation.html.twig', array(
            'ope' => $ope
        ));
    }


    /**
     * Annulation Opération
     *
     * @Route(
     *      "/espace-perso/cancel-operation-pee/{ope}",
     *      name = "cancel_operation_pee"
     * )
     *
     * @param Request $request
     * @param OperationPEE $ope
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function cancelOperationPEEAction(Request $request, OperationPEE $ope)
    {
        // Check rights here
        $user = $this->getUser();
        
        //if ($user === null || $user->getId() !== $ope->getCuser()->getId()) {
        if ($user === null) {
            throw $this->createAccessDeniedException();    
        }

        $ope->setState(OperationPEEState::CANCELLED);
        
        $this->em->persist($ope);
        $this->em->flush();

        //Send Email to Admin
        $this->peeMailer->cancelOperation($ope, $user);

        return new JsonResponse(array('result' => true));
    }


    /**
     * Annulation Opération
     *
     * @Route(
     *      "/cefpep/{demandePEE}/{emailUserHashed}",
     *      name = "cerpepdf"
     * )
     *
     * @param Request $request
     * @param DemandePEE $ope
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function cerpepPdfAction(Request $request, DemandePEE $demandePEE, $emailUserHashed)
    {

        if (sha1($demandePEE->getCuser()->getEmail()) != $emailUserHashed) {
            throw $this->createAccessDeniedException();
        }

        $dispositifs = $this->getParameter('dispositif_CEFPEP');
        $opeAcademy = $demandePEE->getOperationpee()->getAcademy();
        $opeZipCode = $demandePEE->getOperationpee()->getZipcode();
        $numerDispoCEFPEP = null;

        if (!empty($dispositifs['academies']) && !empty($opeAcademy) && !empty($dispositifs['academies'][$opeAcademy])) {
            $numerDispoCEFPEP = $dispositifs['academies'][$opeAcademy];
        } else if (!empty($dispositifs['departements']) && !empty($opeZipCode)) {

            if (substr($opeZipCode,0,2) == 97) {
                $opeZipCode = substr($opeZipCode,0,3);
            } else {
                $opeZipCode = substr($opeZipCode,0,2);
            }

            $numerDispoCEFPEP = !empty($dispositifs['departements'][$opeZipCode]) ? $dispositifs['departements'][$opeZipCode] : '';
        }

       // PDF
        return $this->pdfGenerator->generateCefpep($demandePEE, 'pdf', $numerDispoCEFPEP);

        // VUE HTML
        //return $this->render('Admin/Ope/PEE/printCerfep.html.twig', ['demande' => $demandePEE]);
    }

}
