<?php

namespace App\Entity;

use App\Repository\GameRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\DBAL\Types\Types;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Uid\Uuid;
use App\Enum\AgeRange;

#[ORM\Entity(repositoryClass: GameRepository::class)]
class Game
{
    #[ORM\Id]
    #[ORM\Column(type: UuidType::NAME, unique: true)]
    #[ORM\GeneratedValue(strategy: 'CUSTOM')]
    #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
    private ?Uuid $id = null;

    #[ORM\Column(length: 255)]
    private ?string $name = null;

    #[ORM\Column(length: 255)]
    private ?string $slug = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $description = null;

    #[ORM\Column(nullable: true)]
    private ?bool $isPhysical = null;

    #[ORM\Column(nullable: true)]
    private ?bool $isNumerical = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $urlNumericalVersion = null;

    #[ORM\Column(nullable: true)]
    private ?bool $isInAssoLibrary = null;

    #[ORM\Column(nullable: true)]
    private ?bool $isBorrowed = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $picture = null;
    
    #[ORM\Column(enumType: AgeRange::class, nullable: true)]
    private ?AgeRange $ageRecommendation = null;

    /**
     * @var Collection<int, Genre>
     */
    #[ORM\ManyToMany(targetEntity: Genre::class, inversedBy: 'games')]
    private Collection $genre;

    #[ORM\ManyToOne(inversedBy: 'games')]
    private ?User $addBy = null;

    #[ORM\Column(nullable: true)]
    private ?\DateTime $addDatetime = null;

    #[ORM\Column(nullable: true)]
    private ?bool $isValidByAdmin = null;

    #[ORM\Column(nullable: true)]
    private ?\DateTime $validDatetime = null;

    /**
     * @var Collection<int, Gamemaster>
     */
    #[ORM\ManyToMany(targetEntity: Gamemaster::class, mappedBy: 'gamesCanMaster')]
    private Collection $gamemasters;

    /**
     * @var Collection<int, Event>
     */
    #[ORM\ManyToMany(targetEntity: Event::class, mappedBy: 'gameAssigned')]
    private Collection $eventsAssignedTo;

    /**
     * @var Collection<int, Party>
     */
    #[ORM\OneToMany(targetEntity: Party::class, mappedBy: 'game')]
    private Collection $parties;

    /**
     * @var Collection<int, Gamemaster>
     */
    #[ORM\ManyToMany(targetEntity: Gamemaster::class, mappedBy: 'authorOfGames')]
    private Collection $authors;

    public function __construct()
    {
        $this->genre = new ArrayCollection();
        $this->id = Uuid::v7();
        $this->gamemasters = new ArrayCollection();
        $this->eventsAssignedTo = new ArrayCollection();
        $this->parties = new ArrayCollection();
        $this->authors = new ArrayCollection();
    }

    public function getId(): ?Uuid
    {
        return $this->id;
    }

