<?php

namespace AppBundle\Controller\Admin;

use AppBundle\Entity\Availability;
use AppBundle\Entity\Interest;
use AppBundle\Entity\MerITDLC;
use AppBundle\Entity\MerHistoryITDLC;
use AppBundle\Entity\OperationITDLC;
use AppBundle\Entity\Preference;
use AppBundle\Entity\User;
use AppBundle\Enum\EmployeesInCharge;
use AppBundle\Enum\OperationITDLCState;
use AppBundle\Enum\OperationITDLCType as OperationITDLCTypeEnum;
use AppBundle\Enum\UserType;
use AppBundle\Export\OperationItdlcExporter;
use AppBundle\Form\Type\AvailabilityHebdoType;
use AppBundle\Form\Type\AvailabilityPrecisType;
use AppBundle\Form\Type\ITDLC\OperationITDLCType;
use AppBundle\Form\Type\MailPreviewType;
use AppBundle\Mail\ItdlcMailer;
use AppBundle\Mail\Model\MailPreview;
use AppBundle\Repository\UserRepository;
use AppBundle\Translation\ConstTranslator;
use Cocur\Slugify\Slugify;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Translation\TranslatorInterface;

class OperationITDLCController extends Controller
{
    /**
     * @var EntityManagerInterface
     */
    private $em;

    /**
     * @var ItdlcMailer
     */
    private $itdlcMailer;

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

    /**
     * @var OperationItdlcExporter
     */
    private $operationItdlcExporter;

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

    /**
     * @var ConstTranslator
     */
    private $utils;
    
    public function __construct(
        EntityManagerInterface $em,
        ItdlcMailer $itdlcMailer,
        OperationItdlcExporter $operationItdlcExporter,
        SessionInterface $session,
        TranslatorInterface $translator,
        ConstTranslator $utils
    )
    {
        $this->em = $em;
        $this->itdlcMailer = $itdlcMailer;
        $this->operationItdlcExporter = $operationItdlcExporter;
        $this->session = $session;
        $this->translator = $translator;
        $this->utils = $utils;
    }

    /**
     * Liste les demandes ITDLC
     *
     * @Route(
     *      "/demande-itdlc/list/{user_type}/{page}",
     *      requirements = {"page": "\d+", "user_type":"teacher|engineer"},
     *      name = "admin_demande_itdlc"
     * )
     * @param Request $request
     * @param string $user_type
     * @param int $page
     * @return Response
     */
    public function listDemandeAction(Request $request, string $user_type = 'teacher', int $page = 1)
    {
        $academy = null;
        $resultsMaxPerPage = $this->getParameter('results.admin.max_per_page');
        $userAcademies = array();

        $userName = $request->get('user_name');
        $userAcademy = $request->get('user_academy');
        $demandeState = $request->get('demande_state');
        $demandeEmployee = $request->get('demande_whoisincharge');

        // Mise à jour de la session avec les nouvelles valeurs
        $this->session->set($request->get('_route'), array(
            'user_type' => $user_type,
            'page' => $page,
            'user_name' => $userName,
            'user_academy' => $userAcademy,
            'demande_state' => $demandeState,
            'demande_whoisincharge' => $demandeEmployee,
        ));

        // Création de la requête
        $qb = $this->em->createQueryBuilder();
        $qb
            ->setFirstResult(($page - 1) * $resultsMaxPerPage)
            ->setMaxResults($resultsMaxPerPage);
        if (UserType::TEACHER === $user_type) { // Professors
            $userAcademies = $this->em->getRepository('AppBundle:User')->findAcademies();

            $qb
                ->select('o')
                ->from('AppBundle:OperationITDLC', 'o')
                ->leftJoin('o.prof', 'u')
                ->where('o.type = :o_type')
                ->orderBy('o.created', 'DESC')
                ->addOrderBy('o.id', 'DESC')
                ->setParameter('o_type', OperationITDLCTypeEnum::DEMANDE);
            if (!empty($userAcademy)) {
                $qb
                    ->andWhere('u.academy = :u_academy')
                    ->setParameter('u_academy', $userAcademy);
            }
            if (!empty($demandeState)) {
                $qb
                    ->andWhere('o.state = :o_state')
                    ->setParameter('o_state', $demandeState);
            }
            if (!empty($demandeEmployee)) {
                $qb
                    ->andWhere('o.whoIsInCharge = :o_employee')
                    ->setParameter('o_employee', $demandeEmployee);
            }
        } else {	// Engineer
            $user_type = UserType::ENGINEER;

            $qb->select('u')
                ->from('AppBundle:User', 'u')
                ->where('u.nbContribution != 0')
                ->andWhere($qb->expr()->isNotNull('u.nbContribution'))
                ->orderBy('u.created', 'DESC')
                ->addOrderBy('u.id', 'DESC');
        }
        if (!empty($userName)) {
            $qb->andWhere($qb->expr()->orX(
                $qb->expr()->like('LOWER(u.firstname)', ':u_firstname')
                ,$qb->expr()->like('LOWER(u.lastname)', ':u_lastname')
            ))
            ->setParameter('u_firstname', "%".mb_strtolower($userName)."%")
            ->setParameter('u_lastname', "%".mb_strtolower($userName)."%");
        }

        // Constructeur pagination
        $ope = new Paginator($qb);
        $nb_results = count($ope);
        $nbPage = $nb_results / $resultsMaxPerPage;
        $pagination = array();
        for ($i = 1; $i < $nbPage + 1; $i++) {
            array_push($pagination, $i);
        }

        $demandeStates = $this->utils->trans(OperationITDLCState::class);
        
        // $demandeEmployees = $this->utils->trans(EmployeesInCharge::class);
        $demandeEmployees = EmployeesInCharge::getConstants(); 

        return $this->render('Admin/Ope/ITDLC/indexDemande.html.twig', array(
            'ope' => $ope,
            'user_type' => $user_type,
            'pagination' => $pagination,
            'pageactuelle' => $page,
            'user_name' => $userName,
            'user_academies' => $userAcademies,
            'user_academy' => $userAcademy,
            'demande_states' => $demandeStates,
            'demande_state' => $demandeState,
            'demande_employees' => $demandeEmployees,
            'demande_employee' => $demandeEmployee,
            'nb_results' => $nb_results,
        ));
    }

