<?php

namespace AppBundle\Controller\Admin;

use AppBundle\Entity\Content;
use AppBundle\Entity\Media;
use AppBundle\Entity\Menu;
use AppBundle\Entity\MenuMedia;
use AppBundle\Entity\TypeTemplate;
use AppBundle\Enum\MediaType;
use AppBundle\Enum\TypeTemplateTitle;
use AppBundle\Form\Type\Menu\SimpleMenuType;
use AppBundle\Form\Type\Menu\UrlMenuType;
use Cocur\Slugify\Slugify;
use Doctrine\ORM\EntityManagerInterface;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
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;

class MenuController extends Controller
{
    /**
     * @var EntityManagerInterface
     */
    private $em;
    
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    /**
     * Liste l'ensemble des Pages
     * 
     * @Route(
     *      "/menu/{menu_type}",
     *      name = "admin_menu"
     * )
     * 
     * @param Request $request
     * @param string menu_type
     * 
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function indexAction(Request $request, string $menu_type = 'main')
    {
        $qbMenus = $this->em->createQueryBuilder();
        $qbMenus
            ->select('m1, m1tt, m2, m2tt, m3, m3tt')
            ->from('AppBundle:Menu', 'm1')
            ->leftJoin('m1.typeTemplate', 'm1tt')
            ->leftJoin('m1.children', 'm2')
            ->leftJoin('m2.typeTemplate', 'm2tt')
            ->leftJoin('m2.children', 'm3')
            ->leftJoin('m3.typeTemplate', 'm3tt')
            ->where($qbMenus->expr()->isNull('m1.parent'))
            ->andWhere('m1.menu_type=:menu_type')
            ->orderBy('m1.position', 'asc')
            ->addOrderBy('m1.id', 'asc')
            ->addOrderBy('m2.position', 'asc')
            ->addOrderBy('m2.id', 'asc')
            ->addOrderBy('m3.position', 'asc')
            ->addOrderBy('m3.id', 'asc')
            ->setParameters(array(
                'menu_type' => $menu_type
            ));
        $menus = $qbMenus->getQuery()->getArrayResult();

        //dump($menus);
        //die();

        return $this->render('Admin/Menu/index.html.twig', array(
            'menus' => $menus,
            'menu_type' => $menu_type,
        ));
    }

    /**
     *
     * @Route(
     *      "/menu/{menu_type}/add-separator",
     *      name = "admin_menu_add_separator"
     * )
     *
     * @param Request $request
     * @param string menu_type
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function addSeparatorAction(Request $request, string $menu_type = 'main')
    {
        $menu = new Menu;
        $menu->setMenuType($menu_type);
        $form = $this->createForm(SimpleMenuType::class, $menu);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $slugify = new Slugify();

            $menu->setTypeTemplate($this->em->getRepository(TypeTemplate::class)->findOneByTitle(TypeTemplateTitle::SEPARATOR));
            $menu->setSlug($slugify->slugify($menu->getTitle()));

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

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

            return $this->redirectToRoute('admin_menu_edit_separator', array(
                'menu' => $menu->getId(),
                'menu_type' => $menu_type,
            ));
        }

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

    /**
     *
     * @Route(
     *      "/menu/{menu_type}/edit-separator/{menu}",
     *      name = "admin_menu_edit_separator"
     * )
     *
     * @param Request $request
     * @param Menu $menu
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editSeparatorAction(Request $request, Menu $menu, string $menu_type = 'main')
    {
        $form = $this->createForm(SimpleMenuType::class, $menu);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $slugify = new Slugify();

            $menu->setSlug($slugify->slugify($menu->getTitle()));
            
            $this->em->persist($menu);
            $this->em->flush();

            $this->addFlash('success', 'Menu modifié');

            return $this->redirectToRoute('admin_menu_edit_separator', array(
                'menu' => $menu->getId(),
                'menu_type' => $menu->getMenuType(),
            ));
        }

        return $this->render('Admin/Menu/add.html.twig', array(
            'form' => $form->createView(),
            'menu_type' => $menu->getMenuType(),
        ));
    }

    /**
     *
     * @Route(
     *      "/menu/{menu_type}/add-url",
     *      name = "admin_menu_add_url"
     * )
     *
     * @param Request $request
     * @param string menu_type
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function addUrlAction(Request $request, string $menu_type = 'main')
    {
        $menu = new Menu;
        $menu->setMenuType($menu_type);
        $form = $this->createForm(UrlMenuType::class, $menu);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $menu->setTypeTemplate($this->em->getRepository(TypeTemplate::class)->findOneByTitle(TypeTemplateTitle::FIXED));
            
            $this->em->persist($menu);
            $this->em->flush();

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

            return $this->redirectToRoute('admin_menu_edit_url', array(
                'menu' => $menu->getId(),
                'menu_type' => $menu_type,
            ));
        }

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

    /**
     *
     * @Route(
     *      "/menu/{menu_type}/edit-url/{menu}",
     *      name = "admin_menu_edit_url"
     * )
     *
     * @param Request $request
     * @param Menu $menu
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
     */
    public function editUrlAction(Request $request, Menu $menu, string $menu_type = 'main')
    {
        $form = $this->createForm(UrlMenuType::class, $menu);
        $form->handleRequest($request);

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

            $this->addFlash('success', 'Menu modifié');

            return $this->redirectToRoute('admin_menu_edit_url', array(
                'menu' => $menu->getId(),
                'menu_type' => $menu->getMenuType(),
            ));
        }

