<?php

namespace App\Entity;

use App\Repository\TaskRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

// Les tâches sont l’unité de base du travail à faire. Elles sont groupées dans
// des projets et peut être appropriés par les utilisateurs selon leur état.
#[ORM\Entity(repositoryClass: TaskRepository::class)]
class Task
{
    public const STATUS_TODO = 'todo';
    public const STATUS_DOING = 'doing';
    public const STATUS_DONE = 'done';

    public const TRANSITION_START = 'start';
    public const TRANSITION_FINISH = 'finish';
    public const TRANSITION_CANCEL = 'cancel';
    public const TRANSITION_RESET = 'reset';

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $name = null;

    #[ORM\Column(length: 255, unique: true)]
    #[Gedmo\Slug(fields: ['name'])]
    private ?string $slug = null;

    #[ORM\Column(nullable: true)]
    private ?int $urgent = null;

    #[ORM\Column(nullable: true)]
    private ?int $important = null;

    #[ORM\Column(length: 255)]
    private ?string $status = null;

    #[ORM\ManyToOne(inversedBy: 'tasks')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Project $project = null;

    #[ORM\Column(type: Types::TEXT)]
    private ?string $geojson = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $osm = null;

    /**
     * @var Collection<int, Comment>
     */
    #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'task', orphanRemoval: true)]
    private Collection $comments;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $description = null;

    #[ORM\ManyToOne(inversedBy: 'tasks')]
    #[ORM\JoinColumn(nullable: false)]
    private ?User $createdBy = null;

    #[ORM\Column]
    #[Gedmo\Timestampable(on: 'create')]
    private ?\DateTimeImmutable $createdAt = null;

    #[ORM\ManyToOne(inversedBy: 'lockedTasks')]
    private ?User $lockedBy = null;

    #[ORM\Column(nullable: true)]
    private ?\DateTimeImmutable $lockedAt = null;

    #[ORM\Column(nullable: true)]
    private ?\DateTimeImmutable $startAt = null;

    #[ORM\Column(nullable: true)]
    private ?\DateTimeImmutable $finishAt = null;

    #[ORM\ManyToOne]
    private ?User $doneBy = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $changesets_result = null;

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

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): static
    {
        $this->name = $name;

        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function getUrgent(): ?int
    {
        return $this->urgent;
    }

    public function setUrgent(?int $urgent): static
    {
        $this->urgent = $urgent;

        return $this;
    }

    public function getImportant(): ?int
    {
        return $this->important;
    }

    public function setImportant(?int $important): static
    {
        $this->important = $important;

        return $this;
    }

    public function getStatus(): ?string
    {
        return $this->status;
    }

    public function setStatus($status, array $context = []): static
    {
        $this->status = $status;

        return $this;
    }

    public function getProject(): ?Project
    {
        return $this->project;
    }

    public function setProject(?Project $project): static
    {
        $this->project = $project;

        return $this;
    }

    public function hasGeojson(): bool
    {
        return
            isset($this->geojson)
            and !empty($this->geojson)
            and ('{}' !== $this->geojson)
        ;
    }

    public function getGeojson(): ?string
    {
        return $this->geojson;
    }

    public function setGeojson(string $geojson): static
    {
        $this->geojson = $geojson;

        return $this;
    }

    public function hasOsm(): bool
    {
        return isset($this->osm);
    }

    public function getOsm(): ?string
    {
        return $this->osm;
    }

    public function setOsm(string $osm): static
    {
        $this->osm = $osm;

        return $this;
    }

    /**
     * @return Collection<int, Comment>
     */
    public function getComments(): Collection
    {
        return $this->comments;
    }

    public function addComment(Comment $comment): static
    {
        if (!$this->comments->contains($comment)) {
            $this->comments->add($comment);
            $comment->setTask($this);
        }

        return $this;
    }

    public function removeComment(Comment $comment): static
    {
        if ($this->comments->removeElement($comment)) {
            // set the owning side to null (unless already changed)
            if ($comment->getTask() === $this) {
                $comment->setTask(null);
            }
        }

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): static
    {
        $this->description = $description;

        return $this;
    }

    public function getCreatedBy(): ?User
    {
        return $this->createdBy;
    }

    public function setCreatedBy(?User $createdBy): static
    {
        $this->createdBy = $createdBy;

        return $this;
    }

    public function getCreatedAt(): ?\DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function setCreatedAt(\DateTimeImmutable $createdAt): static
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getLockedBy(): ?User
    {
        return $this->lockedBy;
    }

    public function setLockedBy(?User $lockedBy): static
    {
        $this->lockedBy = $lockedBy;

        return $this;
    }

    public function getLockedAt(): ?\DateTimeImmutable
    {
        return $this->lockedAt;
    }

    public function setLockedAt(?\DateTimeImmutable $lockedAt): static
    {
        $this->lockedAt = $lockedAt;

        return $this;
    }

    public function isLocked(): bool
    {
        return !is_null($this->lockedBy);
    }

    public function lock(User $user): static
    {
        $this->setLockedBy($user);
        $this->setLockedAt(new \DateTimeImmutable('now'));

        return $this;
    }

    public function unlock(): static
    {
        $this->setLockedBy(null);
        $this->setLockedAt(null);

        return $this;
    }

    public function getStartAt(): ?\DateTimeImmutable
    {
        return $this->startAt;
    }

    public function setStartAt(?\DateTimeImmutable $startAt): static
    {
        $this->startAt = $startAt;

        return $this;
    }

    public function getFinishAt(): ?\DateTimeImmutable
    {
        return $this->finishAt;
    }

    public function setFinishAt(?\DateTimeImmutable $finishAt): static
    {
        $this->finishAt = $finishAt;

        return $this;
    }

    public function getDoneBy(): ?User
    {
        return $this->doneBy;
    }

    public function setDoneBy(?User $doneBy): static
    {
        $this->doneBy = $doneBy;

        return $this;
    }

    public function getChangesetsResult(): ?string
    {
        return $this->changesets_result;
    }

    public function setChangesetsResult(?string $changesets_result): static
    {
        $this->changesets_result = $changesets_result;

        return $this;
    }
}
