<?php

/*
 * @author TRYDEA - 2024
 */

namespace Webapp\Core\Entity;

use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Core\Serializer\Filter\GroupFilter;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use Shared\Authentication\Entity\IdentifiedEntity;
use Shared\Utils\ArrayCollectionUtils;
use Symfony\Component\Serializer\Annotation\Groups;
use Webapp\Core\Annotation\GraphicallyDeletable;
use Webapp\Core\Traits\GraphicallyDeletableEntity;

/**
 * @ApiResource(
 *     collectionOperations={
 *          "get"={}
 *     },
 *     itemOperations={
 *          "get"={},
 *          "patch"={"denormalization_context"={"groups"={"declare_dead", "edit"}}}
 *     }
 * )
 *
 * @ApiFilter(SearchFilter::class, properties={"block": "exact", "subBlock": "exact"})
 * @ApiFilter(GroupFilter::class, arguments={"whitelist"={"design_explorer_view", "platform_full_view", "parent_view"}})
 *
 * @Gedmo\SoftDeleteable()
 *
 * @GraphicallyDeletable()
 *
 * @ORM\Entity()
 *
 * @ORM\Table(name="surfacic_unit_plot", schema="webapp")
 */
class SurfacicUnitPlot extends IdentifiedEntity implements BusinessObject
{
    use GraphicallyDeletableEntity;

    use HasGeometryEntity;

    use OpenSilexEntity;

    use SoftDeleteableEntity;

    /**
     * @ORM\Column(type="string")
     *
     * @Groups({"design_explorer_view", "platform_full_view", "webapp_data_view", "change_report", "fusion_result"})
     */
    private string $number = '';

    /**
     * @ORM\Column(type="integer")
     *
     * @Groups({"design_explorer_view", "platform_full_view", "webapp_data_view", "change_report"})
     */
    private int $x = 0;

    /**
     * @ORM\Column(type="integer")
     *
     * @Groups({"design_explorer_view", "platform_full_view", "webapp_data_view", "change_report"})
     */
    private int $y = 0;

    /**
     * @ORM\Column(type="boolean")
     *
     * @Groups({"design_explorer_view", "platform_full_view", "webapp_data_view", "declare_dead"})
     */
    private bool $dead = false;

    /**
     * @Gedmo\Timestampable(on="create")
     *
     * @ORM\Column(type="datetime")
     *
     * @Groups({"platform_full_view", "webapp_data_view"})
     */
    private \DateTime $appeared;

    /**
     * @Gedmo\Timestampable(on="change", field="dead", value=true)
     *
     * @ORM\Column(type="datetime", nullable=true)
     *
     * @Groups({"platform_full_view", "webapp_data_view"})
     */
    private ?\DateTime $disappeared = null;

    /**
     * @ORM\Column(type="string", nullable=true)
     *
     * @Groups({"design_explorer_view", "platform_full_view", "webapp_data_view"})
     */
    private ?string $identifier = null;

    /**
     * @ORM\Column(type="float", nullable=true)
     *
     * @Groups({"design_explorer_view", "platform_full_view"})
     */
    private ?float $latitude = null;

    /**
     * @ORM\Column(type="float", nullable=true)
     *
     * @Groups({"design_explorer_view", "platform_full_view"})
     */
    private ?float $longitude = null;

    /**
     * @ORM\Column(type="float", nullable=true)
     *
     * @Groups({"design_explorer_view", "platform_full_view"})
     */
    private ?float $height = null;

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\Treatment")
     *
     * @ORM\JoinColumn(nullable=false)
     *
     * @Groups({"design_explorer_view", "webapp_data_view", "platform_full_view", "change_report", "edit"})
     */
    private Treatment $treatment;

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\Block", inversedBy="surfacicUnitPlots")
     *
     * @Groups({"webapp_data_view", "parent_view", "change_report"})
     */
    private ?Block $block = null;

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\SubBlock", inversedBy="surfacicUnitPlots")
     *
     * @Groups({"webapp_data_view", "parent_view", "change_report"})
     */
    private ?SubBlock $subBlock = null;

