<?php

/*
 * @author TRYDEA - 2024
 */

namespace Webapp\Core\Entity;

use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
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 Shared\Authentication\Entity\Site;
use Shared\Enumeration\Annotation\EnumType;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Webapp\Core\Enumeration\PathLevelEnum;
use Webapp\Core\Enumeration\VariableTypeEnum;
use Webapp\Core\Validator\UniqueAttributeInParent;

/**
 * @ApiResource(
 *     collectionOperations={
 *         "get"={},
 *         "post"={
 *              "denormalization_context"={"groups"={"simple_variable_post"}},
 *              "security_post_denormalize"="is_granted('ROLE_PLATFORM_MANAGER', object.getSite())",
 *          },
 *     },
 *     itemOperations={
 *          "get"={},
 *          "patch"={
 *              "security_post_denormalize"="is_granted('ROLE_PLATFORM_MANAGER', object.getSite())"
 *          },
 *          "delete"={
 *              "security"="is_granted('ROLE_PLATFORM_MANAGER', object.getSite()) and is_granted('SIMPLE_VARIABLE_DELETE', object)"
 *          }
 *     }
 * )
 *
 * @ApiFilter(SearchFilter::class, properties={"site": "exact", "generatorVariable": "exact", "project": "exact", "projectData.sessions": "exact", "projectData": "exact"})
 * @ApiFilter(GroupFilter::class, arguments={"whitelist"={"project_explorer_view", "connected_variables", "variable_synthesis", "simple_variable_get"}})
 *
 * @ORM\Entity()
 *
 * @ORM\Table(name="variable_simple", schema="webapp")
 *
 * @psalm-import-type PathLevelEnumId from PathLevelEnum
 * @psalm-import-type VariableTypeEnumId from VariableTypeEnum
 */
class SimpleVariable extends AbstractVariable
{
    /**
     * @ORM\Column(type="string", nullable=false)
     *
     * @Groups({"simple_variable_get", "project_explorer_view", "generator_variable_post", "semi_automatic_variable", "webapp_data_view", "simple_variable_post", "data_explorer_view", "connected_variables", "data_entry_synthesis", "project_synthesis", "variable_synthesis", "fusion_result", "webapp_data_path", "webapp_data_fusion"})
     *
     * @Assert\NotBlank
     *
     * @UniqueAttributeInParent(parentsAttributes={"site.simpleVariables", "project.generatorVariables", "project.simpleVariables", "variable_synthesis"})
     */
    protected string $name;

    /**
     * @Groups({"simple_variable_get", "simple_variable_post"})
     *
     * @ORM\ManyToOne(targetEntity="Shared\Authentication\Entity\Site", inversedBy="simpleVariables")
     */
    protected ?Site $site = null;

    /**
     * @Groups({"data_entry_synthesis"})
     *
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\GeneratorVariable", inversedBy="generatedSimpleVariables")
     */
    protected ?GeneratorVariable $generatorVariable = null;

    /**
     * @psalm-var VariableTypeEnumId|''
     *
     * @ORM\Column(type="string", nullable=false)
     *
     * @EnumType(class="Webapp\Core\Enumeration\VariableTypeEnum")
     *
     * @Groups({"webapp_data_view", "project_explorer_view", "generator_variable_post", "simple_variable_get", "simple_variable_post", "data_explorer_view", "data_entry_synthesis", "project_synthesis", "variable_synthesis", "webapp_data_path", "webapp_data_fusion"})
     */
    protected string $type = '';

    /**
     * @Groups({"simple_variable_get", "simple_variable_post"})
     *
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\Project", inversedBy="simpleVariables")
     */
    protected ?Project $project = null;

    /**
     * @var Collection<int, Test>
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\Test",mappedBy="variableSimple", cascade={"persist", "remove"}, orphanRemoval=true)
     *
     * @Groups({"project_explorer_view", "project_synthesis", "variable_synthesis"})
     */
    protected Collection $tests;

    /**
     * @Groups({"webapp_data_view", "project_explorer_view", "simple_variable_get", "simple_variable_post", "project_synthesis", "variable_synthesis"})
     *
     * @ORM\OneToOne(targetEntity="Webapp\Core\Entity\VariableScale", mappedBy="variable", cascade={"persist", "remove"}, orphanRemoval=true)
     */
    private ?VariableScale $scale = null;

    /**
     * @Groups({"project_explorer_view", "simple_variable_get", "simple_variable_post", "variable_synthesis", "data_explorer_view"})
     *
     * @ORM\OneToOne(targetEntity="Webapp\Core\Entity\ValueList", mappedBy="variable", cascade={"persist", "remove"}, orphanRemoval=true)
     */
    private ?ValueList $valueList = null;

    /**
     * @Groups({"variable_synthesis"})
     *
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\ProjectData", inversedBy="simpleVariables")
     */
    protected ?ProjectData $projectData = null;

    /**
     * @var Collection<int, VariableConnection>
     *
     * @ORM\OneToMany(targetEntity="Webapp\Core\Entity\VariableConnection", mappedBy="projectSimpleVariable", cascade={"persist", "remove"}, orphanRemoval=true)
     *
     * @Groups({"project_explorer_view", "connected_variables", "project_synthesis"})
     */
    protected Collection $connectedVariables;

    /**
     * @param PathLevelEnumId|''    $pathLevel
     * @param VariableTypeEnumId|'' $type
     */
    public function __construct(string $name = '', string $shortName = '', int $repetitions = 0, string $pathLevel = '', bool $mandatory = false, string $type = '')
    {
        parent::__construct();
        $this->name = $name; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->shortName = $shortName; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->repetitions = $repetitions; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->pathLevel = $pathLevel; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->mandatory = $mandatory; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->type = $type; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->tests = new ArrayCollection();
    }

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

    /**
     * @psalm-mutation-free
     */
    public function getSite(): ?Site
    {
        return $this->site;
    }

    /**
     * @return $this
     */
    public function setSite(?Site $site): self
    {
        $this->site = $site;
        $this->project = null;
        $this->generatorVariable = null;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getGeneratorVariable(): ?GeneratorVariable
    {
        return $this->generatorVariable;
    }

    /**
     * @return $this
     */
    public function setGeneratorVariable(?GeneratorVariable $generatorVariable): self
    {
        $this->generatorVariable = $generatorVariable;
        $this->site = null;

        return $this;
    }

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

    /**
     * @param VariableTypeEnumId|'' $type
     *
     * @return $this
     */
    public function setType(string $type): self
    {
        $this->type = $type;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getProject(): ?Project
    {
        return $this->project;
    }

    /**
     * @return $this
     */
    public function setProject(?Project $project): self
    {
        $this->project = $project;
        $this->site = null;
        $this->generatorVariable = null;

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getScale(): ?VariableScale
    {
        return $this->scale;
    }

    /**
     * @return $this
     */
    public function setScale(?VariableScale $scale): self
    {
        $this->scale = $scale;
        if (null !== $scale) {
            $scale->setVariable($this);
        }

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getValueList(): ?ValueList
    {
        return $this->valueList;
    }

    /**
     * @return $this
     */
    public function setValueList(?ValueList $valueList): self
    {
        $this->valueList = $valueList;
        if (null !== $valueList) {
            $valueList->setVariable($this);
        }

        return $this;
    }

    /**
     * @psalm-mutation-free
     */
    public function getProjectData(): ?ProjectData
    {
        return $this->projectData;
    }

    /**
     * @return $this
     */
    public function setProjectData(?ProjectData $projectData): self
    {
        $this->projectData = $projectData;

        return $this;
    }
}
