<?php
namespace App\Form\Task;

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

class TaskFilterForm 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,
            'unassigned' => false,
            'followed' => false,

            'status' => null,
            'active' => false,
            'notClosed' => true,

            'doneAfter' => null,
            'doneBefore' => null,
        ]);
        parent::__construct($formBuilder, $data, $usesToken);
    }

    /**
     * Get tasks
     *
     * @param TaskRepository $taskRepository
     * @return array
     */
    public function getTasks(TaskRepository $taskRepository): array
    {
        $data = $this->getData();

        // Create query
        $query = $taskRepository->createQueryBuilder('task');

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

        // Filter actors
        if ($data['followed']) {
            $query->join(ActorEntity::class, 'actor', Join::WITH, 'task.actor = actor');
            $criteria->andWhere($criteria->expr()
                ->eq('actor.followed', true));
        }
        if (!is_null($data['actor'])) {
            $criteria->andWhere($criteria->expr()
                ->eq('task.actor', $data['actor']));
        }
        if ($data['unassigned']) {
            $criteria->andWhere($criteria->expr()
                ->isNull('task.actor'));
        }

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

        // Filter dates
        if (!is_null($data['doneAfter'])) {
            $criteria->andWhere($criteria->expr()
                ->gt('task.executionDate', $data['doneAfter']));
        }
        if (!is_null($data['doneBefore'])) {
            $criteria->andWhere($criteria->expr()
                ->lt('task.executionDate', $data['doneBefore']));
        }

        $query->addCriteria($criteria);

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

    /**
     * {@inheritdoc}
     */
    public function getTemplate(): string
    {
        return '_includes/html/form/task/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('unassigned', CheckboxType::class, [
            'required' => false,
        ])
            ->add('followed', CheckboxType::class, [
            'required' => false,
        ]);

        // Status filters
        $formBuilder->add('status', ChoiceType::class, [
            'required' => false,
            'choices' => TaskEntity::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,
        ]);

        // Date filters
        $formBuilder->add('doneAfter', DateType::class, [
            'required' => false,
            'widget' => 'single_text',
        ])->add('doneBefore', DateType::class, [
            'required' => false,
            'widget' => 'single_text',
        ]);

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