    /**
     * @var Collection<int, Note>
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\Note", mappedBy="surfacicUnitPlotTarget", cascade={"persist", "remove"}, orphanRemoval=true)
     *
     * @Groups({"note_view"})
     *
     * @ApiSubresource()
     */
    private Collection $notes;

    /**
     * @ORM\Column(type="integer", nullable=true)
     *
     * @Groups({"platform_full_view"})
     */
    private ?int $color = null;

    /**
     * @ORM\Column(type="string", nullable=true)
     *
     * @Groups({"platform_full_view", "edit"})
     */
    private ?string $comment = null;

    public function __construct()
    {
        $this->notes = new ArrayCollection();
        $this->appeared = new \DateTime();
    }

    /**
     * @Groups({"platform_full_view"})
     *
     * @psalm-mutation-free
     */
    public function getId(): ?int
    {
        return parent::getId();
    }

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

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

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getX(): int
    {
        return $this->x;
    }

    /**
     * @return $this
     */
    public function setX(int $x): self
    {
        $this->x = $x;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getY(): int
    {
        return $this->y;
    }

    /**
     * @return $this
     */
    public function setY(int $y): self
    {
        $this->y = $y;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function isDead(): bool
    {
        return $this->dead;
    }

    /**
     * @return $this
     */
    public function setDead(bool $dead): self
    {
        $this->dead = $dead;

        return $this;
    }

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

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

        return $this;
    }

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

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

        return $this;
    }

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

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

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getLatitude(): ?float
    {
        return $this->latitude;
    }

    /**
     * @return $this
     */
    public function setLatitude(?float $latitude): self
    {
        $this->latitude = $latitude;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getLongitude(): ?float
    {
        return $this->longitude;
    }

    /**
     * @return $this
     */
    public function setLongitude(?float $longitude): self
    {
        $this->longitude = $longitude;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getHeight(): ?float
    {
        return $this->height;
    }

    /**
     * @return $this
     */
    public function setHeight(?float $height): self
    {
        $this->height = $height;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getTreatment(): Treatment
    {
        return $this->treatment;
    }

    /**
     * @return $this
     */
    public function setTreatment(Treatment $treatment): self
    {
        $this->treatment = $treatment;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getBlock(): ?Block
    {
        return $this->block;
    }

    /**
     * @return $this
     */
    public function setBlock(?Block $block): self
    {
        $this->block = $block;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getSubBlock(): ?SubBlock
    {
        return $this->subBlock;
    }

    /**
     * @return $this
     */
    public function setSubBlock(?SubBlock $subBlock): self
    {
        $this->subBlock = $subBlock;

        return $this;
    }

    /**
     * @return Collection<int,  Note>
     *
     * @psalm-mutation-free
     */
    public function getNotes(): Collection
    {
        return $this->notes;
    }

    /**
     * @param iterable<int,  Note> $notes
     *
     * @return $this
     */
    public function setNotes(iterable $notes): self
    {
        ArrayCollectionUtils::update($this->notes, $notes, function (Note $note) {
            $note->setTarget($this);
        });

        return $this;
    }

    /**
     * @return $this
     */
    public function addNote(Note $note): self
    {
        if (!$this->notes->contains($note)) {
            $this->notes->add($note);
            $note->setTarget($this);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function removeNote(Note $note): self
    {
        if ($this->notes->contains($note)) {
            $this->notes->removeElement($note);
            $note->setTarget(null);
        }

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getColor(): ?int
    {
        return $this->color;
    }

    /**
     * @return $this
     */
    public function setColor(?int $color): self
    {
        $this->color = $color;

        return $this;
    }

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

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

        return $this;
    }

    /**
     * @return $this
     */
    public function setDeletedAt(?\DateTime $deletedAt = null): self
    {
        $this->deletedAt = $deletedAt;
        if (null === $deletedAt) {
            foreach ($this->getNotes() as $child) {
                $child->setDeletedAt($deletedAt);
            }
        }

        return $this;
    }

    /**
     * @return Block|SubBlock
     *
     * @psalm-mutation-free
     */
    public function parent(): ?BusinessObject
    {
        return $this->block ?? $this->subBlock;
    }

    public function children(): array
    {
        return [];
    }
}
