<?php

namespace AppBundle\Controller\Admin;

use AppBundle\Entity\Media;
use AppBundle\Entity\MenuMedia;
use AppBundle\Enum\MediaType as MediaTypeEnum;
use AppBundle\Form\Type\MediaType;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Liip\ImagineBundle\Controller\ImagineController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

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

    /**
     * @var ImagineController
     */
    private $imagineController;

    /**
     * @var SessionInterface
     */
    private $session;
    
    public function __construct(EntityManagerInterface $em, ImagineController $imagineController, SessionInterface $session)
    {
        $this->em = $em;
        $this->imagineController = $imagineController;
        $this->session = $session;
    }

    /**
     *
     * @Route(
     *      "/media/list/{type}/{page}",
     *      requirements = {"page": "\d+"},
     *      name = "admin_media"
     * )
     *
     * @param Request $request
     * @param string type
     * @param int page
     * @return \Symfony\Component\HttpFoundation\Response
     */

    public function indexAction(Request $request, string $type = 'all', int $page = 1)
    {
        $order = $request->get('order') ?? 'id';
        $dir = $request->get('dir') ?? 'desc';

       
        $direction= [
            'id' => ($order=='id' && $dir=='ASC') ? 'DESC' : 'ASC',
            'title' =>  ($order=='title' && $dir=='ASC') ? 'DESC' : 'ASC',
            'pagePerso' =>  ($order=='pagePerso' && $dir=='ASC') ? 'DESC' : 'ASC',
            'opeItdlcEmail' =>  ($order=='opeItdlcEmail' && $dir=='ASC') ? 'DESC' : 'ASC',
        ];

        $resultsMaxPerPage = $this->getParameter('results.admin.max_per_page');
        $search_title = $request->get('title');

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

        $qbMedias = $this->em->createQueryBuilder()
            ->select('m')
            ->from(Media::class, 'm')
            ->orderBy('m.' . $order, $direction[$order])
            ->setFirstResult(($page - 1) * $resultsMaxPerPage)
            ->setMaxResults($resultsMaxPerPage)
        ;
        if ('all' != $type) {
            $qbMedias
                ->andWhere('m.type = :m_type')
                ->setParameter('m_type', $type);
        }
        if ($search_title) {
            $qbMedias
                ->andWhere($qbMedias->expr()->like(
                    $qbMedias->expr()->upper('m.title'),
                    $qbMedias->expr()->upper(':m_title')
                ))
                ->setParameter('m_title', '%'.$search_title.'%')
            ;
        }

        $medias = new Paginator($qbMedias->getQuery());

        return $this->render('Admin/Media/index.html.twig', array(
            'search_title' => $search_title,
            'medias' => $medias,
            'type' => $type,
            'nb_pages' => ceil(count($medias) / $resultsMaxPerPage),
            'pageactuelle' => $page,
            'direction' => $direction
        ));
    }

    /**
     *
     * @Route(
     *      "/media/add/{type}",
     *      defaults = {"type" = "pdf|picture|video"},
     *      name = "admin_media_add"
     * )
     *
     * @param Request $request
     * @param string $type
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function addAction(Request $request, $type)
    {
        $media = new Media;
        $media->setType($type);

        $form = $this->createForm(MediaType::class, $media);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // Récupération des Ids de tous les menus cochés
            $menusIds = array();
            foreach ($media->getMenu() as $key => $menu) {
                $menusIds[] = $menu->getId();
            }

            // Récupération des plus grandes valeurs de position du type de média pour chaque menu coché
            $menusHighestMediaPosition = $this->em->getRepository(Media::class)->findAllByHighestPosition($menusIds, $type, Query::HYDRATE_ARRAY);

            foreach ($media->getMenu() as $key => $menu) {
                // Recherche du résultat de la requête SQL correspondant au $menu
                $menusHighestMediaPositionFiltered = array_filter($menusHighestMediaPosition, function($menuMediaPosition) use ($menu) {
                    return $menuMediaPosition['id'] === $menu->getId();
                });

                // Il n'y a normalement qu'1 seul élément retourné, étant donné que le test se fait sur les Id
                if (1 === count($menusHighestMediaPositionFiltered)) {
                    $menuHighestMediaPosition = array_pop($menusHighestMediaPositionFiltered);

                    $menuMedia = new MenuMedia;
                    $menuMedia->setMenu($menu);
                    $menuMedia->setMedia($media);
                    $menuMedia->setPosition($menuHighestMediaPosition['highest'] + 1);

                    $this->em->persist($menuMedia);
                }
            }

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

            // Génération de la miniature si le média est une image
            if (MediaTypeEnum::PICTURE === $type) {
                $this->imagineController->filterAction($request, $media->getWebPathPicture(), '50H');
            }

            // On définit un message flash
            $this->addFlash('success', 'Media ajouté');

            return $this->redirectToRoute('admin_media_edit', array(
                'id' => $media->getId(),
            ));
        }

        return $this->render('Admin/Media/add.html.twig', array(
            'form' => $form->createView(),
            'type' => $type,
        ));
    }

    /**
     *
     * @Route(
     *      "/media/edit/{id}",
     *      requirements = {"id": "\d+"},
     *      name = "admin_media_edit"
     * )
     *
     * @param Request $request
     * @param Media $media
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function editAction(Request $request, Media $media)
    {
        $menusOld = clone $media->getMenu(); // Clone du ArrayCollection, car sinon il sera mis à jour après l'usage de handleRequest()
        $type = $media->getType();

        $form = $this->createForm(MediaType::class, $media);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $menusNew = $media->getMenu(); // Liste des menus cochés après soumission du formulaire

            // Récupération de la liste des menus décochés et suppression des entités MenuMedia correspondantes
            $menusIds = array();
            foreach ($menusOld as $menuOld) { // Parcours des menus cochés AVANT soumission du formulaire, et comparaison avec ceux qui ont été cochés APRES
                if (!$menusNew->contains($menuOld)) { // Signifie que le menu a été nouvellement décoché
                    $menusIds[] = $menuOld->getId();
                }
            }

            $menusMediaToRemove = $this->em->getRepository(MenuMedia::class)->findAllByMenusAndMedia($menusIds, $media->getId());
            foreach ($menusMediaToRemove as $menuMediaToRemove) {
                $this->em->remove($menuMediaToRemove);
            }

            // Récupération de la liste des menus nouvellement cochés et création des entités MenuMedia correspondantes
            $menusIds = array();
            // Parcours des menus cochés APRES soumission du formulaire,
            // et comparaison avec ceux qui étaient cochés AVANT
            foreach ($menusNew as $menuNew) {
                if (!$menusOld->contains($menuNew)) { // Le menu a été nouvellement coché
                    $menusIds[] = $menuNew->getId();
                }
            }
            $menusHighestMediaPosition = $this->em->getRepository(Media::class)->findAllByHighestPosition($menusIds, $type, Query::HYDRATE_ARRAY);
            foreach ($menusNew as $menuNew) {
                // Recherche de la ligne de la requête qui correspond au menu actuellement parcouru ($mediaMenuNew)
                $menusHighestMediaPositionFiltered = array_filter($menusHighestMediaPosition, function($menu) use ($menuNew) {
                    return $menu['id'] === $menuNew->getId();
                });

                // Il n'y a normalement qu'1 seul élément retourné,
                // étant donné que le test (de la fonction array_filter) se fait sur les Id
                if (1 === count($menusHighestMediaPositionFiltered)) {
                    $menuHighestMediaPosition = array_pop($menusHighestMediaPositionFiltered);

                    $menuMedia = new MenuMedia;
                    $menuMedia->setMenu($menuNew);
                    $menuMedia->setMedia($media);
                    $menuMedia->setPosition($menuHighestMediaPosition['highest'] + 1);

                    $this->em->persist($menuMedia);
                }
            }

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

            // On définit un message flash
            $this->addFlash('success', 'Media modifié');

            return $this->redirectToRoute('admin_media_edit', array(
                'id' => $media->getId(),
            ));
        }

        return $this->render('Admin/Media/add.html.twig', array(
            'form' => $form->createView(),
            'type' => $type,
        ));
    }
}
