<?php
namespace App\Form\Activity;

use App\Entity\ActivityEntity;
use App\Entity\ActorEntity;
use App\Enum\StatusEnum;
use App\Form\AbstractFormManager;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Repository\ActivityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\Common\Collections\Criteria;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class ActivityFilterForm extends AbstractFormManager
{

    /** @var array List of actors */
    protected $actors = [];

    /**
     * {@inheritdoc}
     */
    public function __construct(FormBuilderInterface $formBuilder, array $data = [], bool $usesToken = true)
    {
        $this->actors = $data['actors'];
        $formBuilder->setData([
            'actor' => null,
            'followed' => false,

            'status' => null,
            'active' => false,
            'notClosed' => true,
        ]);
        parent::__construct($formBuilder, $data, $usesToken);
    }

    /**
     * Create query builder
     *
     * @param ActivityRepository $activityRepository
     * @return array
     */
    public function getActivities(ActivityRepository $activityRepository): array
    {
        $data = $this->getData();

        // Create filter
        $criteria = new Criteria();

        // Filter actors
        if (!is_null($data['actor'])) {
            $criteria->andWhere($criteria->expr()
                ->eq('activity.actor', $data['actor']));
        }
        if ($data['followed']) {
            $criteria->andWhere($criteria->expr()
                ->eq('actor.followed', true));
        }

        // Filter status
        if (!is_null($data['status'])) {
            $criteria->andWhere($criteria->expr()
                ->eq('activity.status', $data['status']));
        }
        if ($data['active']) {
            $criteria->andWhere($criteria->expr()
                ->in('activity.status', StatusEnum::ACTIVE_STATUS));
        }
        if ($data['notClosed']) {
            $criteria->andWhere($criteria->expr()
                ->neq('activity.status', StatusEnum::CLOSED));
        }

        // Create query
        $query = $activityRepository->createQueryBuilder('activity');
        $query->join(ActorEntity::class, 'actor', Join::WITH, 'activity.actor = actor');
        $query->addCriteria($criteria);

        return $query->getQuery()->execute([], Query::HYDRATE_OBJECT);
    }

    /**
     * {@inheritdoc}
     */
    public function getTemplate(): string
    {
        return '_includes/html/form/activity/filter.html.twig';
    }

    /**
     * {@inheritdoc}
     */
    protected function addFields($formBuilder, $options): void
    {
        // Actor filters
        $formBuilder->add('actor', EntityType::class, [
            'class' => ActorEntity::class,
            'choices' => $this->actors,
            'group_by' => function (ActorEntity $choice) {
                if ($choice->getFollowed()) {
                    return 'Suivi';
                }
                if ($choice->getActive()) {
                    return 'Actif';
                }

                return 'Inactif';
            },
            'choice_label' => 'displayName',
            'required' => false,
        ])
            ->add('followed', CheckboxType::class, [
            'required' => false,
        ]);

        // Status filters
        $formBuilder->add('status', ChoiceType::class, [
            'required' => false,
            'choices' => ActivityEntity::VALID_STATUS,
            'choice_label' => function ($choice, $key, $value) {
                return StatusEnum::STATUS_NAME[$choice];
            },
        ])
            ->add('active', CheckboxType::class, [
            'required' => false,
        ])
            ->add('notClosed', CheckboxType::class, [
            'required' => false,
        ]);

        // Submit
        $formBuilder->add('submit', SubmitType::class);
    }
}