<?php

namespace AppBundle\Entity\Booking;

use AppBundle\Entity\AccessAndFunction\Access;
use AppBundle\Entity\Core\Tagg;
use AppBundle\Entity\Place\Place;
use AppBundle\Entity\Place\Room;
use AppBundle\Entity\Product\Equipment;
use AppBundle\Entity\Traits\ActivityYearTrait;
use Doctrine\ORM\Mapping as ORM;
use Dunglas\ApiBundle\Annotation\Iri;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Serializer\Annotation\Groups;

use AppBundle\Annotation\DefaultField;
use AppBundle\Entity\Person\Person;
use AppBundle\Entity\Organization\Organization;
use AppBundle\Entity\Traits\TimestampableEntity;
use AppBundle\Entity\Traits\CreatorUpdaterEntity;

/**
 * Données d'un évènement générique, classe de base des évènements
 * Classe de base de @see Event, Course, EducationalProject, Examen, OrganizationHoliday, PersonHoliday
 *
 *
 */
#[ORM\Entity]
#[ORM\Table(name: 'Booking')]
#[ORM\Index(name: 'viewIndex', columns: ['discr', 'datetimeEnd', 'visibility', 'isCanceled'])]
#[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
#[ORM\DiscriminatorMap(['event' => 'Event', 'course' => 'Course', 'educationalproject' => 'EducationalProject', 'examen' => 'Examen', 'organizationholiday' => 'OrganizationHoliday', 'personholiday' => 'PersonHoliday'])]
#[ORM\Entity(repositoryClass: 'AppBundle\Entity\Booking\Repository\BookingRepository')]
abstract class AbstractBooking implements IBooking
{
    use TimestampableEntity;
    use CreatorUpdaterEntity;
    use ActivityYearTrait;
    /**
     * @var int
     */
    #[ORM\Column(type: 'integer')]
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    #[Groups(['booking', 'student_list', 'attendancebooking_list', 'examenconvocation_list', 'invitations_list', 'my_attendance_list', 'generate_attendance', 'access_details', 'presence_attendance', 'event_details', 'examen_details', 'course_details', 'educationalproject_details', 'edu_stu_courses', 'student_registration', 'planning_detail', 'booking_event', 'accesses_courseteacher_show', 'course_informations_edit', 'examen_informations_edit', 'educationalproject_informations_edit', 'booking_event_documents', 'accessholidays_list'])]
    private $id;
    /**
     * @var string
     */
    #[ORM\Column(type: 'string', length: 100, nullable: true)]
    #[Assert\Type(type: 'string')]
    #[Groups(['booking', 'attendancebooking_list_course', 'attendancebooking_list_educationalproject', 'attendancebooking_list_event', 'attendancebooking_list_examen', 'access_details_attendancebookings', 'access_details_attendancebookingsfiltered', 'invitations_list_event', 'my_attendance_list_course', 'my_attendance_list_educationalproject', 'my_attendance_list_event', 'my_attendance_list_examen', 'planning_list', 'generate_attendance', 'access_details_practicalcourses', 'presence_attendance', 'event_details', 'examen_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'booking_event', 'examenconvocation_list_examen', 'report_card_examenconvocations', 'report_card_attendancebookings', 'accesses_courseteacher_show_practicalcourses', 'course_informations_edit', 'examen_informations_edit', 'educationalproject_informations_edit', 'accessbilling_edit_billingeducationalprojectpayers', 'accesses_courseteacher_show_practicalcourses', 'education_input_list_access', 'activity_report', 'worksbyusers_db_work', 'access_attendance_detail_attendancebookings', 'accessholidays_list', 'build_bills_billlines'])]
    private $name;
    /**
     * @var Organization
     *
     * @DefaultField
     */
    #[ORM\ManyToOne(targetEntity: 'AppBundle\Entity\Organization\Organization')]
    #[ORM\JoinColumn(nullable: false)]
    #[Assert\NotNull]
    #[Groups(['booking'])]
    private $organization;
    /**
     * @var ArrayCollection<Person>
     */
    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\AccessAndFunction\Access', inversedBy: 'practicalCourses')]
    #[ORM\JoinTable(name: 'booking_organizer', joinColumns: [], inverseJoinColumns: [])]
    #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
    #[ORM\JoinColumn(name: 'organizer_id', referencedColumnName: 'id')]
    #[Groups(['booking_access', 'booking', 'planning_list', 'event_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'booking_event', 'course_informations_edit', 'educationalproject_informations_edit', 'booking_event', 'presence_attendance', 'education_input_list_access', 'worksbyusers_db_work', 'attendancebooking_list_course'])]
    private $organizer;
    /**
     * @var string
     */
    #[Assert\Type(type: 'string')]
    #[Groups(['booking', 'planning_list'])]
    private $color;
    /**
     * @var boolean
     */
    #[Assert\Type(type: 'boolean')]
    private $hasReplacement;
    /**
     * @var \DateTime
     */
    #[ORM\Column(type: 'datetime', nullable: true)]
    #[Assert\DateTime]
    #[Groups(['booking', 'examenconvocation_list_examen', 'planning_list', 'generate_attendance', 'report_card_examenconvocations', 'access_details_practicalcourses', 'event_details', 'examen_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'booking_event', 'accesses_courseteacher_show_practicalcourses', 'course_informations_edit', 'examen_informations_edit', 'educationalproject_informations_edit', 'activity_report', 'education_input_list_access', 'accessholidays_list'])]
    private $datetimeStart;
    /**
     * @var \DateTime
     */
    #[ORM\Column(type: 'datetime', nullable: true)]
    #[Assert\DateTime]
    #[Groups(['booking', 'planning_list', 'generate_attendance', 'access_details_practicalcourses', 'event_details', 'examen_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'booking_event', 'examenconvocation_list_examen', 'accesses_courseteacher_show_practicalcourses', 'activity_report', 'course_informations_edit', 'examen_informations_edit', 'educationalproject_informations_edit', 'accessholidays_list'])]
    private $datetimeEnd;
    /**
     * @var ArrayCollection<IBookingRecur>
     * !!!! Please define the ORM\OneToMany to the child class !!!
     * ORM\OneToMany(targetEntity="Xxxx", mappedBy="event", cascade={"persist"}, orphanRemoval=true)
     */
    #[Assert\Valid]
    #[Groups(['booking_recur', 'planning_list', 'planning_detail', 'booking_event', 'educationalproject_informations_edit', 'accesses_courseteacher_show_practicalcourses', 'student_list_courses'])]
    protected $eventRecur;
    /**
     * @var string A short description of the item.
     *
     * @Iri("https://schema.org/description")
     */
    #[ORM\Column(type: 'text', nullable: true)]
    #[Assert\Type(type: 'string')]
    #[Groups(['booking', 'event_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'booking_event', 'planning_detail', 'course_informations_edit', 'examen_informations_edit', 'examen_details', 'educationalproject_informations_edit', 'planning_detail', 'activity_report'])]
    private $description;
    /**
     * @var Place
     */
    #[ORM\ManyToOne(targetEntity: 'AppBundle\Entity\Place\Place')]
    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
    #[Groups(['booking', 'examenconvocation_list_examen', 'planning_list', 'event_details', 'examen_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'invitations_list_event', 'planning_detail', 'booking_event', 'course_informations_edit', 'course_informations_edit', 'examen_informations_edit', 'educationalproject_informations_edit', 'activity_report'])]
    private $place;
    /**
     * @var Room
     */
    #[ORM\ManyToOne(targetEntity: 'AppBundle\Entity\Place\Room')]
    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
    #[Groups(['booking', 'examenconvocation_list_examen', 'planning_list', 'examen_details', 'course_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'course_informations_edit', 'examen_informations_edit', 'educationalproject_informations_edit', 'booking_event', 'event_details'])]
    private $room;
    /**
     * @var ArrayCollection<Equipment>
     */
    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\Product\Equipment')]
    #[ORM\JoinTable(name: 'booking_equipment', joinColumns: [], inverseJoinColumns: [])]
    #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
    #[ORM\JoinColumn(name: 'equipment_id', referencedColumnName: 'id')]
    #[Groups(['booking_equipment', 'event_details', 'course_details', 'planning_detail', 'examen_details', 'educationalproject_details', 'edu_stu_courses_courses', 'student_registration_courses', 'booking_event'])]
    private $equipments;
    /**
     * @var ArrayCollection<Tagg>
     */
    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\Core\Tagg', cascade: ['persist'], inversedBy: 'bookings')]
    #[Assert\Valid]
    #[ORM\JoinTable(name: 'tag_booking', joinColumns: [], inverseJoinColumns: [])]
    #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
    #[ORM\JoinColumn(name: 'tag_id', referencedColumnName: 'id')]
    #[Groups(['booking_tags', 'manage_tags', 'booking_event', 'event_details', 'course_informations_edit', 'course_details', 'educationalproject_informations_edit', 'educationalproject_details', 'examen_informations_edit', 'examen_details', 'planning_list'])]
    private $tags;
    /**
     * The constructor
     */
    public function __construct() {
        $this->eventRecur = new ArrayCollection();
        $this->organizer = new ArrayCollection();
        $this->equipments = new ArrayCollection();
        $this->tags = new ArrayCollection();
    }
    /**
     * Sets id.
     *
     * @param int $id
     *
     * @return $this
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }
    /**
     * Gets id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Sets name.
     * 
     * @param string $name
     * 
     * @return $this
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }
    /**
     * Gets name.
     * 
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
    /**
     * Sets color.
     *
     * @param string $color
     *
     * @return $this
     */
    public function setColor($color)
    {
        $this->color = $color;

        return $this;
    }
    /**
     * Gets color.
     *
     * @return string
     */
    public function getColor()
    {
        return $this->color;
    }
    /**
     * Sets hasReplacement.
     *
     * @param boolean $hasReplacement
     *
     * @return $this
     */
    public function setHasReplacement($hasReplacement)
    {
        $this->hasReplacement = $hasReplacement;

        return $this;
    }
    /**
     * Gets hasReplacement.
     *
     * @return boolean
     */
    public function getHasReplacement()
    {
        return $this->hasReplacement;
    }
    /**
     * Sets organization.
     * 
     * @param Organization $organization
     * 
     * @return $this
     */
    public function setOrganization(Organization $organization = null)
    {
        $this->organization = $organization;

        return $this;
    }
    /**
     * Gets organization.
     * 
     * @return Organization
     */
    public function getOrganization()
    {
        return $this->organization;
    }
    /**
     * Adds organizer.
     *
     * @param Access $organizer
     *
     * @return $this
     */
    public function addOrganizer(Access $organizer)
    {
        $this->organizer[] = $organizer;

        return $this;
    }
    /**
     * Removes organizer.
     *
     * @param Access $organizer
     *
     * @return $this
     */
    public function removeOrganizer(Access $organizer)
    {
        $this->organizer->removeElement($organizer);

        return $this;
    }
    /**
     * Gets organizer.
     *
     * @return ArrayCollection<Access>
     */
    public function getOrganizer()
    {
        return $this->organizer;
    }
    /**
     * Sets datetimeStart.
     * 
     * @param \DateTime $datetimeStart
     * 
     * @return $this
     */
    public function setDatetimeStart(\DateTime $datetimeStart = null)
    {
        $this->datetimeStart = $datetimeStart;

        return $this;
    }
    /**
     * Gets datetimeStart.
     * 
     * @return \DateTime
     */
    public function getDatetimeStart()
    {
        return $this->datetimeStart;
    }
    /**
     * Sets datetimeEnd.
     * 
     * @param \DateTime $datetimeEnd
     * 
     * @return $this
     */
    public function setDatetimeEnd(\DateTime $datetimeEnd = null)
    {
        $this->datetimeEnd = $datetimeEnd;

        return $this;
    }
    /**
     * Gets datetimeEnd.
     * 
     * @return \DateTime
     */
    public function getDatetimeEnd()
    {
        return $this->datetimeEnd;
    }
    /**
     * Add eventRecur
     *
     * @param IBookingRecur $eventRecur
     *
     * @return $this
     */
    public function addEventRecur(IBookingRecur $eventRecur)
    {
        $eventRecur->setEvent($this);
        $this->eventRecur->add($eventRecur);

        return $this;
    }
    /**
     * Remove eventRecur
     *
     * @param IBookingRecur $eventRecur
     */
    public function removeEventRecur(IBookingRecur $eventRecur)
    {        
        $eventRecur->setEvent(null);
        $this->eventRecur->removeElement($eventRecur);
    }
    /**
     * Remove eventRecur
     *
     * @param IBookingRecur $eventRecur
     */
    public function resetEventRecur()
    {
        foreach($this->getEventRecur() as $eventRecur){
            $eventRecur->setEvent(null);
            $this->eventRecur->removeElement($eventRecur);
        }
        $this->eventRecur->clear();
    }
    /**
     * Get eventRecur
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getEventRecur()
    {
        return $this->eventRecur;
    }
    /**
     * Set description
     *
     * @param string $description
     *
     * @return AbstractBooking
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }
    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }
    /**
     * Set place
     *
     * @param \AppBundle\Entity\Place\Place $place
     *
     * @return AbstractBooking
     */
    public function setPlace(\AppBundle\Entity\Place\Place $place = null)
    {
        $this->place = $place;

        return $this;
    }
    /**
     * Get place
     *
     * @return \AppBundle\Entity\Place\Place
     */
    public function getPlace()
    {
        return $this->place;
    }
    /**
     * Set room
     *
     * @param \AppBundle\Entity\Place\Room $room
     *
     * @return AbstractBooking
     */
    public function setRoom(\AppBundle\Entity\Place\Room $room = null)
    {
        $this->room = $room;

        return $this;
    }
    /**
     * Get room
     *
     * @return \AppBundle\Entity\Place\Room
     */
    public function getRoom()
    {
        return $this->room;
    }
    /**
     * {@inheritdoc}
     */
    public function getParticipants() {
        throw new \Exception('This method must be implemented by children');
    }
    /**
     * Add equipment
     *
     * @param \AppBundle\Entity\Product\Equipment $equipment
     *
     * @return AbstractBooking
     */
    public function addEquipment(\AppBundle\Entity\Product\Equipment $equipment)
    {
        $this->equipments[] = $equipment;

        return $this;
    }
    /**
     * Remove equipment
     *
     * @param \AppBundle\Entity\Product\Equipment $equipment
     */
    public function removeEquipment(\AppBundle\Entity\Product\Equipment $equipment)
    {
        $this->equipments->removeElement($equipment);
    }
    /**
     * Get equipments
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getEquipments()
    {
        return $this->equipments;
    }
    /**
     * Add tag
     *
     * @param \AppBundle\Entity\Core\Tagg $tag
     *
     * @return AbstractBooking
     */
    public function addTag(\AppBundle\Entity\Core\Tagg $tag)
    {
        $this->tags[] = $tag;

        return $this;
    }
    /**
     * Remove tag
     *
     * @param \AppBundle\Entity\Core\Tagg $tag
     */
    public function removeTag(\AppBundle\Entity\Core\Tagg $tag)
    {
        $this->tags->removeElement($tag);
    }
    /**
     * Get tags
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getTags()
    {
        return $this->tags;
    }
}