    /**
     * Exporte la liste des demandes ITDLC d'un type d'utilisateur.
     * Le fichier exporté est au format Excel 2007.
     *
     * @Route(
     *      "/demande-itdlc/export/{user_type}",
     *      name = "admin_demande_itdlc_export",
     *      requirements = {"user_type"="teacher|engineer"}
     * )
     * @param Request $request
     * @param string  $user_type
     * @return StreamedResponse
     * @throws PhpSpreadsheetException
     * @throws \Doctrine\ORM\NoResultException
     * @throws \Doctrine\ORM\NonUniqueResultException
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public function exportDemandeAction(Request $request, string $user_type = 'teacher')
    {
        $filename = 'demandesITDLC_'.(new Slugify)->slugify($this->translator->trans('word.type.user.' . $user_type . '.label', array(), 'word')) .'.xlsx';

        // Récupération des paramètres GET
        $userName = $request->query->get('user_name');
        $userAcademy = $request->query->get('user_academy');

        $demandeState = $request->query->get('demande_state');
        $demandeEmployee = $request->query->get('demande_whoisincharge');

        // Création de la requête
        $qb = $this->em->createQueryBuilder();
        if (UserType::TEACHER === $user_type) {
            $qb
                ->select('o')
                ->from('AppBundle:OperationITDLC', 'o')
                ->leftJoin('o.prof', 'u')
                ->where('o.type = :o_type')
                ->orderBy('o.created', 'DESC')
                ->addOrderBy('o.id', 'DESC')
                ->setParameter('o_type', OperationITDLCTypeEnum::DEMANDE);
            if ($userAcademy) {
                $qb
                    ->andWhere('u.academy = :u_academy')
                    ->setParameter('u_academy', $userAcademy);
            }

            if ($demandeState) {
                $qb
                    ->andWhere('o.state = :o_state')
                    ->setParameter('o_state', $demandeState);
            }
    
            if ($demandeEmployee) {
                $qb
                    ->andWhere('o.whoIsInCharge = :o_whoisincharge')
                    ->setParameter('o_whoisincharge', $demandeEmployee);
            }
        } else {    // Engineer
            // Liste de tous les ingénieurs ayant effectué une demande ITDLC.
            $qb = $this->em->createQueryBuilder();
            $qb
                ->select('u')
                ->from(User::class, 'u')
                ->where('u.nbContribution != 0')
                ->andWhere('u.nbContribution IS NOT NULL')
                ->orderBy('u.created', 'DESC')
                ->addOrderBy('u.id', 'DESC');
        }

        if ($userName) {
            $qb
                ->andWhere($qb->expr()->orX(
                    $qb->expr()->like('LOWER(u.firstname)', ':u_firstname'),
                    $qb->expr()->like('LOWER(u.lastname)', ':u_lastname')
                ))
                ->setParameter('u_firstname', "%".mb_strtolower($userName)."%")
                ->setParameter('u_lastname', "%".mb_strtolower($userName)."%");
        }

        $applications = $qb->getQuery()->getResult();

        return $this->operationItdlcExporter->exportApplications($applications, $filename);
    }

    /**
     * Modification d'une demande ITDLC d'un professeur
     *
     * @Route(
     *      "/demande-itdlc/edit/{id}",
     *      name = "admin_demande_itdlc_professeur_edit"
     * )
     * @param Request $request
     * @param OperationITDLC $operation
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editTeacherApplicationAction(Request $request, OperationITDLC $operation)
    {
        /* Recherche si une demande est rattachée à une entrée mer_itdlc, si non créer un lien */
        $mer = $this->em->getRepository(MerITDLC::class)->findByOpe($operation);
        if (!$mer) {
            $mer = new MerITDLC($operation);
            $mer->setOpe($operation);
            if ($operation->getInge()) {
                $mer->setInge($operation->getInge());
            }
            $mer->setFirstDate(new \DateTime());
            $mer->setFirstDateStartTime(null);
            $mer->setFirstDateEndTime(null);

            $mer->setSecondDate(new \DateTime());
            $mer->setSecondDateStartTime(null);
            $mer->setSecondDateEndTime(null);

            $mer->setThirdDate(new \DateTime());
            $mer->setThirdDateStartTime(null);
            $mer->setThirdDateEndTime(null);

            $operation->addMerITDLC($mer);
            $this->em->persist($operation);
            $this->em->flush();
        }
        
