<?php
/**
 * @author      Aurélien BERNARD - TRYDEA - 2020
 */

declare(strict_types=1);

namespace Mobile\Measure\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Mobile\Project\Entity\DataEntryProject;
use Shared\Authentication\Entity\IdentifiedEntity;
use Shared\Utils\ArrayCollectionUtils;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ORM\Entity(repositoryClass="Mobile\Measure\Repository\DataEntryRepository")
 *
 * @ORM\Table(name="data_entry", schema="adonis")
 */
class DataEntry extends IdentifiedEntity
{
    public const STATUS_NEW = 'new';
    public const STATUS_WIP = 'wip';
    public const STATUS_DONE = 'done';

    /**
     * @ORM\OneToOne(targetEntity="Mobile\Project\Entity\DataEntryProject", inversedBy="dataEntry")
     *
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     */
    private DataEntryProject $project;

    /**
     * @ORM\Column(type="string", nullable=false)
     */
    private string $status = '';

    /**
     * @ORM\Column(type="datetime", nullable=false)
     */
    private \DateTime $startedAt;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private ?\DateTime $endedAt = null;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private ?string $currentPosition = null;

    /**
     * @var string[]|null
     *
     * @ORM\Column(type="json", nullable=true)
     */
    private ?array $workpath = null;

    /**
     * @var Collection<int, Session>
     *
     * @Groups({"status_project_webapp_return_data"})
     *
     * @ORM\OneToMany(targetEntity="Mobile\Measure\Entity\Session", mappedBy="dataEntry", cascade={"persist", "remove", "detach"})
     */
    private Collection $sessions;

    public static function build(\DateTime $startedAt): self
    {
        return new self($startedAt);
    }

    /**
     * @internal
     * @see self::build()
     */
    public function __construct(\DateTime $startedAt = null)
    {
        $this->startedAt = $startedAt ?? new \DateTime();
        $this->status = self::STATUS_NEW;
        $this->sessions = new ArrayCollection();
    }

    /**
     * @psalm-mutation-free
     */
    public function getProject(): DataEntryProject
    {
        return $this->project;
    }

    /**
     * @return $this
     */
    public function setProject(DataEntryProject $project): self
    {
        $this->project = $project;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getStatus(): string
    {
        return $this->status;
    }

    /**
     * @return $this
     */
    public function setStatus(string $status): self
    {
        $this->status = $status;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getStartedAt(): \DateTime
    {
        return $this->startedAt;
    }

    /**
     * @return $this
     */
    public function setStartedAt(\DateTime $startedAt): self
    {
        $this->startedAt = $startedAt;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getEndedAt(): ?\DateTime
    {
        return $this->endedAt;
    }

    /**
     * @return $this
     */
    public function setEndedAt(?\DateTime $endedAt): self
    {
        $this->endedAt = $endedAt;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getCurrentPosition(): ?string
    {
        return $this->currentPosition;
    }

    /**
     * @return $this
     */
    public function setCurrentPosition(?string $currentPosition): self
    {
        $this->currentPosition = $currentPosition;

        return $this;
    }

    /**
     * @return string[]|null
     *
     * @psalm-mutation-free
     */
    public function getWorkpath(): ?array
    {
        return $this->workpath;
    }

    /**
     * @param string[]|null $workpath
     *
     * @return $this
     */
    public function setWorkpath(?array $workpath): self
    {
        $this->workpath = $workpath;

        return $this;
    }

    /**
     * @return Collection<int,  Session>
     *
     * @psalm-mutation-free
     */
    public function getSessions(): Collection
    {
        return $this->sessions;
    }

    /**
     * @param iterable<int,  Session> $sessions
     *
     * @return $this
     */
    public function setSessions(iterable $sessions): self
    {
        ArrayCollectionUtils::update($this->sessions, $sessions, function (Session $session) {
            $session->setDataEntry($this);
        });

        return $this;
    }

    /**
     * @return $this
     */
    public function addSession(Session $session): self
    {
        if (!$this->sessions->contains($session)) {
            $this->sessions->add($session);
            $session->setDataEntry($this);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function removeSession(Session $session): self
    {
        if ($this->sessions->contains($session)) {
            $this->sessions->removeElement($session);
        }

        return $this;
    }
}
