<?php
declare (strict_types=1);

namespace App\Entity\Place;

use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\ApiResource;
use App\Entity\Booking\Course;
use App\Entity\Booking\EducationalProject;
use App\Entity\Booking\Event;
use App\Entity\Booking\Examen;
use App\Entity\Core\AddressPostal;
use App\Entity\Core\ContactPoint;
use App\Entity\Core\Tagg;
use App\Entity\Organization\Organization;
use App\Entity\Product\Equipment;

//use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @todo : A la suite de la migration, il faut supprimer le nom de la table pour avoir une table Place, et supprimer l'attribut discr.
 *
 * Classe ... qui ...
 */
#[ApiResource(
    operations: [
        new Get(
            security: 'is_granted(\'ROLE_ADMIN\') and object.getOrganization().getId() == user.getOrganization().getId()'
        )
    ]
)]
//#[Auditable]
#[ORM\Entity]
#[ORM\Table(name: 'Place')]
#[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
#[ORM\DiscriminatorMap([
    'place' => 'Place',
    'place_system' => 'PlaceSystem'
])]
class Place
{
    #[ORM\Id]
    #[ORM\Column]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'places')]
    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
    private AddressPostal $addressPostal;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Event::class)]
    private Collection $events;

    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'places', cascade: ['persist'])]
    #[ORM\JoinTable(name: 'tag_place')]
    #[ORM\JoinColumn(name: 'place_id', referencedColumnName: 'id')]
    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
    private Collection $tags;

    #[ORM\ManyToOne(inversedBy: 'places')]
    private Organization $organization;

    #[ORM\ManyToMany(targetEntity: ContactPoint::class, inversedBy: 'place', cascade: ['persist'])]
    private Collection $contactpoint;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Room::class, cascade: ['persist'], orphanRemoval: true)]
    #[ORM\JoinColumn(nullable: false)]
    private Collection $rooms;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: PlaceControl::class, cascade: ['persist'], orphanRemoval: true)]
    #[ORM\JoinColumn(nullable: false)]
    private Collection $controls;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: PlaceRepair::class, cascade: ['persist'], orphanRemoval: true)]
    #[ORM\JoinColumn(nullable: false)]
    private Collection $repairs;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Course::class)]
    private Collection $courses;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: EducationalProject::class)]
    private Collection $educationalProjects;

    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Examen::class)]
    private Collection $examens;

    #[ORM\OneToMany(mappedBy: 'placeStorage', targetEntity: Equipment::class)]
    private Collection $equipmentStorages;

    #[ORM\OneToMany(mappedBy: 'placeWhereIsUsed', targetEntity: Equipment::class)]
    private Collection $equipmentUseds;

    public function __construct()
    {
        $this->events = new ArrayCollection();
        $this->tags = new ArrayCollection();
        $this->contactpoint = new ArrayCollection();
        $this->rooms = new ArrayCollection();
        $this->controls = new ArrayCollection();
        $this->repairs = new ArrayCollection();
        $this->courses = new ArrayCollection();
        $this->educationalProjects = new ArrayCollection();
        $this->examens = new ArrayCollection();
        $this->equipmentStorages = new ArrayCollection();
        $this->equipmentUseds = new ArrayCollection();
    }

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

    public function getAddressPostal(): ?AddressPostal
    {
        return $this->addressPostal;
    }

    public function setAddressPostal(?AddressPostal $addressPostal): self
    {
        $this->addressPostal = $addressPostal;
        return $this;
    }

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

    public function addEvent(Event $event): self
    {
        if (!$this->events->contains($event)) {
            $this->events[] = $event;
            $event->setPlace($this);
        }
        return $this;
    }

    public function removeEvent(Event $event): self
    {
        if ($this->events->removeElement($event)) {
            // set the owning side to null (unless already changed)
            if ($event->getPlace() === $this) {
                $event->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, Tagg>
     */
    public function getTags(): Collection
    {
        return $this->tags;
    }

    public function addTag(Tagg $tag): self
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
        }
        return $this;
    }

    public function removeTag(Tagg $tag): self
    {
        $this->tags->removeElement($tag);
        return $this;
    }

    public function getOrganization(): ?Organization
    {
        return $this->organization;
    }

    public function setOrganization(?Organization $organization): self
    {
        $this->organization = $organization;
        return $this;
    }

    /**
     * @return Collection<int, ContactPoint>
     */
    public function getContactpoint(): Collection
    {
        return $this->contactpoint;
    }

    public function addContactpoint(ContactPoint $contactpoint): self
    {
        if (!$this->contactpoint->contains($contactpoint)) {
            $this->contactpoint[] = $contactpoint;
        }
        return $this;
    }

    public function removeContactpoint(ContactPoint $contactpoint): self
    {
        $this->contactpoint->removeElement($contactpoint);
        return $this;
    }

    /**
     * @return Collection<int, Room>
     */
    public function getRooms(): Collection
    {
        return $this->rooms;
    }

    public function addRoom(Room $room): self
    {
        if (!$this->rooms->contains($room)) {
            $this->rooms[] = $room;
            $room->setPlace($this);
        }
        return $this;
    }

    public function removeRoom(Room $room): self
    {
        if ($this->rooms->removeElement($room)) {
            // set the owning side to null (unless already changed)
            if ($room->getPlace() === $this) {
                $room->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, PlaceControl>
     */
    public function getControls(): Collection
    {
        return $this->controls;
    }

    public function addControl(PlaceControl $control): self
    {
        if (!$this->controls->contains($control)) {
            $this->controls[] = $control;
            $control->setPlace($this);
        }
        return $this;
    }

    public function removeControl(PlaceControl $control): self
    {
        if ($this->controls->removeElement($control)) {
            // set the owning side to null (unless already changed)
            if ($control->getPlace() === $this) {
                $control->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, PlaceRepair>
     */
    public function getRepairs(): Collection
    {
        return $this->repairs;
    }

    public function addRepair(PlaceRepair $repair): self
    {
        if (!$this->repairs->contains($repair)) {
            $this->repairs[] = $repair;
            $repair->setPlace($this);
        }
        return $this;
    }

    public function removeRepair(PlaceRepair $repair): self
    {
        if ($this->repairs->removeElement($repair)) {
            // set the owning side to null (unless already changed)
            if ($repair->getPlace() === $this) {
                $repair->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, Course>
     */
    public function getCourses(): Collection
    {
        return $this->courses;
    }

    public function addCourse(Course $course): self
    {
        if (!$this->courses->contains($course)) {
            $this->courses[] = $course;
            $course->setPlace($this);
        }
        return $this;
    }

    public function removeCourse(Course $course): self
    {
        if ($this->courses->removeElement($course)) {
            // set the owning side to null (unless already changed)
            if ($course->getPlace() === $this) {
                $course->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, EducationalProject>
     */
    public function getEducationalProjects(): Collection
    {
        return $this->educationalProjects;
    }

    public function addEducationalProject(EducationalProject $educationalProject): self
    {
        if (!$this->educationalProjects->contains($educationalProject)) {
            $this->educationalProjects[] = $educationalProject;
            $educationalProject->setPlace($this);
        }
        return $this;
    }

    public function removeEducationalProject(EducationalProject $educationalProject): self
    {
        if ($this->educationalProjects->removeElement($educationalProject)) {
            // set the owning side to null (unless already changed)
            if ($educationalProject->getPlace() === $this) {
                $educationalProject->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, Examen>
     */
    public function getExamens(): Collection
    {
        return $this->examens;
    }

    public function addExamen(Examen $examen): self
    {
        if (!$this->examens->contains($examen)) {
            $this->examens[] = $examen;
            $examen->setPlace($this);
        }
        return $this;
    }

    public function removeExamen(Examen $examen): self
    {
        if ($this->examens->removeElement($examen)) {
            // set the owning side to null (unless already changed)
            if ($examen->getPlace() === $this) {
                $examen->setPlace(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, Equipment>
     */
    public function getEquipmentStorages(): Collection
    {
        return $this->equipmentStorages;
    }

    public function addEquipmentStorage(Equipment $equipmentStorage): self
    {
        if (!$this->equipmentStorages->contains($equipmentStorage)) {
            $this->equipmentStorages[] = $equipmentStorage;
            $equipmentStorage->setPlaceStorage($this);
        }
        return $this;
    }

    public function removeEquipmentStorage(Equipment $equipmentStorage): self
    {
        if ($this->equipmentStorages->removeElement($equipmentStorage)) {
            // set the owning side to null (unless already changed)
            if ($equipmentStorage->getPlaceStorage() === $this) {
                $equipmentStorage->setPlaceStorage(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, Equipment>
     */
    public function getEquipmentUseds(): Collection
    {
        return $this->equipmentUseds;
    }

    public function addEquipmentUsed(Equipment $equipmentUsed): self
    {
        if (!$this->equipmentUseds->contains($equipmentUsed)) {
            $this->equipmentUseds[] = $equipmentUsed;
            $equipmentUsed->setPlaceWhereIsUsed($this);
        }
        return $this;
    }

    public function removeEquipmentUsed(Equipment $equipmentUsed): self
    {
        if ($this->equipmentUseds->removeElement($equipmentUsed)) {
            // set the owning side to null (unless already changed)
            if ($equipmentUsed->getPlaceWhereIsUsed() === $this) {
                $equipmentUsed->setPlaceWhereIsUsed(null);
            }
        }
        return $this;
    }
}
