<?php

namespace AppBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;

/**
 * MediaRepository
 */
class MediaRepository extends EntityRepository
{
    /**
     * Retourne l'ensemble des médias liés à un menu donné.
     * Les médias sont groupés par type, et ordonnés selon leur position.
     *
     * @param int $menuId Identifiant du menu.
     * @param array $filters Liste de filtres à appliquer à la recherche: is_active, positionMin, positionMax
     * @param int $hydratation Mode d'hydratation de Doctrine
     *
     * @return array
     */
    public function findByMenu($menuId, $filters = array(), $hydratation = Query::HYDRATE_OBJECT): array
    {
        $qbm = $this->getEntityManager()->createQueryBuilder();
        $comparisonOperatorsAuthorized = array(
            'min' => array('>', '>='),
            'max' => array('<', '<='),
        );

        $qbm
            ->select('media, mm')
            ->from('AppBundle:Media', 'media')
            ->leftJoin('media.menu', 'menu')
            ->leftJoin('media.menumedias', 'mm', 'with', 'mm.menu = menu')
            ->where('menu.id = :menu_id')
            ->orderBy('media.type', 'ASC')
            ->addOrderBy('mm.position', 'ASC')
            ->setParameter('menu_id', $menuId);

        if (isset($filters['type'])) {
            $qbm
                ->andWhere('media.type = :media_type')
                ->setParameter('media_type', $filters['type']);
        }

        if (isset($filters['is_active']) && true === $filters['is_active']) {
            $qbm
                ->andWhere('media.is_active = :media_is_active')
                ->setParameter('media_is_active', true);
        }

        if (isset($filters['positionMin']) && null !== $filters['positionMin']['value'] && in_array($filters['positionMin']['operator'], $comparisonOperatorsAuthorized['min'])) {
            $qbm
                ->andWhere('mm.position '.$filters['positionMin']['operator'].' :mm_position_min')
                ->setParameter('mm_position_min', $filters['positionMin']['value']);
        }

        if (isset($filters['positionMax']) && null !== $filters['positionMax']['value'] && in_array($filters['positionMax']['operator'], $comparisonOperatorsAuthorized['max'])) {
            $qbm
                ->andWhere('mm.position '.$filters['positionMax']['operator'].' :mm_position_max')
                ->setParameter('mm_position_max', $filters['positionMax']['value']);
        }

        return $qbm->getQuery()->getResult($hydratation);
    }

    /**
     * Retoune la plus grande position d'un média pour chaque menu qui en possède.
     * Les résultat sont groupés par type de média pour chaque menu, si aucun type n'est spécifié.
     *
     * @param array $menusIds Liste des identifiants de menu auquels restreindre la recherche
     * @param string $mediaType Type du média recherché
     * @param int $hydratation Mode d'hydratation de Doctrine
     *
     * @return array
     */
    function findAllByHighestPosition($menusIds = array(), $mediaType = null, $hydratation = Query::HYDRATE_OBJECT): array
    {
        $qbm = $this->getEntityManager()->createQueryBuilder();
        $qbm
            ->select('menu.id, MAX(mm.position) AS highest')
            ->from('AppBundle:MenuMedia', 'mm')
            ->leftJoin('mm.menu', 'menu')
            ->leftJoin('mm.media', 'media')
            ->groupBy('menu.id');

        if (count($menusIds) > 0) {
            $qbm
                ->andWhere($qbm->expr()->in('menu.id', ':menu_ids'))
                ->setParameter('menu_ids', $menusIds);
        }

        if (null === $mediaType) {
            $qbm->addGroupBy('media.type');
        } else {
            $qbm
                ->andWhere('media.type = :media_type')
                ->setParameter('media_type', $mediaType);
        }

        return $qbm->getQuery()->getResult($hydratation);
    }



    /**
     * Get List with only id and name by a set of criteria.
     *
     * Optionally sorting and limiting details can be passed. An implementation may throw
     * an UnexpectedValueException if certain values of the sorting or limiting details are
     * not supported.
     *
     * @param array      $criteria // Not used
     * @param array|null $orderBy
     * @param int|null   $limit
     * @param int|null   $offset
     *
     * @return array The objects.
     *
     * @throws \UnexpectedValueException
     */
    public function findSimpleListBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) 
    {
        $items_list = array();

        $tmp = $this->findBy($criteria, $orderBy, $limit, $offset);
        
        foreach($tmp as $item) {
            $items_list[$item->getId()] = $item->getTitle();
        }

        return $items_list;
    } 
}
