<?php

namespace Mobile\Device\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Shared\Utils\ArrayCollectionUtils;

/**
 * @ORM\Entity(repositoryClass="Mobile\Device\Repository\BlockRepository")
 *
 * @ORM\Table(name="block", schema="adonis")
 */
class Block extends BusinessObject
{
    /**
     * @ORM\ManyToOne(targetEntity="Mobile\Device\Entity\Device", inversedBy="blocks")
     *
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     */
    private Device $device;

    /**
     * @var Collection<int, SubBlock>
     *
     * @ORM\OneToMany(targetEntity="Mobile\Device\Entity\SubBlock", mappedBy="block", cascade={"persist", "remove", "detach"})
     */
    private Collection $subBlocks;

    /**
     * @var Collection<int, UnitParcel>
     *
     * @ORM\OneToMany(targetEntity="Mobile\Device\Entity\UnitParcel", mappedBy="block", cascade={"persist", "remove", "detach"})
     */
    private Collection $unitParcels;

    /**
     * @var Collection<int, OutExperimentationZone>
     *
     * @ORM\OneToMany(targetEntity="Mobile\Device\Entity\OutExperimentationZone", mappedBy="block", cascade={"persist", "remove", "detach"})
     */
    private Collection $outExperimentationZones;

    public function __construct(string $name = '')
    {
        parent::__construct($name);
        $this->subBlocks = new ArrayCollection();
        $this->unitParcels = new ArrayCollection();
        $this->outExperimentationZones = new ArrayCollection();
    }

    /**
     * @psalm-mutation-free
     */
    public function getDevice(): Device
    {
        return $this->device;
    }

    /**
     * @return $this
     */
    public function setDevice(Device $device): Block
    {
        $this->device = $device;

        return $this;
    }

    /**
     * @return Collection<int,  SubBlock>
     *
     * @psalm-mutation-free
     */
    public function getSubBlocks(): Collection
    {
        return $this->subBlocks;
    }

    /**
     * @param iterable<array-key, SubBlock> $subBlocks
     *
     * @return $this
     */
    public function setSubBlocks(iterable $subBlocks): self
    {
        ArrayCollectionUtils::update($this->subBlocks, $subBlocks, fn (SubBlock $subBlock) => $subBlock->setBlock($this));

        return $this;
    }

    /**
     * @return $this
     */
    public function addSubBlock(SubBlock $subBlock): self
    {
        if (!$this->subBlocks->contains($subBlock)) {
            $this->subBlocks->add($subBlock);
            $subBlock->setBlock($this);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function removeSubBlock(SubBlock $subBlock): self
    {
        if ($this->subBlocks->contains($subBlock)) {
            $this->subBlocks->removeElement($subBlock);
        }

        return $this;
    }

    /**
     * @return Collection<int,  UnitParcel>
     *
     * @psalm-mutation-free
     */
    public function getUnitParcels(): Collection
    {
        return $this->unitParcels;
    }

    /**
     * @param iterable<int, UnitParcel> $unitParcels
     *
     * @return $this
     */
    public function setUnitParcels(iterable $unitParcels): self
    {
        ArrayCollectionUtils::update($this->unitParcels, $unitParcels, function (UnitParcel $unitParcel): void {
            $unitParcel->setBlock($this);
            $unitParcel->setSubBlock(null);
        });

        return $this;
    }

    /**
     * @return $this
     */
    public function addUnitParcel(UnitParcel $unitParcel): self
    {
        if (!$this->unitParcels->contains($unitParcel)) {
            $this->unitParcels->add($unitParcel);
            $unitParcel->setBlock($this);
            $unitParcel->setSubBlock(null);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function removeUnitParcel(UnitParcel $unitParcel): self
    {
        if ($this->unitParcels->contains($unitParcel)) {
            $this->unitParcels->removeElement($unitParcel);
        }

        return $this;
    }

    /**
     * @return Collection<int,  OutExperimentationZone>
     *
     * @psalm-mutation-free
     */
    public function getOutExperimentationZones(): Collection
    {
        return $this->outExperimentationZones;
    }

    /**
     * @param iterable<int,  OutExperimentationZone> $outExperimentationZones
     *
     * @return $this
     */
    public function setOutExperimentationZones(iterable $outExperimentationZones): self
    {
        ArrayCollectionUtils::update($this->outExperimentationZones, $outExperimentationZones, function (OutExperimentationZone $outExperimentationZone): void {
            $outExperimentationZone->setBlock($this);
        });

        return $this;
    }

    /**
     * @return $this
     */
    public function addOutExperimentationZone(OutExperimentationZone $outExperimentationZone): self
    {
        if (!$this->outExperimentationZones->contains($outExperimentationZone)) {
            $this->outExperimentationZones->add($outExperimentationZone);
            $outExperimentationZone->setBlock($this);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function removeOutExperimentationZone(OutExperimentationZone $outExperimentationZone): self
    {
        if ($this->outExperimentationZones->contains($outExperimentationZone)) {
            $this->outExperimentationZones->removeElement($outExperimentationZone);
            $outExperimentationZone->setBlock(null);
        }

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function parent(): ?BusinessObject
    {
        return $this->getDevice();
    }
}
