<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\TaskBundle\Entity;

use Chill\TaskBundle\Entity\Task\SingleTaskPlaceEvent;
use Chill\TaskBundle\Repository\SingleTaskRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * SingleTask.
 */
#[ORM\Entity(repositoryClass: SingleTaskRepository::class)]
#[ORM\Table(name: 'chill_task.single_task')]
#[ORM\Index(name: 'by_type', columns: ['type'])]
#[ORM\Index(name: 'by_current_state', columns: ['current_states'])]
#[ORM\Index(name: 'by_end_date', columns: ['end_date'])]
class SingleTask extends AbstractTask
{
    #[Serializer\Groups(['read'])]
    #[ORM\Column(name: 'end_date', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)]
    private ?\DateTime $endDate = null;

    #[Serializer\Groups(['read'])]
    #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    private ?int $id = null;

    #[ORM\ManyToOne(targetEntity: RecurringTask::class, inversedBy: 'singleTasks')]
    private ?RecurringTask $recurringTask = null;

    #[Serializer\Groups(['read'])]
    #[Assert\Expression('value === null or this.getEndDate() === null or value < this.getEndDate()', message: 'The start date must be before the end date')]
    #[Assert\Expression('value === null or this.getWarningDate() === null or this.getWarningDate() > this.getStartDate()', message: 'The start date must be before warning date')]
    #[ORM\Column(name: 'start_date', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)]
    private ?\DateTime $startDate = null;

    /**
     * @var Collection<int, SingleTaskPlaceEvent>
     */
    #[ORM\OneToMany(mappedBy: 'task', targetEntity: SingleTaskPlaceEvent::class, cascade: ['remove'])]
    private Collection $taskPlaceEvents;

    #[Serializer\Groups(['read'])]
    #[Assert\Expression('!(value != null and this.getEndDate() == null)', message: 'An end date is required if a warning interval is set')]
    #[ORM\Column(name: 'warning_interval', type: \Doctrine\DBAL\Types\Types::DATEINTERVAL, nullable: true)]
    private ?\DateInterval $warningInterval = null;

    public function __construct()
    {
        $this->taskPlaceEvents = new ArrayCollection();
    }

    /**
     * Get endDate.
     */
    public function getEndDate(): ?\DateTime
    {
        return $this->endDate;
    }

    /**
     * Get id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    public function getRecurringTask(): RecurringTask
    {
        return $this->recurringTask;
    }

    /**
     * Get startDate.
     *
     * @return \DateTime
     */
    public function getStartDate()
    {
        return $this->startDate;
    }

    public function getTaskPlaceEvents(): Collection
    {
        return $this->taskPlaceEvents;
    }

    /**
     * Get the Warning date, computed from the difference between the
     * end date and the warning interval.
     *
     * Return null if warningDate or endDate is null
     *
     * @return \DateTimeImmutable
     */
    #[Serializer\Groups(['read'])]
    public function getWarningDate()
    {
        if (null === $this->getWarningInterval()) {
            return null;
        }

        if (null === $this->getEndDate()) {
            return null;
        }

        return \DateTimeImmutable::createFromMutable($this->getEndDate())
            ->sub($this->getWarningInterval());
    }

    /**
     * Get warningInterval.
     */
    public function getWarningInterval(): ?\DateInterval
    {
        return $this->warningInterval;
    }

    /**
     * Set endDate.
     *
     * @return SingleTask
     */
    public function setEndDate(?\DateTime $endDate)
    {
        $this->endDate = $endDate;

        return $this;
    }

    public function setRecurringTask(RecurringTask $recurringTask)
    {
        $this->recurringTask = $recurringTask;
    }

    /**
     * Set startDate.
     *
     * @return SingleTask
     */
    public function setStartDate(?\DateTime $startDate)
    {
        $this->startDate = $startDate;

        return $this;
    }

    public function setTaskPlaceEvents(Collection $taskPlaceEvents)
    {
        $this->taskPlaceEvents = $taskPlaceEvents;

        return $this;
    }

    /**
     * Set warningInterval.
     *
     * @return SingleTask
     */
    public function setWarningInterval(?\DateInterval $warningInterval)
    {
        $this->warningInterval = $warningInterval;

        return $this;
    }
}