    public function setId(Uuid $id): static
    {
        $this->id = $id;

        return $this;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): static
    {
        $this->name = $name;

        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function setSlug(string $slug): static
    {
        $this->slug = $slug;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): static
    {
        $this->description = $description;

        return $this;
    }

    public function isPhysical(): ?bool
    {
        return $this->isPhysical;
    }

    public function setIsPhysical(?bool $isPhysical): static
    {
        $this->isPhysical = $isPhysical;

        return $this;
    }

    public function isNumerical(): ?bool
    {
        return $this->isNumerical;
    }

    public function setIsNumerical(bool $isNumerical): static
    {
        $this->isNumerical = $isNumerical;

        return $this;
    }

    public function getUrlNumericalVersion(): ?string
    {
        return $this->urlNumericalVersion;
    }

    public function setUrlNumericalVersion(?string $urlNumericalVersion): static
    {
        $this->urlNumericalVersion = $urlNumericalVersion;

        return $this;
    }

    public function isInAssoLibrary(): ?bool
    {
        return $this->isInAssoLibrary;
    }

    public function setIsInAssoLibrary(?bool $isInAssoLibrary): static
    {
        $this->isInAssoLibrary = $isInAssoLibrary;

        return $this;
    }

    public function isBorrowed(): ?bool
    {
        return $this->isBorrowed;
    }

    public function setIsBorrowed(?bool $isBorrowed): static
    {
        $this->isBorrowed = $isBorrowed;

        return $this;
    }

    public function getPicture(): ?string
    {
        return $this->picture;
    }

    public function setPicture(?string $picture): static
    {
        $this->picture = $picture;

        return $this;
    }

    /**
     * @return Collection<int, Genre>
     */
    public function getGenre(): Collection
    {
        return $this->genre;
    }

    public function addGenre(Genre $genre): static
    {
        if (!$this->genre->contains($genre)) {
            $this->genre->add($genre);
        }

        return $this;
    }

    public function removeGenre(Genre $genre): static
    {
        $this->genre->removeElement($genre);

        return $this;
    }

    public function getAddBy(): ?User
    {
        return $this->addBy;
    }

    public function setAddBy(?User $addBy): static
    {
        $this->addBy = $addBy;

        return $this;
    }

    public function getAddDatetime(): ?\DateTime
    {
        return $this->addDatetime;
    }

    public function setAddDatetime(?\DateTime $addDatetime): static
    {
        $this->addDatetime = $addDatetime;

        return $this;
    }

    public function isValidByAdmin(): ?bool
    {
        return $this->isValidByAdmin;
    }

    public function setIsValidByAdmin(bool $isValidByAdmin): static
    {
        $this->isValidByAdmin = $isValidByAdmin;

        return $this;
    }

    public function getValidDatetime(): ?\DateTime
    {
        return $this->validDatetime;
    }

    public function setValidDatetime(?\DateTime $validDatetime): static
    {
        $this->validDatetime = $validDatetime;

        return $this;
    }

    /**
     * @return Collection<int, Gamemaster>
     */
    public function getGamemasters(): Collection
    {
        return $this->gamemasters;
    }

    public function addGamemaster(Gamemaster $gamemaster): static
    {
        if (!$this->gamemasters->contains($gamemaster)) {
            $this->gamemasters->add($gamemaster);
            $gamemaster->addGamesCanMaster($this);
        }

        return $this;
    }

    public function removeGamemaster(Gamemaster $gamemaster): static
    {
        if ($this->gamemasters->removeElement($gamemaster)) {
            $gamemaster->removeGamesCanMaster($this);
        }

        return $this;
    }

    /**
     * @return Collection<int, Event>
     */
    public function getEventsAssignedTo(): Collection
    {
        return $this->eventsAssignedTo;
    }

    public function addEventsAssignedTo(Event $eventsAssignedTo): static
    {
        if (!$this->eventsAssignedTo->contains($eventsAssignedTo)) {
            $this->eventsAssignedTo->add($eventsAssignedTo);
            $eventsAssignedTo->addGameAssigned($this);
        }

        return $this;
    }

    public function removeEventsAssignedTo(Event $eventsAssignedTo): static
    {
        if ($this->eventsAssignedTo->removeElement($eventsAssignedTo)) {
            $eventsAssignedTo->removeGameAssigned($this);
        }

        return $this;
    }

    /**
     * @return Collection<int, Party>
     */
    public function getParties(): Collection
    {
        return $this->parties;
    }

    public function addParty(Party $party): static
    {
        if (!$this->parties->contains($party)) {
            $this->parties->add($party);
            $party->setGame($this);
        }

        return $this;
    }

    public function removeParty(Party $party): static
    {
        if ($this->parties->removeElement($party)) {
            // set the owning side to null (unless already changed)
            if ($party->getGame() === $this) {
                $party->setGame(null);
            }
        }

        return $this;
    }
    
    // Getter et setters pour la recommandation d'âge du jeu
    public function getAgeRecommendation(): ?AgeRange
    {
        return $this->ageRecommendation;
    }
    
    public function setAgeRecommendation(?AgeRange $ageRange): self
    {
        $this->ageRecommendation = $ageRange;
        return $this;
    }
    public function getAgeRecommendationLabel(): ?string
    {
        return $this->ageRecommendation?->label();
    }
    public function getAgeRecommendationPreRequists(): ?string
    {
        return $this->ageRecommendation?->prerequist();
    }
    public function getAgeRecommendationShortLabel(): ?string
    {
        return $this->ageRecommendation->shortLabel();
    }

    /**
     * @return Collection<int, Gamemaster>
     */
    public function getAuthors(): Collection
    {
        return $this->authors;
    }

    public function addAuthor(Gamemaster $author): static
    {
        if (!$this->authors->contains($author)) {
            $this->authors->add($author);
            $author->addAuthorOfGame($this);
        }

        return $this;
    }

    public function removeAuthor(Gamemaster $author): static
    {
        if ($this->authors->removeElement($author)) {
            $author->removeAuthorOfGame($this);
        }

        return $this;
    }
    
    

}