        return $this->render('Admin/Menu/add.html.twig', array(
            'form' => $form->createView(),
            'menu_type' => $menu->getMenuType(),
        ));
    }

    /**
     *
     * @Route(
     *      "/menu/edit/{id}",
     *      requirements = {"id" = "\d+"},
     *      name = "admin_menu_edit"
     * )
     *
     * @param Menu $menu
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
     */
    public function editAction(Menu $menu)
    {
        switch($menu->getTypeTemplate()->getTitle()) {
            case TypeTemplateTitle::SIMPLE:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c FROM AppBundle:Content c
                            WHERE c.menu = :menu and c.is_main = :ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'menu' => $menu,
                        'ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_page_simple', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::LIST:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c FROM AppBundle:Content c
                            WHERE c.menu = :menu and c.is_main = :ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'menu' => $menu,
                        'ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_page_liste', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::PRESENTATION:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c
                            FROM AppBundle:Content c
                            WHERE c.menu = :c_menu AND c.is_main = :c_ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'c_menu' => $menu->getId(),
                        'c_ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_page_presentation', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::FIXED:
                return $this->redirectToRoute('admin_menu_edit_url', array(
                    'menu' => $menu->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::SEPARATOR:
                return $this->redirectToRoute('admin_menu_edit_separator', array(
                    'menu' => $menu->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::LIST_CHILD:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c FROM AppBundle:Content c
                            WHERE c.menu = :menu and c.is_main = :ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'menu' => $menu->getId(),
                        'ismain'=> true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_list_child', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::MEDIA:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c FROM AppBundle:Content c
                            WHERE c.menu = :menu and c.is_main = :ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'menu' => $menu,
                        'ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();
                $contentId = 0; // Legacy - Add New Content entity to edited Menu

                if (!empty($content)) {
                    $contentId = $content->getId();
                }
            
                return $this->redirectToRoute('admin_content_edit_category_media', array(
                    'menu' => $menu->getId(),
                    'content' => $contentId,
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::NEWS:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c FROM AppBundle:Content c
                            WHERE c.menu = :menu and c.is_main = :ismain and c.is_actu = :isactu
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'menu' => $menu,
                        'ismain' => true,
                        'isactu' => false,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();
                $contentId = 0; // Legacy - Add New Content entity to edited Menu

                if (!empty($content)) {
                    $contentId = $content->getId();
                }

                return $this->redirectToRoute('admin_content_edit_category_actu', array(
                    'menu' => $menu->getId(),
                    'content' => $contentId,
                    'menu_type' => $menu->getMenuType(),
                ));
                break;

            case TypeTemplateTitle::CONTACT:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c FROM AppBundle:Content c
                            WHERE c.menu = :menu and c.is_main = :ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'menu' => $menu,
                        'ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_page_contact', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;
            case TypeTemplateTitle::PARTNERS:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c
                            FROM AppBundle:Content c
                            WHERE c.menu = :c_menu AND c.is_main = :c_ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'c_menu' => $menu->getId(),
                        'c_ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_page_partners', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;
            case TypeTemplateTitle::TESTIMONIALS:
                $querycontents = $this->em
                    ->createQuery(
                        "SELECT c
                            FROM AppBundle:Content c
                            WHERE c.menu = :c_menu AND c.is_main = :c_ismain
                            ORDER BY c.position ASC, c.id ASC"
                    )
                    ->setParameters(array(
                        'c_menu' => $menu->getId(),
                        'c_ismain' => true,
                    ))
                    ->setMaxResults(1);
                $content = $querycontents->getOneOrNullResult();

                return $this->redirectToRoute('admin_content_edit_page_testimonials', array(
                    'menu' => $menu->getId(),
                    'content' => $content->getId(),
                    'menu_type' => $menu->getMenuType(),
                ));
                break;
        }

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

    /**
     * Positionne un élément parmi ses semblables
     *
     * @Route(
     *      "/admin/menu/position",
     *      name = "element_position"
     * )
     *
     * @param Request $request
     * @return Response
     */
    public function positionAction(Request $request)
    {
        $type = $request->get('type');
        $liste = $request->get('list');

        $i = 1;
        foreach ($liste as $elementid) {
            $element = $this->em->getRepository('AppBundle:'.$type)->find($elementid);
            if (!$element) {
                throw $this->createNotFoundException(
                    'No product found for id '.$elementid
                );
            }

            $element->setPosition($i);
            $i++;
        }
        $this->em->flush();

        return new Response();
    }

    /**
     * Met à jour la position d'un média au sein de tous les médias du même type qui sont rattaché au même menu.
     *
     * @Route(
     *      "/menu/position/inside/{mediaType}/{menuMediaId}",
     *      requirements = {"mediaType" = "pdf|picture|video", "menuMediaId" = "\d+"},
     *      name = "element_position_inside"
     * )
     *
     * @ParamConverter(
     *      "menuMedia",
     *      class="AppBundle:MenuMedia",
     *      options={"id"="menuMediaId"}
     * )
     *
     * @param Request $request
     * @param string $mediaType
     * @param MenuMedia $menuMedia
     * @return Response
     */
    public function positionMediaAction(Request $request, $mediaType, MenuMedia $menuMedia)
    {
        $positionCurrent = $menuMedia->getPosition();
        $positionDesired = intval($request->get('positionDesired'), 10);

        if ($positionCurrent !== $positionDesired) {
            // Détermination des autres médias affectés par ce repositionnement.
            // Les repositionner tous serait plus simple au niveau de l'implémentation,
            // mais plus coûteux concernant les accès à la BDD (nombre de lignes affectées)
            if ($positionCurrent > $positionDesired) {
                $positionMin = array(
                    'operator' => '>=',
                    'value' => $positionDesired,
                );

                $positionMax = array(
                    'operator' => '<',
                    'value' => $positionCurrent,
                );
            } else {
                $positionMin = array(
                    'operator' => '>',
                    'value' => $positionCurrent,
                );

                $positionMax = array(
                    'operator' => '<=',
                    'value' => $positionDesired,
                );
            }

            $medias = $this->em->getRepository('AppBundle:Media')->findByMenu(
                $menuMedia->getMenu()->getId(),
                array(
                    'type' => $mediaType,
                    'positionMin' => $positionMin,
                    'positionMax' => $positionMax,
                )
            );

            // Détermine le sens (vers le haut ou le bas) dans lequel doivent être "poussés" les autres médias affectés
            $increment = ($positionCurrent > $positionDesired) ? 1 : -1;

            // Mise à jour des autres médias affectés
            foreach ($medias as $media) {
                $mm = $media->getMenuMedias()->get(0); // La requête ne retourne qu'un seul MenuMedia

                $mm->setPosition($mm->getPosition() + $increment);
                $this->em->persist($mm);
            }

            // Mise à jour du média repositionné par l'utilisateur
            $menuMedia->setPosition($positionDesired);
            $this->em->persist($menuMedia);

            $this->em->flush();
        }

        return new Response();
    }

    /**
     *
     * @Route(
     *      "/menu/delete/{id}/{type}",
     *      requirements = {"id" = "\d+"},
     *      name = "admin_menu_delete"
     * )
     * @param CacheManager $cacheManager
     * @param int $id
     * @param string $type
     * @return Response
     */
    public function deleteAction(CacheManager $cacheManager, int $id, string $type)
    {
        $typeIn = 'Content';

        if ('ContentIn' === $type) {
            $type = 'Content';
            $typeIn = 'ContentIn';
        }

        $entity = $this->em->getRepository('AppBundle:' . $type)->findOneById($id);

        if ($entity instanceof Menu) {
            $contents = $this->em->getRepository(Content::class)->findByMenu($id);

            foreach($contents as $content) {
                $this->em->remove($content);
            }
        } elseif ($entity instanceof Media) {
            // Delete picture thumbnails
            if (MediaType::PICTURE === $entity->getType()) {
                $cacheManager->remove($entity->getWebPathPicture());
            }
        }

        $allowedTypes = ['Content', 'Media', 'Menu', 'Slider'];
        if (in_array($type, $allowedTypes, true) || 'ContentIn' === $typeIn) {
            $this->em->remove($entity);
            $this->em->flush();

            $this->addFlash('success', $type.' supprimé');
        }

        return new Response();
    }

    /**
     *
     * @Route(
     *      "/menu/delete-ajax/{id}/Content",
     *      name = "admin_menu_delete_ajax",
     *  )
     * @param int $id
     * @return Response
     */
    public function deleteAjaxAction(int $id)
    {
        $content = $this->em->getRepository(Content::class)->findOneById($id);

        $this->em->remove($content);
        $this->em->flush();

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

        return new Response();
    }

    /**
     *
     * @Route(
     *      "/element/actif",
     *      name = "element_actif"
     * )
     * @param Request $request
     * @return Response
     */
    public function actifAction(Request $request)
    {
        $id = $request->get('id');
        $actif = $request->get('actif');
        $type = $request->get('type');

        $element = $this->em->getRepository('AppBundle:' . $type)->find($id);

        if (!$element) {
            throw $this->createNotFoundException(
                'No product found for id '.$id
            );
        }

        $element->setIsActive($actif);
        $this->em->flush();
        
        return new Response();
    }
}
