<?php


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 DateTime;
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 Symfony\Component\Serializer\Annotation\Groups;
use Webapp\Core\Annotation\GraphicallyDeletable;
use Webapp\Core\Traits\GraphicallyDeletableEntity;

/**
 * Class SubBlock
 * @package Webapp\Core\Entity
 *
 * @ApiResource(
 *     collectionOperations={
 *          "get"={}
 *     },
 *     itemOperations={
 *          "get"={},
 *          "patch"={
 *              "security"="is_granted('ROLE_PLATFORM_MANAGER')",
 *              "denormalization_context"={"groups"={"edit"}}
 *          },
 *     }
 * )
 *
 * @ApiFilter(SearchFilter::class, properties={"block": "exact"})
 * @ApiFilter(GroupFilter::class, arguments={"whitelist"={"design_explorer_view", "platform_full_view", "parent_view"}})
 *
 * @Gedmo\SoftDeleteable()
 * @GraphicallyDeletable()
 *
 * @ORM\Entity()
 * @ORM\Table(name="sub_block", schema="webapp")
 */
class SubBlock extends IdentifiedEntity implements BusinessObject
{
    use GraphicallyDeletableEntity;

    use SoftDeleteableEntity;

    use OpenSilexEntity;

    use HasGeometryEntity;

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

    /**
     * @var Collection | array<UnitPlot> | null
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\UnitPlot", cascade={"persist", "remove"}, mappedBy="subBlock")
     * @Groups({"platform_full_view"})
     */
    private $unitPlots;

    /**
     * @var Collection | array<SurfacicUnitPlot> | null
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\SurfacicUnitPlot", cascade={"persist", "remove"}, mappedBy="subBlock")
     * @Groups({"platform_full_view"})
     */
    private $surfacicUnitPlots;

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

    /**
     * @var Collection | array<OutExperimentationZone>
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\OutExperimentationZone", mappedBy="subBlock", cascade={"persist", "remove"})
     * @Groups({"platform_full_view"})
     */
    private $outExperimentationZones;

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

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

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

    public function __construct()
    {
        $this->unitPlots = new ArrayCollection();
        $this->surfacicUnitPlots = new ArrayCollection();
        $this->outExperimentationZones = new ArrayCollection();
        $this->notes = new ArrayCollection();
        $this->color = null;
        $this->comment = null;
        $this->openSilexInstance = null;
        $this->openSilexUri = null;
    }

    /**
     * @Groups({"platform_full_view"})
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

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

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

    /**
     * @return Collection|UnitPlot[]|null
     */
    public function getUnitPlots()
    {
        return $this->unitPlots;
    }

    /**
     * @param UnitPlot $unitPlot
     * @return SubBlock
     */
    public function addUnitPlots($unitPlot)
    {
        if(!$this->unitPlots->contains($unitPlot)){
            $this->unitPlots->add($unitPlot);
            $unitPlot->setSubBlock($this);
        }
        return $this;
    }

    /**
     * @param Collection|UnitPlot[]|null $unitPlots
     * @return SubBlock
     */
    public function setUnitPlots($unitPlots)
    {
        $this->unitPlots = $unitPlots;
        if($unitPlots !== null) {
            foreach ($unitPlots as $unitPlot) {
                $unitPlot->setSubBlock($this);
            }
        }
        return $this;
    }

    /**
     * @return Collection|SurfacicUnitPlot[]|null
     */
    public function getSurfacicUnitPlots()
    {
        return $this->surfacicUnitPlots;
    }

    /**
     * @param SurfacicUnitPlot $unitPlot
     * @return SubBlock
     */
    public function addSurfacicUnitPlots($unitPlot)
    {
        if(!$this->surfacicUnitPlots->contains($unitPlot)){
            $this->surfacicUnitPlots->add($unitPlot);
            $unitPlot->setSubBlock($this);
        }
        return $this;
    }

    /**
     * @param Collection|SurfacicUnitPlot[]|null $surfacicUnitPlots
     * @return SubBlock
     */
    public function setSurfacicUnitPlots($surfacicUnitPlots)
    {
        $this->surfacicUnitPlots = $surfacicUnitPlots;
        if($surfacicUnitPlots !== null) {
            foreach ($surfacicUnitPlots as $surfacicUnitPlot) {
                $surfacicUnitPlot->setSubBlock($this);
            }
        }
        return $this;
    }

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

    /**
     * @param Block $block
     * @return SubBlock
     */
    public function setBlock(Block $block): SubBlock
    {
        $this->block = $block;
        return $this;
    }

    /**
     * @return Collection|Note[]
     */
    public function getNotes()
    {
        return $this->notes;
    }

    /**
     * @param Collection|Note[] $notes
     * @return SubBlock
     */
    public function setNotes($notes)
    {
        $this->notes = $notes;
        return $this;
    }

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

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

    /**
     * @return Collection|OutExperimentationZone[]
     */
    public function getOutExperimentationZones()
    {
        return $this->outExperimentationZones;
    }

    /**
     * @param OutExperimentationZone $outExperimentationZone
     * @return SubBlock
     */
    public function addOutExperimentationZone($outExperimentationZone)
    {
        if (!$this->outExperimentationZones->contains($outExperimentationZone)) {
            $this->outExperimentationZones->add($outExperimentationZone);
            $outExperimentationZone->setSubBlock($this);
        }
        return $this;
    }

    /**
     * @param OutExperimentationZone $outExperimentationZone
     * @return SubBlock
     */
    public function removeOutExperimentationZone($outExperimentationZone)
    {
        if ($this->outExperimentationZones->contains($outExperimentationZone)) {
            $this->outExperimentationZones->removeElement($outExperimentationZone);
            $outExperimentationZone->setSubBlock(null);
        }
        return $this;
    }

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

    /**
     * @param int|null $color
     * @return SubBlock
     */
    public function setColor(?int $color): SubBlock
    {
        $this->color = $color;
        return $this;
    }

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

    /**
     * @param string|null $comment
     * @return SubBlock
     */
    public function setComment(?string $comment): SubBlock
    {
        $this->comment = $comment;
        return $this;
    }

    public function setDeletedAt(DateTime $deletedAt = null)
    {
        $this->deletedAt = $deletedAt;
        if($deletedAt === null){
            foreach ($this->children() as $child){
                $child->setDeletedAt($deletedAt);
            }
            foreach ($this->getNotes() as $child){
                $child->setDeletedAt($deletedAt);
            }
        }

        return $this;
    }

    function parent(): ?BusinessObject
    {
        return $this->block;
    }

    function children(): array
    {
        return [
            ...$this->unitPlots->toArray(),
            ...$this->surfacicUnitPlots->toArray(),
            ...$this->outExperimentationZones->toArray()];
    }

}
