<?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 Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Webapp\Core\Enumeration\VariableTypeEnum;
use Webapp\Core\Validator\UniqueAttributeInParent;

/**
 * Class SemiAutomaticVariable
 * @package Webapp\Core\Entity
 * @ApiResource(
 *     collectionOperations={
 *          "get"={"security"="is_granted('ROLE_PLATFORM_MANAGER')"},
 *          "post"={
 *              "security_post_denormalize"="object.getDevice().getProject() !== null"
 *          }
 *     },
 *     itemOperations={
 *          "get"={"security"="is_granted('ROLE_PLATFORM_MANAGER', object.getDevice().getSite())"},
 *          "patch"={
 *              "security_post_denormalize"="is_granted('ROLE_PLATFORM_MANAGER', object.getDevice().getSite())"
 *          }
 *     }
 * )
 * @ApiFilter(SearchFilter::class, properties={"site": "exact", "generatorVariable": "exact", "projectData.sessions": "exact", "projectData": "exact"})
 * @ApiFilter(GroupFilter::class, arguments={"whitelist"={"project_explorer_view", "connected_variables"}})
 *
 * @ORM\Entity()
 * @ORM\Table(name="variable_semi_automatic", schema="webapp")
 *
 * @psalm-import-type VariableTypeEnumId from VariableTypeEnum
 */
class SemiAutomaticVariable extends AbstractVariable
{

    /**
     * @var string
     *
     * @ORM\Column(type="string", nullable=false)
     * @Groups({"project_explorer_view", "semi_automatic_variable", "webapp_data_view", "data_explorer_view", "data_entry_synthesis", "project_synthesis", "variable_synthesis", "fusion_result", "webapp_data_path", "webapp_data_fusion"})
     * @Assert\NotBlank
     * @UniqueAttributeInParent(parentsAttributes={"device.managedVariables"})
     */
    protected string $name;

    /**
     * @var int
     * @ORM\Column(type="integer", name="frame_start")
     * @Groups({"semi_automatic_variable"})
     */
    private int $start;

    /**
     * @var int
     * @ORM\Column(type="integer", name="frame_end")
     * @Groups({"semi_automatic_variable"})
     */
    private int $end;

    /**
     * @var string
     * @psalm-var VariableTypeEnumId|''
     *
     * @ORM\Column(type="string", nullable=false)
     * @Groups({"semi_automatic_variable", "webapp_data_view", "data_entry_synthesis", "project_synthesis", "variable_synthesis", "webapp_data_path", "webapp_data_fusion"})
     */
    protected string $type;

    /**
     * @var Device|null
     * @ORM\ManyToOne(targetEntity="Webapp\Core\Entity\Device", inversedBy="managedVariables", cascade={"persist"})
     * @Groups({"data_explorer_view"})
     */
    private ?Device $device;

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

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

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

    public function __construct($name, $shortName, $repetitions, $pathLevel, $mandatory, $type, $start, $end)
    {
        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->start = $start; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->end = $end; // TODO delete when https://github.com/api-platform/core/issues/3974 is solved
        $this->tests = new ArrayCollection();
        $this->projectData = null;
    }

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

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

    /**
     * @return int
     */
    public function getStart(): int
    {
        return $this->start;
    }

    /**
     * @param int $start
     * @return SemiAutomaticVariable
     */
    public function setStart(int $start): SemiAutomaticVariable
    {
        $this->start = $start;
        return $this;
    }

    /**
     * @return int
     */
    public function getEnd(): int
    {
        return $this->end;
    }

    /**
     * @param int $end
     * @return SemiAutomaticVariable
     */
    public function setEnd(int $end): SemiAutomaticVariable
    {
        $this->end = $end;
        return $this;
    }

    /**
     * @return Device|null
     */
    public function getDevice(): ?Device
    {
        return $this->device;
    }

    /**
     * @param Device|null $device
     * @return SemiAutomaticVariable
     */
    public function setDevice(?Device $device): SemiAutomaticVariable
    {
        $this->device = $device;
        return $this;
    }

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

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

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

}