        $statePrevious = $operation->getState();

        $form = $this->createForm(OperationITDLCType::class, $operation);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->em->persist($operation);
            $this->em->flush();

            // The application has been changed into an operation: redirect to the dedicated editing page
            if (OperationITDLCTypeEnum::OPERATION === $operation->getType()) {
                return $this->redirectToRoute('admin_operation_itdlc_edit', [
                    'id' => $operation->getId(),
                ]);
            }

            // Application: the state has changed for the NO_CONTRIBUTOR one
            
            
            if ($statePrevious !== $operation->getState() && OperationITDLCState::NO_CONTRIBUTOR == $operation->getState()) {
                $this->addFlash('fancybox-load', $this->generateUrl('admin_operation_itdlc_mail_state', [
                    'id' => $operation->getId(),
                    'statePrevious' => $statePrevious,
                ]));
            }
            

            $this->addFlash('success', $this->translator->trans('notice.demandeITDLC.updated', [], 'notice'));

            return $this->redirectToRoute('admin_demande_itdlc_professeur_edit', [
                'id' => $operation->getId(),
            ]);
        }

        $preferences = $this->em->getRepository(Preference::class)->findBy(['mainUser' => $operation->getProf()], ['id' => 'ASC']);

        return $this->render('Admin/Ope/ITDLC/editDemandeProf.html.twig', array(
            'form' => $form->createView(),
            'ope' => $operation,
            'dates' => $operation->getAvailability(),
            'preferences' => $preferences,
        ));
    }


     /**
     * Réponse d'une mise en relation d'une ITDLC
     *
     * @Route(
     *      "/espace-perso/reponse-merITDLC/{mer}/{reponse}",
     *      name = "admin_merITDLC_reponse"
     * )
     *
     * @param Request $request
     * @param MerITDLC $mer
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function answerMerITDLCAction(Request $request, MerITDLC $mer, $reponse)
    {
        $ope = $mer->getOpe();

        if ($ope->getState() !=  OperationITDLCState::ONGOING)
        {
            $this->addFlash('warning', "Attention ! La demande doit être placée dans l'état 'En cours de traitement' pour pouvoir être transformée en opération ");
            return $this->redirectToRoute('admin_demande_itdlc_professeur_edit', ['id' => $ope->getId()]);
        }

        if (is_null($ope->getInge()))
        {
            $this->addFlash('warning', "Attention ! Il faut choisir un intervenant avant de transformer cette demande en opération");
            return $this->redirectToRoute('admin_demande_itdlc_professeur_edit', ['id' => $ope->getId()]);
        }

        $user = $this->getUser();
        $mer->setAnswerDate(new \DateTime());
        
        $mer->setInge($ope->getInge());

        $ope->removeAllAvailability();

        switch ($reponse) {
            case 'date1':
            case 'date2':
            case 'date3':
                $availability = new Availability();
                $mer->setAnswer($reponse);
                if ($reponse === "date1") {
                    $availability->setDateVisite($mer->getFirstDate());
                    $availability->setStartTime($mer->getFirstDateStartTime());
                    $availability->setEndTime($mer->getFirstDateEndTime());
                } else if ($reponse == "date2") {
                    $availability->setDateVisite($mer->getSecondDate());
                    $availability->setStartTime($mer->getSecondDateStartTime());
                    $availability->setEndTime($mer->getSecondDateEndTime());
                } else {
                    $availability->setDateVisite($mer->getThirdDate());
                    $availability->setStartTime($mer->getThirdDateStartTime());
                    $availability->setEndTime($mer->getThirdDateEndTime());
                }

                $merHistory = new MerHistoryITDLC();
                $merHistory->setInfos("Date du " . $availability->getDateVisite()->format('d/m/Y') . " de " . $availability->getStartTime()->format('H\hi') . " à " . $availability->getEndTime()->format('H\hi') . " acceptée par " . $user->getFirstName() . " " . $user->getLastName());
                $mer->addHistory($merHistory);

                $ope->addAvailability($availability);
                $ope->setType(OperationITDLCTypeEnum::OPERATION);
                $dateSending = new \DateTime();
                // Update DB about the date when the mail were send
                $ope->setDateMail($dateSending);
                $this->em->persist($mer);
                $this->em->persist($ope);

                // Envoi d'un email au professeur que l'ingenieur a accepté
                $reponses = $this->itdlcMailer->sendITDLCAccepted($mer);
                if ($reponses['teacher'] && $reponses['engineer']) {
                    $this->em->flush();
                    $this->addFlash('success', 'Votre réponse a été enregistrée');
                }
                break;
        }
        $this->addFlash('success', $this->translator->trans('notice.operationITDLC.updated', [], 'notice'));
        return $this->redirectToRoute('admin_operation_itdlc');
    }


    /**
     * Recherche d'un ingénieur pour la demande ITDLC d'un professeur
     *
     * @Route(
     *      "/demande-itdlc-p/search/{id}",
     *      name = "admin_demande_itdlc_professeur_search"
     * )
     * @param OperationITDLC $demandeItdlc
     * @return Response
     */
    public function searchDemandeProfAction(OperationITDLC $demandeItdlc)
    {
        if (UserType::TEACHER !== $demandeItdlc->getProf()->getType()) {
            throw $this->createAccessDeniedException();
        }

        $preferences = $this->em->getRepository(Preference::class)->findPreferredByActiveUser($demandeItdlc->getProf());

        return $this->render('Admin/Ope/ITDLC/searchDemandeProf.html.twig', array(
            'ope' => $demandeItdlc,
            'dates' => $demandeItdlc->getAvailability(),
            'preferences' => $preferences,
        ));
    }

    /**
     * Recherche d'un professeur pour la demande ITDLC d'un ingénieur
     *
     * @Route(
     *      "/demande-itdlc-i/search/{user}",
     *      name = "admin_demande_itdlc_ingenieur_search"
     * )
     * @param User $user
     * @return Response
     */
    public function searchDemandeIngeAction(User $user)
    {
        if (UserType::ENGINEER !== $user->getType()) {
            throw $this->createAccessDeniedException();
        }

        $preferences = $this->em->getRepository(Preference::class)->findPreferredByActiveUser($user);

        return $this->render('Admin/Ope/ITDLC/searchDemandeInge.html.twig', array(
            'engineer' => $user,
            'preferences' => $preferences,
        ));
    }

    /**
     * Modification d'une demande ITDLC d'un ingénieur
     *
     * @Route(
     *      "/demande-itdlc-it/edit/{id}",
     *      name = "admin_demande_itdlc_inge_edit"
     * )
     * @param User $demandeItdlc
     * @return Response
     */
    public function editDemandeIngeAction(User $demandeItdlc)
    {
        $preferences = $this->em->getRepository(Preference::class)->findBy(['mainUser' => $demandeItdlc], ['id' => 'ASC']);

        return $this->render('Admin/Ope/ITDLC/editDemandeInge.html.twig', array(
            'ope' => $demandeItdlc,
            'preferences' => $preferences,
        ));
    }

    /**
     * Liste des opérations ITDLC
     *
     * @Route(
     *      "/operation-itdlc/list/{page}",
     *      requirements = {"page": "\d+"},
     *      name = "admin_operation_itdlc"
     * )
     * @param Request $request
     * @param int $page
     * @return Response
     */
    public function listOperationAction(Request $request, int $page = 1)
    {
        $resultsMaxPerPage = $this->getParameter('results.admin.max_per_page');
        $academies = $this->em->getRepository(User::class)->findAcademies(Query::HYDRATE_ARRAY);
        $academy = $request->get('academy');

        // Mise à jour de la session avec les nouvelles valeurs
        $this->session->set($request->get('_route'), array(
            'page' => $page,
            'academy' => $academy,
        ));

        // Création de la requête
        $qb = $this->em->createQueryBuilder();
        $qb
            ->select('o, a, t, e')
            ->from(OperationITDLC::class, 'o')
            ->leftJoin('o.availability', 'a')
            ->leftJoin('o.prof', 't')
            ->leftJoin('o.inge', 'e')
            ->where('o.type = :o_type')
            ->andWhere(
                $qb->expr()->like(
                    $qb->expr()->upper('t.academy'),
                    $qb->expr()->upper(':t_academy')
                )
            )
            ->orderBy('a.dateVisite', 'desc')
            ->addOrderBy('o.id', 'desc')
            ->setParameters([
                'o_type' => OperationITDLCTypeEnum::OPERATION,
                't_academy' => '%'.$academy.'%',
            ])
            ->setFirstResult(($page - 1) * $resultsMaxPerPage)
            ->setMaxResults($resultsMaxPerPage)
        ;

        // Création de la pagination
        $ope = new Paginator($qb->getQuery(), false);
        $nbPage = count($ope) / $resultsMaxPerPage;
        $pagination = array();
        for ($i = 1; $i < $nbPage + 1; $i++) {
            array_push($pagination, $i);
        }


        return $this->render('Admin/Ope/ITDLC/indexOperation.html.twig', array(
            'ope' => $ope,
            'type' => OperationITDLCTypeEnum::OPERATION,
            'pagination' => $pagination,
            'pageactuelle' => $page,
            'academies' => $academies,
            'academy' => $academy,
        ));
    }

    /**
     * Ajout d'une opération ITDLC
     *
     * @Route(
     *      "/operation-itdlc/add",
     *      name = "admin_operation_itdlc_add"
     * )
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function addOperationAction(Request $request)
    {
        $operationitdlc = new OperationITDLC;
        
        $mer = new MerITDLC($operationitdlc);
        $mer->setOpe($operationitdlc);
        
        $mer->setFirstDate(new \DateTime());
        $mer->setFirstDateStartTime(null);
        $mer->setFirstDateEndTime(null);

        $mer->setSecondDate(new \DateTime());
        $mer->setSecondDateStartTime(null);
        $mer->setSecondDateEndTime(null);

        $mer->setThirdDate(new \DateTime());
        $mer->setThirdDateStartTime(null);
        $mer->setThirdDateEndTime(null);

        
        $operationitdlc->addMerITDLC($mer);
        $this->em->persist($operationitdlc);
        $this->em->flush();



        $form = $this->createForm(OperationITDLCType::class, $operationitdlc);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $operationitdlc->setType(OperationITDLCTypeEnum::OPERATION);
            if ($operationitdlc->getInge()) {
                $mer->setInge($operationitdlc->getInge());
            }
            

            $this->em->persist($operationitdlc);
            $this->em->flush();

            $this->addFlash('success', 'Opération enregistrée');

            return $this->redirectToRoute('admin_operation_itdlc_edit', [
                'id' => $operationitdlc->getId(),
            ]);
        }

        return $this->render('Admin/Ope/ITDLC/editOperation.html.twig', array(
            'form' => $form->createView(),
            'ope' => $operationitdlc,
        ));
    }

    /**
     * Modification d'une opération ITDLC
     *
     * @Route(
     *      "/operation-itdlc/edit/{id}",
     *      requirements = {"id": "\d+"},
     *      name = "admin_operation_itdlc_edit"
     * )
     * @param Request $request
     * @param OperationITDLC $operationItdlc
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editOperationAction(Request $request, OperationITDLC $operationItdlc)
    {
        $statePrevious = $operationItdlc->getState();

        $form = $this->createForm(OperationITDLCType::class, $operationItdlc);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->em->persist($operationItdlc);
            $this->em->flush();

           
            if ($statePrevious !== $operationItdlc->getState() && OperationITDLCState::CLOSED == $operationItdlc->getState()) {
                $this->addFlash('fancybox-load', $this->generateUrl('admin_operation_itdlc_mail_state', [
                    'id' => $operationItdlc->getId(),
                    'statePrevious' => $statePrevious,
                ]));
            }
            

            $this->addFlash('success', $this->translator->trans('notice.operationITDLC.updated', [], 'notice'));
            
            return $this->redirectToRoute('admin_operation_itdlc_edit', ['id' => $operationItdlc->getId()]);
        }

        $dates = $this->em->getRepository(Availability::class)->findBy(
            ['operationitdlc' => $operationItdlc->getId()],
            ['id' => 'ASC']
        );

        $preferences = $this->em->getRepository(Preference::class)->findBy(
            ['mainUser' => $operationItdlc->getProf()->getId()],
            ['id' => 'ASC']
        );

        return $this->render('Admin/Ope/ITDLC/editOperation.html.twig', array(
            'form' => $form->createView(),
            'ope' => $operationItdlc,
            'dates' => $dates,
            'preferences' => $preferences,
        ));
    }

    /**
     * Ajout d'une disponibilité à une opération ITDLC
     *
     * @Route(
     *      "/availability/add",
     *      name = "admin_availability_add"
     * )
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function addAvailabilityAction(Request $request)
    {
        $ope = $request->get('ope');
        $typedispo = $request->get('typedispo');

        // Formulaire horaire 
        $availability = new Availability;
        if ('precis' == $typedispo) {
            $form = $this->createForm(AvailabilityPrecisType::class, $availability);
        } else {
            $form = $this->createForm(AvailabilityHebdoType::class, $availability);
        }

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // On enregistre le contenu de la page simple 
            $availability->setOperationitdlc($this->em->find('AppBundle:OperationITDLC', $ope));
            $this->em->persist($availability);

            $this->em->flush();

            $this->addFlash('success', 'Disponibilité ajoutée');

            return $this->redirectToRoute('admin_availability_edit', array(
                'availability' => $availability->getId(),
                'typedispo' => $typedispo,
            ));
        }

        return $this->render('Admin/Ope/ITDLC/addOperationAvailability.html.twig', array(
            'form' => $form->createView(),
            'typedispo' => $typedispo,
        ));
    }

    /**
     * Modification de la disponibilité d'une opération ITDLC
     *
     * @Route(
     *      "/availability/edit/{availability}",
     *      requirements = {"availability": "\d+"},
     *      name = "admin_availability_edit"
     * )
     * @param Request $request
     * @param Availability $availability
     * @return Response
     */
    public function editAvailabilityAction(Request $request, Availability $availability)
    {
        $typedispo = $request->get('typedispo');

        // Formulaire horaire
        $form = $this->createForm(
            'precis' === $typedispo ? AvailabilityPrecisType::class : AvailabilityHebdoType::class,
            $availability
        );
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->em->persist($availability);
            $this->em->flush();

            $this->addFlash('success', 'Disponibilité modifiée');
        }

        return $this->render('Admin/Ope/ITDLC/editOperationAvailability.html.twig', array(
            'form' => $form->createView(),
            'typedispo' => $typedispo,
        ));
    }

    /**
     * Supprime la disponibilité d'une opération ITDLC
     *
     * @Route(
     *      "/availability/delete/{id}",
     *      name = "admin_availability_delete"
     * )
     * @ParamConverter(
     *      "availability",
     *      class="AppBundle:Availability"
     * )
     * @param Availability $availability
     * @return Response
     */
    public function deleteAvailabilityAction(Availability $availability)
    {
        $this->em->remove($availability);
        $this->em->flush();

        $this->addFlash('success', 'Date supprimé');

        return new Response();
    }

    /**
     * Supprime une demande ou une opération ITDLC
     *
     * @Route(
     *      "/operation-itdlc/delete/{id}",
     *      name = "admin_operation_itdlc_delete"
     * )
     * @param OperationITDLC $operationItdlc
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
     */
    public function deleteAction(OperationITDLC $operationItdlc)
    {
        $this->em->remove($operationItdlc);
        $this->em->flush();

        $this->addFlash('success', 'Elément supprimé');

        return $this->redirectToRoute(
            OperationITDLCTypeEnum::DEMANDE == $operationItdlc->getType()
                ? 'admin_demande_itdlc'
                : 'admin_operation_itdlc'
        );
    }

    /**
     * Confirm the opening of an ITDLC operation:
     * 1. Preview the mails that will be send to the teacher & engineer
     * 2. Send the mails
     *
     * @Route(
     *      "/operation-itdlc/confirm/{id}",
     *      name = "admin_operation_itdlc_confirm"
     * )
     * @param Request $request
     * @param OperationITDLC $operationItdlc
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     * @throws \Exception
     */
    public function confirmOperationAction(Request $request, OperationITDLC $operationItdlc)
    {
        $mailPreview = new MailPreview();

        $mails = $this->itdlcMailer->getConfirmOperation($operationItdlc);
        foreach ($mails as $title => $mail) {
            $mailPreview->addMail($mail);
        }

        $form = $this->createForm(MailPreviewType::class, $mailPreview);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $dateSending = new \DateTime();

            // Update DB about the date when the mail were send
            $operationItdlc->setDateMail($dateSending);
            $this->em->persist($operationItdlc);
            $this->em->flush();

            $this->itdlcMailer->send($mails, true);

            return $this->redirectToRoute('admin_operation_itdlc_confirm', array(
                'id' => $operationItdlc->getId(),
                'datesending' => $dateSending->format('d/m/Y'), // Will be use by JavaScript
            ));
        }

        return $this->render('Admin/Mail/preview.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    /**
     * Recherche les ingénieurs qui peuvent correspondrent à la demande ITDLC d'un professeur
     *
     * @Route(
     *       "/demande-itdlc-p/find/{id}",
     *       name = "admin_demande_itdlc_professeur_find",
     *       requirements={"id":"\d+"}
     * )
     * @Method("POST")
     * @param Request $request
     * @param OperationITDLC $demandeItdlc
     * @return Response
     */
    public function findDemandeMatchingEngineersAction(Request $request, OperationITDLC $demandeItdlc)
    {
        $filters = [];
        $usePersonalLocation = $request->request->getBoolean('usePersonalLocation');

        // Retrieve matching engineers
        if ($request->request->getBoolean('filterByClass')) {
            $filters['classroom'] = $demandeItdlc->getClassLevel()[0];
        }

        $engineers = $this->em->getRepository(User::class)->findClosestOthers(
            $demandeItdlc->getProf(),
            $filters,
            $usePersonalLocation
        );

        //echo "ENGINEER: " . $engineers->count();
        if (count($engineers == 0))
        {
            $filters['distance'] = false;

            $engineers = $this->em->getRepository(User::class)->findClosestOthers(
                $demandeItdlc->getProf(),
                $filters,
                $usePersonalLocation
            );
        }

        // Add Interest
        foreach ($engineers as &$e) {
            $e['isInterested'] = $this->em->getRepository(Interest::class)->findOneBy(array('user' => $e[0], 'operationitdlc' => $demandeItdlc));
        }

        return $this->render('Admin/Ope/ITDLC/_component/listUserTeacher.html.twig', array(
            'engineers' => $engineers,
            'demande' => $demandeItdlc,
            'usePersonalLocation' => $usePersonalLocation,
        ));
    }

    /**
     * Recherche les professeurs qui peuvent correspondrent à la demande ITDLC d'un ingénieur
     *
     * @Route(
     *      "/demande-itdlc-i/find/{id}",
     *      name = "admin_demande_itdlc_ingenieur_find",
     *      requirements={"id":"\d+"}
     * )
     * @Method("POST")
     * @param Request $request
     * @param User $engineer
     * @return Response
     */
    public function findDemandeMatchingTeachersAction(Request $request, User $engineer)
    {
        $filterByClass = $request->request->getBoolean('filterByClass');
        $filterByEstablishment = $request->request->getBoolean('filterByEstablishment');

        $querypreference = $this->em
            ->createQuery(
                "SELECT IDENTITY(p.selectedUser)
                    FROM AppBundle:Preference p
                    WHERE p.mainUser = :p_mainUser
                    ORDER BY p.id ASC"
            )
            ->setParameter('p_mainUser', $engineer->getId());
        $preferences = $querypreference->getResult();

        // Création de la requête, selon les cases cochées
        $qb = $this->em->createQueryBuilder();
        $qb
            ->select('o AS demande, u')
            ->from(OperationITDLC::class, 'o')
            ->leftJoin('o.prof', 'u')
            ->leftJoin('o.interest', 'i', 'with', 'i.user = :uCurrent and i.operationitdlc = o')
            ->where('o.type = :oType')
            ->andWhere('o.state = :oState')
            ->andWhere('u.enabled = :uEnabled')
            ->andWhere('u.is_active = :uIsActive')
            ->andWhere('u.is_available = :uIsAvailable')
            ->groupBy('o, u, i')
            ->orderBy('COUNT(o.interest)', 'DESC')
            ->addOrderBy('distance', 'ASC')
            ->setParameters([
                'oType' => OperationITDLCTypeEnum::DEMANDE,
                'oState' => OperationITDLCState::NEW,
                'uEnabled' => true,
                'uIsActive' => true,
                'uIsAvailable' => true,
                'uCurrent' => $engineer,
            ])
        ;

        // Always filter by distance, except if $filterByEstablishment is true and $filterByClass false
        UserRepository::addDistanceConditions($qb, $engineer, !$filterByEstablishment || $filterByClass);

        if ($filterByClass) {
            $qb
                ->andWhere($qb->expr()->in('o.classLevel', ':oClasslevel'))
                ->setParameter('oClasslevel', $engineer->getClassroom())
            ;
        }

        if ($filterByEstablishment && count($preferences) > 0) {
            $qb
                ->andWhere($qb->expr()->in('u.id', ':uIds'))
                ->setParameter('uIds', array_map('array_shift', $preferences))
            ;
        }

        // Exécution de la requête
        $demandes = $qb->getQuery()->getResult();

        return $this->render('Admin/Ope/ITDLC/_component/listUserEngineer.html.twig', array(
            'demandes' => $demandes,
            'engineer' => $engineer,
            'preferences' => $preferences,
        ));
    }

    /**
     * Génère une opération ITDLC à partir d'une demande ITDLC (qu'elle ai été initiée par un professeur ou un ingénieur)
     *
     * @Route(
     *      "/demande-itdlc/generate-ope/{type}/{demandeitdlc}/{user}",
     *      name = "admin_demande_itdlc_generate_ope_inge"
     * )
     * @param string $type
     * @param OperationITDLC $demandeitdlc
     * @param User $user
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
     */
    public function generateOpeAction(string $type, OperationITDLC $demandeitdlc, User $user)
    {
        $demandeitdlc->setType(OperationITDLCTypeEnum::OPERATION);
        if ('inge' === $type || 'prof' === $type) {
            $demandeitdlc->setInge($user);
        }

        $this->em->persist($demandeitdlc);
        $this->em->flush();

        return $this->redirectToRoute('admin_operation_itdlc_edit', [
            'id' => $demandeitdlc->getId(),
        ]);
    }

    /**
     * Gestion de l'envoi d'un e-mail personnalisé du professeur ayant fait une demande ITDLC à l'ingénieur spécifié.
     * Lorsque le contrôleur est appelé via la méthode get, le formulaire est affiché. Un appel via la méthode POST soumet le formulaire et envoi le mail.
     *
     * @Route(
     *      "/demande-itdlc-p/{demandeItdlc}/mail/{engineer}",
     *      name = "admin_demande_itdlc_professeur_mail"
     * )
     * @param Request $request
     * @param OperationITDLC $demandeItdlc
     * @param User $engineer
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     * @throws \Exception
     */
    public function mailToIngeAction(Request $request, OperationITDLC $demandeItdlc, User $engineer)
    {
        $mailPreview = new MailPreview();

        $mailEngineer = $this->itdlcMailer->getSuggestOperationMeeting($demandeItdlc, $engineer);
        $mailPreview->addMail($mailEngineer);

        $form = $this->createForm(MailPreviewType::class, $mailPreview);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->itdlcMailer->send($mailEngineer, true);

            return $this->redirectToRoute('admin_demande_itdlc_professeur_mail', array(
                'demandeItdlc' => $demandeItdlc->getId(),
                'engineer' => $engineer->getId(),
            ));
        }

        return $this->render('Admin/Mail/preview.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    /**
     * Displays the form emails that will be send depending on the new state of an operation / application.
     *
     * @Route(
     *      "/operation-itdlc/{id}/mail/{statePrevious}",
     *      name = "admin_operation_itdlc_mail_state",
     *      requirements = {"id": "\d+", "statePrevious":"\w+"}
     * )
     * @param Request $request
     * @param OperationITDLC $operationItdlc
     * @param string $statePrevious
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response|\Symfony\Component\Security\Core\Exception\AccessDeniedException
     * @throws \Exception
     */
    public function mailStatusAction(Request $request, OperationITDLC $operationItdlc, string $statePrevious)
    {
        if ($operationItdlc->getState() === $statePrevious) {
            return $this->createAccessDeniedException();
        }

        $allowedStates = [
            OperationITDLCState::CLOSED,
            OperationITDLCState::NO_CONTRIBUTOR,
        ];
        if (!in_array($operationItdlc->getState(), $allowedStates)) {
            return $this->createAccessDeniedException();
        }

        $mailPreview = new MailPreview();
        $mails = $this->itdlcMailer->getOperationState($operationItdlc, $operationItdlc->getState());
        foreach ($mails as $mail) {
            $mailPreview->addMail($mail);
        }

        $form = $this->createForm(MailPreviewType::class, $mailPreview);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->itdlcMailer->send($mails, true);

            return $this->redirectToRoute('admin_operation_itdlc_mail_state', [
                'id' => $operationItdlc->getId(),
                'state' => $operationItdlc->getState(),
            ]);
        }

        return $this->render('Admin/Mail/preview.html.twig', [
            'form' => $form->createView(),
        ]);
    }


    /**
     * Liste des mise en relations d'ITDLC
     *
     * @Route(
     *      "/mer-itdlc/list/{page}",
     *      requirements = {"page": "\d+"},
     *      name = "admin_mer_itdlc"
     * )
     * @param Request $request
     * @param int $page
     * @return Response
     */
    public function listMERAction(Request $request, int $page = 1)
    {
        $resultsMaxPerPage = $this->getParameter('results.admin.max_per_page');

        // Mise à jour de la session avec les nouvelles valeurs
        $this->session->set($request->get('_route'), array(
            'page' => $page
        ));

        // Création de la requête
        $qb = $this->em->createQueryBuilder();
        $qb
            ->select('m, o, p, i')
            ->from(MerITDLC::class, 'm')
            ->join('m.ope', 'o')
            ->join('o.prof', 'p')
            ->join('m.inge', 'i')
            ->orderBy('m.createdAt', 'desc')
            ->setFirstResult(($page - 1) * $resultsMaxPerPage)
            ->setMaxResults($resultsMaxPerPage)
        ;

        // Création de la pagination
        $mers = new Paginator($qb->getQuery(), false);
        $nbPage = count($mers) / $resultsMaxPerPage;
        $pagination = array();
        for ($i = 1; $i < $nbPage + 1; $i++) {
            array_push($pagination, $i);
        }

        return $this->render('Admin/Ope/ITDLC/indexMer.html.twig', array(
            'mers' => $mers,
            'pagination' => $pagination,
            'pageactuelle' => $page,
        ));
    }


    /**
     * Export des mises en relations d'ITDLC
     *
     * @Route(
     *      "/mer-itdlc/export",
     *      name = "admin_mer_itdlc_export"
     * )
     * @param Request $request
     * @return Response
     */
    public function exportMERAction(Request $request)
    {
        $resultsMaxPerPage = $this->getParameter('results.admin.max_per_page');

        // Création de la requête
        $qb = $this->em->createQueryBuilder();
        $qb
            ->select('m, o, p, i')
            ->from(MerITDLC::class, 'm')
            ->join('m.ope', 'o')
            ->join('o.prof', 'p')
            ->join('m.inge', 'i')
            ->orderBy('m.createdAt', 'desc')
        ;

        $mers = $qb->getQuery()->getResult();

        return $this->operationItdlcExporter->exportMERS($mers, 'MER-'.date('Ymd').'.xlsx');

    }
}
