<?php

namespace Comitium5\DesignerBundle\Repository\Widget;

use Comitium5\DesignerBundle\Entity\User;
use Comitium5\DesignerBundle\Model\Interfaces\SearchableRepositoryInterface;
use Comitium5\DesignerBundle\Model\WidgetType;
use Comitium5\DesignerBundle\Repository\AbstractRepository;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Class WidgetRepository
 *
 * @author Carles Gómez <carles@bab-soft.com>
 * @package Comitium5\DesignerBundle\Repository\Widget
 */
class WidgetRepository extends AbstractRepository implements SearchableRepositoryInterface
{
    /**
     * @param $term
     * @param array $params
     *
     * @return mixed
     */
    public function search($term, array $params = array())
    {
        $builder = $this->createQueryBuilder("w");

        if(!empty($term)) {
            foreach (explode(' ', $term) as $key => $word) {
                $builder
                    ->andWhere("CONCAT_WS('', w.name, w.title, w.description) LIKE ?$key")
                    ->setParameter("$key", "%$word%");
            }
        }

        if (!empty($params['type'])) {
            $builder
                ->andWhere('w.type = :type')
                ->setParameter('type', $params['type']);
        }

        if (!empty($params['group'])) {
            $groups  = $params['group'];

            if ($groups instanceof ArrayCollection && $groups->count() > 0) {
                $builder
                    ->andWhere('w.group IN (:group)')
                    ->setParameter('group', $groups);
            }
        }

        if (!empty($params['workflow_state']['state'])) {
            $states = $params['workflow_state']['state'];

            if ($states instanceof ArrayCollection && $states->count() > 0) {
                $builder
                    ->andWhere('w.state IN (:state)')
                    ->setParameter('state', $states);
            }
        }

        $builder
            ->addOrderBy('w.createdAt', 'DESC')
            ->addOrderBy('w.id', 'ASC');

        return $builder;
    }

    /**
     * @return \Doctrine\ORM\QueryBuilder
     */
    public function findAll()
    {
        $builder = $this
            ->createQueryBuilder('w')
            ->addOrderBy('w.createdAt', 'DESC')
            ->addOrderBy('w.id', 'ASC')
        ;

        return $builder;
    }

    /**
     * @param String $search
     * @param int $stateBehaviour
     * @param array $params
     *
     * @return mixed
     */
    public function findAllByStateBehaviour(string $search, int $stateBehaviour, array $params = []) {
        $builder = $this
            ->search($search, $params)
            ->innerJoin('w.state', 's')
            ->innerJoin('s.behaviours', 'b')
            ->andWhere('b.behaviour = :behaviour_code')
            ->setParameter('behaviour_code', $stateBehaviour);

        return $builder;
    }

    /**
     * @param String $search
     * @param array $statesBehaviour
     * @param array $params
     *
     * @return mixed
     */
    public function findAllByStatesBehaviour(string $search, array $statesBehaviour, array $params = []) {
        $builder = $this
            ->search($search, $params)
            ->innerJoin('w.state', 's')
            ->innerJoin('s.behaviours', 'b')
            ->andWhere('b.behaviour IN (:behaviour_code)')
            ->setParameter('behaviour_code', $statesBehaviour);

        return $builder;
    }

    /**
     * @param $search
     * @param array $statesBehaviour
     * @param User $user
     *
     * @return array|int|string
     */
    public function findByVisualEditor($search, array $statesBehaviour, User $user)
    {
        $builder = $this
            ->createQueryBuilder("w")
            ->andWhere('w.type NOT IN (:types)')
            ->setParameter('types', [
                WidgetType::ABSTRACTS
            ])
        ;

        if (!empty($search)) {
            foreach (explode(' ', $search) as $key => $word) {
                $builder
                    ->andWhere("CONCAT_WS('', w.name, w.title, w.description) LIKE ?$key")
                    ->setParameter("$key", "%$word%");
            }
        } else {
            $builder
                ->leftJoin("w.widgetFavorites", "wf")
                ->andWhere("wf.user = :user")
                ->setParameter("user", $user->getId())
            ;
        }

        return $builder
            ->getQuery()
            ->getResult();
    }
}
