<?php


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\VariableTypeEnum;
use Webapp\Core\Validator\UniqueAttributeInParent;

/**
 * Class SimpleVariable
 * @package Webapp\Core\Entity
 * @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 VariableTypeEnumId from VariableTypeEnum
 */
class SimpleVariable extends AbstractVariable
{
    /**
     * @var string
     *
     * @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;

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

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

    /**
     * @var string
     * @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;

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

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

    /**
     * @var VariableScale | null
     * @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;

    /**
     * @var ValueList|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;

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

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

    /**
     * @param VariableTypeEnumId|'' $type
     */
    public function __construct($name, $shortName, $repetitions, $pathLevel, $mandatory, $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->site = null;
        $this->generatorVariable = null;
        $this->project = null;
        $this->valueList = null;
        $this->tests = new ArrayCollection();
        $this->projectData = null;
        $this->scale = null;
    }

    /**
     * @return mixed
     * @Groups("project_explorer_view")
     */
    public function getId()
    {
        return parent::getId();
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @param ProjectData|null $projectData
     * @return SimpleVariable
     */
    public function setProjectData(?ProjectData $projectData): SimpleVariable
    {
        $this->projectData = $projectData;
        return $this;
    }

}
