<?php

namespace Webapp\Core\Entity;

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

/**
 * @ORM\Entity
 *
 * @ORM\Table(name="path_filter_node", schema="webapp")
 */
class PathFilterNode extends IdentifiedEntity
{
    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\PathBase", inversedBy="pathFilterNodes"  )
     */
    private ?PathBase $pathBase = null;

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\PathFilterNode", inversedBy="branches")
     */
    private ?PathFilterNode $parentFilter = null;

    /**
     * @ORM\Column(type="integer")
     */
    private int $type; // TODO FILTERKEYENUM

    /**
     * @ORM\Column(type="string")
     */
    private string $text;

    /**
     * @var Collection<int, PathFilterNode>
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\PathFilterNode", mappedBy="parentFilter", cascade={"remove", "persist"}, orphanRemoval=true )
     */
    private Collection $branches;

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

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

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\GeneratorVariable", cascade={"persist"})
     *
     * @ORM\JoinColumn(nullable=true)
     */
    private ?GeneratorVariable $generatorVariable = null;

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\SimpleVariable", cascade={"persist"})
     *
     * @ORM\JoinColumn(nullable=true)
     */
    private ?SimpleVariable $simpleVariable = null;

    /**
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\SemiAutomaticVariable", cascade={"persist"})
     *
     * @ORM\JoinColumn(nullable=true)
     */
    private ?SemiAutomaticVariable $semiAutomaticVariable = null;

    public function __construct(int $type, string $text)
    {
        $this->type = $type; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->text = $text; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->branches = new ArrayCollection();
    }

    /**
     * @psalm-mutation-free
     */
    public function getPathBase(): ?PathBase
    {
        return $this->pathBase;
    }

    /**
     * @return $this
     */
    public function setPathBase(?PathBase $pathBase): self
    {
        $this->pathBase = $pathBase;

        return $this;
    }

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

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

        return $this;
    }

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

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

        return $this;
    }

    /**
     * @return Collection<int,  PathFilterNode>
     */
    public function getBranches(): Collection
    {
        return $this->branches;
    }

    /**
     * @param iterable<int,  PathFilterNode> $branches
     *
     * @return $this
     */
    public function setBranches(iterable $branches): self
    {
        ArrayCollectionUtils::update($this->branches, $branches, function (PathFilterNode $pathFilterNode) {
            $pathFilterNode->setParentFilter($this);
        });

        return $this;
    }

    /**
     * @return $this
     */
    public function addBranche(PathFilterNode $branche): self
    {
        if (!$this->branches->contains($branche)) {
            $this->branches->add($branche);
            $branche->setParentFilter($this);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function removeBranche(PathFilterNode $branche): self
    {
        if ($this->branches->contains($branche)) {
            $this->branches->removeElement($branche);
            $branche->setParentFilter(null);
        }

        return $this;
    }

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

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

        return $this;
    }

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

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

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getParentFilter(): ?PathFilterNode
    {
        return $this->parentFilter;
    }

    /**
     * @return $this
     */
    public function setParentFilter(?PathFilterNode $parentFilter): self
    {
        $this->parentFilter = $parentFilter;

        return $this;
    }

    /**
     * @return SimpleVariable|SemiAutomaticVariable|GeneratorVariable|null
     */
    public function getVariable(): ?AbstractVariable
    {
        return $this->simpleVariable ?? $this->semiAutomaticVariable ?? $this->generatorVariable;
    }

    /**
     * @param SimpleVariable|SemiAutomaticVariable|GeneratorVariable|null $variable
     *
     * @return $this
     */
    public function setVariable(?AbstractVariable $variable): self
    {
        $this->simpleVariable = null;
        $this->semiAutomaticVariable = null;
        $this->generatorVariable = null;
        if ($variable instanceof SimpleVariable) {
            $this->simpleVariable = $variable;
        } elseif ($variable instanceof SemiAutomaticVariable) {
            $this->semiAutomaticVariable = $variable;
        } elseif ($variable instanceof GeneratorVariable) {
            $this->generatorVariable = $variable;
        }

        return $this;
    }
}
