<?php

namespace AppBundle\Repository;

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

/**
 * ModuleRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class ModuleRepository extends \Doctrine\ORM\EntityRepository
{
    /**
     * Retourne l'ensemble des modules liés à un menu donné.
     * Les modules sont ordonnés selon leur position.
     *
     * @param string $position Position.
     * @return array
     */
    public function findByPosition($position): array
    {
        $modules = $this->findBy([
            'isActive' => true, 
            'position' => $position,
        ], [
            'ordering' => 'ASC',
            'created' => 'DESC',
        ]);
        
        return $modules;
    }

    /**
     * Retourne l'ensemble des modules liés à un menu donné.
     * Les modules sont ordonnés selon leur position.
     *
     * @param string $position 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();
        
        $qbm
            ->select('module')
            ->from('AppBundle:Module', 'module')
            ->leftJoin('module.menu', 'menu')
            ->where('menu = :menu_id OR menu IS NULL')
            ->orderBy('module.ordering', 'ASC')
            ->addOrderBy('module.created', 'DESC')
            ->setParameter('menu_id', $menuId);

        if (isset($filters['position'])) {
            if (!is_array($filters['position'])) {
                $qbm
                    ->andWhere('module.position = :module_position')
                    ->setParameter('module_position', $filters['position']);
            } else {
                $qbm
                    ->andWhere('module.position IN (:module_positions)')
                    ->setParameter('module_positions', implode(',', $filters['position']));
            }
        }

        if (isset($filters['likePosition'])) {
            if (!is_array($filters['likePosition'])) {
                $qbm
                    ->andWhere('module.position LIKE :module_lposition')
                    ->setParameter('module_lposition', $filters['likePosition']);
            } else {
                $sql = '';

                foreach ($filters['likePosition'] as $i => $position) {
                    if ($i !== 0) { 
                        $sql .= ' OR ';
                    }
                    $sql .= 'module.position LIKE :module_lposition_'.$i;

                    $qbm
                        ->setParameter('module_lposition_'.$i, $position);
                }
                
                $qbm
                    ->andWhere($sql);
            }
        }

        if (isset($filters['notLikePosition'])) {
            if (!is_array($filters['notLikePosition'])) {
                $qbm
                    ->andWhere('module.position NOT LIKE :module_nlposition')
                    ->setParameter('module_nlposition', $filters['notLikePosition']);
            } else {
                $sql = '';

                foreach ($filters['notLikePosition'] as $i => $position) {
                    if ($i !== 0) { 
                        $sql .= ' AND ';
                    }
                    $sql .= 'module.position NOT LIKE :module_nlposition_'.$i;

                    $qbm
                        ->setParameter('module_nlposition_'.$i, $position);
                }

                $qbm
                    ->andWhere($sql);
            }
        }

        if (isset($filters['isActive'])) {
            $qbm
                ->andWhere('module.isActive = :module_is_active')
                ->setParameter('module_is_active', (bool) $filters['isActive']);
        }

        if (isset($filters['type'])) {
            if (!is_array($filters['notLikePosition'])) {
                $qbm
                    ->andWhere('module.type = :module_type')
                    ->setParameter('module_type', $filters['type']);
            } else {
                $qbm
                    ->andWhere('module.type IN (:module_types)')
                    ->setParameter('module_types', implode(',', $filters['type']));
            }
        }

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