<?php

namespace AppBundle\Controller;

use AppBundle\Entity\Availability;
use AppBundle\Entity\DemandePEE;
use AppBundle\Entity\Interest;
use AppBundle\Entity\MerHistoryITDLC;
use AppBundle\Entity\OperationITDLC;
use AppBundle\Entity\OperationPEE;
use AppBundle\Entity\Preference;
use AppBundle\Entity\User;
use AppBundle\Entity\Media;
use AppBundle\Entity\MerITDLC;
use AppBundle\Enum\OperationITDLCType;
use AppBundle\Enum\DemandePEEState;
use AppBundle\Enum\OperationITDLCState;
use AppBundle\Enum\OperationPEEState;
use AppBundle\Enum\UserType;
use AppBundle\Enum\MediaType;
use Doctrine\ORM\EntityManagerInterface;
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\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use AppBundle\Mail\ItdlcMailer;


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

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

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

    public function __construct(EntityManagerInterface $em, UserManagerInterface $userManager, ItdlcMailer $itdlcMailer)
    {
        $this->em = $em;
        $this->userManager = $userManager;
        $this->itdlcMailer = $itdlcMailer;
    }

    /**
     * Accueil de l'espace personnel des utilisateurs (professeurs et ingénieurs)
     *
     * @Route(
     *      "/espace-perso",
     *      name = "espace_perso"
     * )
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function indexAction(Request $request)
    {
        /* $dPeeWaitingValidation = 0;
        $oPeePlanned = $oPeeDone = [];
        $user = $this->getUser();

        $otherUsers = $this->em->getRepository(User::class)->findClosestOthers($user);

        // Applications
        $peeApplications = $this->em
            ->getRepository(DemandePEE::class)
            ->findBy(['cuser' => $user], ['created' => 'DESC']);
        
        $itdlcApplications = $this->em
            ->getRepository(OperationITDLC::class)
            ->findRecentApplicationsByUser($user);

        // Operations
        $oItdlcPlanned = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::NEW]);

        $oItdlcDone = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::CLOSED]);

        if (UserType::TEACHER === $user->getType()) {
            $oPeePlanned = $this->em
                ->getRepository(OperationPEE::class)
                ->findUserRegistrations($user, [DemandePEEState::REGISTERED], [OperationPEEState::OPEN]);

            $oPeeDone = $this->em
                ->getRepository(OperationPEE::class)
                ->findUserRegistrations($user, [DemandePEEState::REGISTERED], [OperationPEEState::CLOSED]);

            $dPeeWaitingValidation = $this->em
                ->getRepository(DemandePEE::class)
                ->waitingForValidation($user, true);
        }

        return $this->render('Front/User/index.html.twig', array(
            'others' => $otherUsers,
            'itdlcApplications' => $itdlcApplications,
            'peeApplications' => $peeApplications,
            'dPeeWaitingValidation' => $dPeeWaitingValidation,
            'oItdlcPlanned' => $oItdlcPlanned,
            'oItdlcDone' => $oItdlcDone,
            'oPeePlanned' => $oPeePlanned,
            'oPeeDone' => $oPeeDone,
        )); */

        $params = array();
        $first_login = $request->get('first_login');
        if (!empty($first_login)) {
            $params['first_login'] = $first_login;
        }

        $user = $this->getUser();

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

    /**
     * Espace personnel des opérations des utilisateurs (Ingénieurs)
     *
     * @Route(
     *      "/espace-perso/mes-interventions",
     *      name = "espace_perso_operations"
     * )
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function indexOperationsAction(Request $request)
    {
        $first_login = $request->get('first_login');

        $user = $this->getUser();

        // Authorize only ENGINEER user
        if ($user->getType() !== UserType::ENGINEER) {
            return $this->redirectToRoute('espace_perso');
        }

        // $otherUsers = $this->em->getRepository(User::class)->findClosestOthers($user);

        // Operations
        $operationsItdlc = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::NEW, OperationITDLCState::ONGOING, OperationITDLCState::CANCELLED]);

        $operationsItdlcDone = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::CLOSED]);

//        $demandesItdlcWaitingValidation = $this->em
//            ->getRepository(OperationITDLC::class)
//            ->findUserInterests($user);

        $demandesItdlcWaitingValidation = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserMER($user);

        
        if (count($operationsItdlc)>=1) {
            $videos = $this->em->getRepository(Media::class)->findBy([
                'is_active' => true,
                'pagePerso' => UserType::ENGINEER,
                'type' => MediaType::VIDEO], [
                'title' => 'ASC', 'id' => 'ASC']
            );

            $files = $this->em->getRepository(Media::class)->findBy([
                'is_active' => true,
                'pagePerso' => UserType::ENGINEER,
                'type' => MediaType::PDF ], [
                'title' => 'ASC', 'id' => 'ASC']
            );
        }
       

        return $this->render('Front/User/Engineer/listeOperation.html.twig', array(
            // 'othersUsers' => $otherUsers,
            'operationsItdlc' => $operationsItdlc,
            'operationsItdlcDone' => $operationsItdlcDone,
            'demandesItdlcWaitingValidation' => $demandesItdlcWaitingValidation,
            'first_login' => $first_login,
            'videos' => $videos ?? null,
            'files' => $files ?? null
        ));
    }

    /**
     * Espace personnel des demandes des utilisateurs (Ingénieurs)
     *
     * @Route(
     *      "/espace-perso/demandes-etablissements",
     *      name = "espace_perso_demandes"
     * )
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function indexDemandesAction(Request $request)
    {
        $first_login = $request->get('first_login');

        $user = $this->getUser();

        // Authorize only ENGINEER user
        if ($user->getType() !== UserType::ENGINEER) {
            return $this->redirectToRoute('espace_perso');
        }
        
        $demandesItdlc = $this->em
            ->getRepository(OperationITDLC::class)
            ->findAllWithUserInterests($user);

        return $this->render('Front/User/Engineer/listeDemande.html.twig', array(
            // 'others' => $otherUsers,
            'demandesItdlc' => $demandesItdlc,
            //'demandesPee' => $demandesPee,
            'first_login' => $first_login,
        ));
    }

    /**
     * Espace personnel des opérations ITDLC des utilisateurs (professeurs)
     *
     * @Route(
     *      "/espace-perso/demandes-itdlc",
     *      name = "espace_perso_itdlc"
     * )
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function indexITDLCAction(Request $request)
    {
        $first_login = $request->get('first_login');

        $user = $this->getUser();

        // Authorize only TEACHER user
        if ($user->getType() !== UserType::TEACHER) {
            return $this->redirectToRoute('espace_perso');
        }

        $otherUsers = $this->em->getRepository(User::class)->findClosestOthers($user);


        // Applications
        $demandes = $this->em
            ->getRepository(OperationITDLC::class)
            ->findRecentApplicationsByUser($user);

        // Operations
        $operations = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::NEW, OperationITDLCState::ONGOING]);

        $operationsCancelled = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::CANCELLED]);

        $operationsDone = $this->em
            ->getRepository(OperationITDLC::class)
            ->findUserRegistrations($user, [OperationITDLCState::CLOSED]);

        if (count($operations)>=1) {
            $videos = $this->em->getRepository(Media::class)->findBy([
                'is_active' => true,
                'pagePerso' => UserType::TEACHER,
                'type' => MediaType::VIDEO], [
                'title' => 'ASC', 'id' => 'ASC']
            );

            $files = $this->em->getRepository(Media::class)->findBy([
                'is_active' => true,
                'pagePerso' => UserType::TEACHER,
                'type' => MediaType::PDF ], [
                'title' => 'ASC', 'id' => 'ASC']
            );
        }


        return $this->render('Front/User/Teacher/listeITDLC.html.twig', array(
            'othersUsers' => $otherUsers,
            'demandes' => $demandes,
            'operations' => $operations,
            'operationsDone' => $operationsDone,
            'operationsCancelled' => $operationsCancelled,
            'first_login' => $first_login,
            'videos' => $videos ?? null,
            'files' => $files ?? null
        ));
    }

    /**
     * Espace personnel des demandes PEE des utilisateurs (professeurs)
     *
     * @Route(
     *      "/espace-perso/demandes-pee",
     *      name = "espace_perso_pee"
     * )
     * 
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function indexPEEAction(Request $request)
    {
        $first_login = $request->get('first_login');

        $user = $this->getUser();

        // Authorize only TEACHER user
        if ($user->getType() !== UserType::TEACHER) {
            return $this->redirectToRoute('espace_perso');
        }

        // $otherUsers = $this->em->getRepository(User::class)->findClosestOthers($user);

        // Applications
        $demandes = $this->em
            ->getRepository(DemandePEE::class)
            ->findBy(['cuser' => $user, 'state' => array(DemandePEEState::PREREGISTERED, DemandePEEState::WAITING, DemandePEEState::WITHDRAWAL)], ['created' => 'DESC']);

        $demandesWaitingValidation = $this->em
            ->getRepository(DemandePEE::class)
            ->waitingForValidation($user, true);

        // Operations

        $operations = $this->em
            ->getRepository(OperationPEE::class)
            ->findUserRegistrations($user, [DemandePEEState::REGISTERED], [OperationPEEState::OPEN, OperationPEEState::FENCED, OperationPEEState::CANCELLED]);

        $operationsDone = $this->em
            ->getRepository(OperationPEE::class)
            ->findUserRegistrations($user, [DemandePEEState::REGISTERED], [OperationPEEState::CLOSED]);

        return $this->render('Front/User/Teacher/listePEE.html.twig', array(
            // 'othersUsers' => $otherUsers,
            'demandes' => $demandes,
            'demandesWaitingValidation' => $demandesWaitingValidation,
            'operations' => $operations,
            'operationsDone' => $operationsDone,
            'first_login' => $first_login,
        ));
    }

    /**
     * Get a user file, if the user has enough right to do it.
     *
     * @Route(
     *      "/secure-file/{filename}/{ownerId}",
     *      name = "secure_user_file"
     * )
     *
     * @param string $filename
     * @param int $ownerId File owner identifier. If not provided, assume that the owner is the current logged user.
     * @param BinaryFileResponse
     * @return BinaryFileResponse
     */
    public function userFileAction(string $filename, int $ownerId = 0): BinaryFileResponse
    {
        $loggedUser = $this->getUser();
        $owner = !$ownerId ? $loggedUser : $this->userManager->findUserBy(['id' => $ownerId]);

        if (
            !$this->isGranted('ROLE_ADMIN_FULL')
            && !$this->isGranted('ROLE_ADMIN_ITDLC')
            && !$this->isGranted('ROLE_ADMIN_PEE')
            && $loggedUser->getId() !== $owner->getId()
        ) {
            throw $this->createAccessDeniedException();
        }

        switch (true) {
            case $owner->getIdentityCard1() === $filename:
                $filepath = $owner->getAbsoluteIdentityCard1();
                break;

            case $owner->getIdentityCard2() === $filename:
                $filepath = $owner->getAbsoluteIdentityCard2();
                break;

            case $owner->getId() . '.' . $owner->getPhoto() === $filename:
                $filepath = $owner->getAbsolutePhoto();
                break;
            
            default:
                $filepath = null;
                break;
        }

        $file = new File($filepath);

        return new BinaryFileResponse($file);
    }

    /**
     * Défini un professeur comme préféré de l'ingénieur connecté et inversement.
     *
     * @Route(
     *      "/espace-perso/ajax-preference",
     *      name = "preference"
     * )
     * @Method({"POST"})
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function preferenceAction(Request $request)
    {
        $userIdPreferred = $request->get('id');
        $response = new JsonResponse(array(), Response::HTTP_FORBIDDEN);
        $etat = $request->get('actif');
        // On récupère les 2 utilisateurs 
        $user = $this->getUser();
        $otherUser = $this->em->getRepository('AppBundle:User')->findOneById($userIdPreferred);

        // S'il ne sont pas du même type 
        if (
            (UserType::TEACHER === $user->getType() && UserType::ENGINEER === $otherUser->getType())
            || (UserType::ENGINEER === $user->getType() && UserType::TEACHER === $otherUser->getType())
        ) {
            // On vérifie si la connexion existe 
            $queryrelation = $this->em
                ->createQuery(
                    "SELECT p FROM AppBundle:Preference p WHERE p.mainUser = :p_mainUser AND p.selectedUser = :p_selectedUser"
                )
                ->setParameters(array(
                    'p_mainUser' => $user,
                    'p_selectedUser' => $otherUser,
                ));
            $relation = $queryrelation->getResult();

            // Si la relation n'existe pas et qu'on a coché la checkbox 
            if (0 == count($relation) && 'true' == $etat) {
                $relation = new Preference;
                $relation->setMainUser($user);
                $relation->setSelectedUser($otherUser);
                $this->em->persist($relation);
                $this->em->flush();

                $response->setStatusCode(Response::HTTP_OK);
            } elseif (count($relation) > 0 && 'false' == $etat) { // Si la relation existe et qu'on a décoché la checkbox 
                $this->em->remove($relation[0]);
                $this->em->flush();

                $response->setStatusCode(Response::HTTP_OK);
            }
        }

        return $response;
    }


    /**
     * Défini l'intérêt d'un utilisateur pour une opération
     *
     * @Route(
     *      "/espace-perso/ajax-interest-itdlc/{ope}",
     *      name = "interest_itdlc"
     * )
     *
     * @param Request $request
     * @param OperationITDLC $ope
     * @return JsonResponse
     */
    public function interestITDLCAction(Request $request, OperationITDLC $ope)
    {
        $ope = $request->get('ope');
        $response = new JsonResponse(array('result' => false));
        $interested = (int) $request->get('interested');

        // On récupère les 2 utilisateurs 
        $user = $this->getUser();

        // On vérifie si la connexion existe 
        $interest = $this->em->getRepository(Interest::class)->findOneBy(array('user' => $user, 'operationitdlc' => $ope));

        if (!empty($interest) && $interest instanceof Interest && !$interested) {
            $this->em->remove($interest);
            $this->em->flush();
            
            $response = new JsonResponse(array('result' => true, 'interested' => $interested));
        }
        elseif ($interested) {
            $relation = new Interest;
            $relation->setUser($user);
            $relation->setOperationitdlc($ope);
            $this->em->persist($relation);

            $this->em->flush();

            $response = new JsonResponse(array('result' => true, 'interested' => $interested));
        }

        return $response;
    }

    /**
     * Défini l'intérêt d'un utilisateur pour une opération
     *
     * @Route(
     *      "/espace-perso/ajax-interest-pee/{ope}",
     *      name = "interest_pee"
     * )
     *
     * @param Request $request
     * @param OperationPEE $ope
     * @return JsonResponse
     */
    public function interestPEEAction(Request $request, OperationPEE $ope)
    {
        $ope = $request->get('ope');
        $response = new JsonResponse(array('result' => false), Response::HTTP_FORBIDDEN);
        $interested = (int) $request->get('interested');

        // On récupère les 2 utilisateurs 
        $user = $this->getUser();

        // On vérifie si la connexion existe 
        $interest = $this->em->getRepository(Interest::class)->findOneBy(array('user' => $user, 'operationitdlc' => $ope));
        
        if (!empty($interest) && $interest instanceof Interest) {

            if ($interested) {
                $relation = new Interest;
                $relation->setUser($user);
                $relation->setOperationpee($otherUser);
                $this->em->persist($relation);
            }
            else {
                $this->em->remove($interest);
            }
            
            $this->em->flush();

            $response->setStatusCode(Response::HTTP_OK);
            $response->setContent(array('result' => true, 'interested' => $interested));
        }

        return $response;
    }

     /**
     * Réponse d'une mise en relation d'une ITDLC
     *
     * @Route(
     *      "/espace-perso/reponse-merITDLC/{mer}/{reponse}",
     *      name = "espace_perso_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)
    {

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

        $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(OperationITDLCType::OPERATION);
                $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;

            case 'non':
                $mer->setAnswer($reponse);

                $form = $this->createFormBuilder()
                    ->setAction($this->generateUrl("espace_perso_merITDLC_reponse", array("mer" => $mer->getId(), "reponse" => $reponse)))
                    ->add('comment', TextareaType::class, array(
                        "label" => false,
                        "attr" => array(
                            'placeholder' => "Motif de votre refus",
                            'class' => "with-border form-control",
                            'rows' => 6,
                            'cols' => 90,
                        ),
                        "required" => true
                        )
                    )
                    ->add('desactivate', CheckboxType::class, array(
                            "required" => false,
                    ))
                    ->add('submit', SubmitType::class, array(
                        'attr' => ['class' => 'btn btn-theme float-right'],
                        'label'=> "Enregistrer ma réponse"
                    ))->getForm();

                $form->handleRequest($request);

                if ($form->isSubmitted() === true && $form->isValid() === true ) {
                    $data = $form->getData();
                    $mer->setComment($data['comment']);

                    if (!empty($data['desactivate'])) {
                        // Désactivation du profile
                        $user->setIsActive(false);
                        $user->setIsAvailable(false);
                        $this->em->persist($user);
                    } else {
                        $user->setIsAvailable(true);
                        $this->em->persist($user);
                    }

                } else {
                    return $this->render('Front/User/Engineer/merITDLC.html.twig', array(
                        'form' => $form->createView(),
                    ));
                }

                // Envoi d'un email au professeur que l'ingenieur a refusé
                $reponse = $this->itdlcMailer->sendITDLCRefused($mer);

                if (!empty($reponse) && $reponse[0]['code'] === "success") {
                    $ope->setInge(null);
                    $ope->setState(OperationITDLCState::NEW);

                    $merHistory = new MerHistoryITDLC();
                    $merHistory->setInfos($user->getFirstName()." ".$user->getLastName()." a décliné votre proposition");

                    $mer->addHistory($merHistory);

                    $this->em->persist($ope);
                    $this->em->persist($mer);

                    $this->em->flush();
                    $this->addFlash('success', 'Votre réponse a été enregistrée');
                } else {
                    $this->addFlash('error', "Suite à une erreur nous n'avons pas enregistrer votre réponse");
                }

                break;

            case 'autre':
                $mer->setAnswer($reponse);
                $this->em->persist($mer);

                // Envoi d'un email à ?
                $this->addFlash('success', 'Votre réponse a bien été enregistrée, CGénial va prendre contact avec vous pour vous permettre d\'intervenir dans cette classe.');
                $this->em->flush();

                break;
        }

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