<?php

namespace AppBundle\Entity\Booking;

use AppBundle\Annotation\ExportSplitFields;
use AppBundle\Enum\Education\PratiqueEnum;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Dunglas\ApiBundle\Annotation\Iri;
use Recurr\Rule;
use Recurr\Weekday;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use AppBundle\Validator\Constraints\Booking as OpentalentEventAssert;
use AppBundle\Entity\AccessAndFunction\Access;
use AppBundle\Entity\Education\Education;
use AppBundle\Entity\Education\EducationCurriculum;
/**
 * Cours
 *
 * @Iri("http://schema.org/Cours")
 * @OpentalentEventAssert\Course()
 */
#[ORM\Entity(repositoryClass: 'AppBundle\Entity\Booking\Repository\CourseRepository')]
class Course extends AbstractBooking
{
    /**
     * @var ArrayCollection<CourseRecur>
     *     "course",
     *     "course_bookingrecur",
     *     "planning_list",
     *     "access_details_practicalcourses",
     *     "edu_stu_courses_courses",
     *     "student_registration_courses",
     *     "planning_detail",
     *     "course_details",
     *     "course_informations_edit"
     * })
     */
    #[Assert\Valid]
    #[ORM\OneToMany(targetEntity: 'CourseRecur', mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
    #[Groups(['bookingrecur', 'course', 'course_bookingrecur', 'planning_list', 'access_details_practicalcourses', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'course_details', 'course_informations_edit'])]
    protected $eventRecur;
    /**
     * @var ArrayCollection<Course>
     */
    #[ORM\OneToMany(targetEntity: 'Course', mappedBy: 'parent', orphanRemoval: true)]
    #[Groups(['course_timeline'])]
    private $timeline;
    /**
     * @var \AppBundle\Entity\Booking\Course
     */
    #[ORM\ManyToOne(targetEntity: 'Course', inversedBy: 'timeline')]
    #[Groups(['course'])]
    private $parent;
    /**
     * @var string
     */
    #[Assert\Type(type: 'string')]
    #[Assert\Choice(callback: ['\AppBundle\Enum\Booking\CourseTimelineTypeEnum', 'toArray'], multiple: false, min: 1)]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    #[Groups(['course'])]
    private $type;
    /**
     * @var string
     */
    #[ORM\ManyToOne(targetEntity: 'AppBundle\Entity\Education\Education')]
    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
    #[Groups(['course', 'planning_list', 'attendancebooking_list_course', 'generate_attendance', 'presence_attendance', 'course_details', 'edu_stu_courses_courses', 'student_registration_courses', 'course_informations_edit', 'planning_detail', 'student_registration_courses', 'education_input_list_access', 'worksbyusers_db_work', 'access_attendance_detail_attendancebookings', 'education_student_next_year_access'])]
    private $education;
    /**
     * @var ArrayCollection<EducationCurriculum>
     */
    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\Education\EducationCurriculum')]
    #[Groups(['course', 'course_educationcurriculum', 'planning_list', 'planning_detail', 'attendancebooking_list_course', 'generate_attendance', 'access_details_practicalcourses', 'presence_attendance', 'course_details', 'edu_stu_courses_courses', 'student_registration_courses', 'worksbyusers_db_work', 'accesses_courseteacher_show_practicalcourses', 'course_informations_edit', 'education_input_list_access'])]
    private $educationCurriculum;
    /**
     * @var ArrayCollection<Access>
     */
    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\AccessAndFunction\Access', inversedBy: 'courses')]
    #[ORM\JoinTable(name: 'course_student', joinColumns: [], inverseJoinColumns: [])]
    #[ORM\JoinColumn(name: 'course_id', referencedColumnName: 'id')]
    #[ORM\JoinColumn(name: 'student_id', referencedColumnName: 'id')]
    #[Groups(['course_access', 'access_details_practicalcourses', 'presence_attendance', 'course_details', 'edu_stu_courses_courses', 'student_registration_courses', 'planning_detail', 'course_informations_edit'])]
    private $students;
    /**
     * @var bool
     */
    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    #[Assert\Type(type: 'boolean')]
    #[Assert\NotNull]
    #[Groups(['course', 'planning_list', 'planning_detail', 'education_input_list_access'])]
    private $isCanceled = false;
    /**
     * @var bool
     */
    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    #[Assert\Type(type: 'boolean')]
    #[Assert\NotNull]
    #[Groups(['course', 'planning_detail'])]
    private $isDuplicate = false;
    /**
     * var ArrayCollection<AttendanceBooking>
     */
    #[Assert\Valid]
    #[ORM\OneToMany(targetEntity: 'AppBundle\Entity\Booking\AttendanceBooking', cascade: ['persist'], mappedBy: 'course', orphanRemoval: true)]
    #[ORM\JoinColumn(nullable: false)]
    #[Groups(['course_attendancebooking', 'planning_list', 'presence_attendance', 'student_registration_courses', 'planning_detail', 'course_details'])]
    private $attendanceBooking;
    /**
     * @var string
     * @ExportSplitFields({"name","education.educationCategory.label","educationComplementTemplate","educationCurricullumsTemplate","timeTemplate","organizersTemplate","place.name","room.name"})
     */
    #[Groups(['student_list_coursesfiltered', 'education_student_next_year_access'])]
    private $fullLabelTemplate;
    /**
     * @var string
     */
    #[Groups(['template'])]
    private $timeTemplate;
    /**
     * @var string
     */
    #[Groups(['template'])]
    private $educationComplementTemplate;
    /**
     * @var string
     */
    #[Groups(['template'])]
    private $educationCurricullumsTemplate;
    /**
     * @var string
     */
    #[Groups(['template'])]
    private $organizersTemplate;
    /**
     * @var string
     */
    #[Groups(['planning_list'])]
    private $onlyOneStudentName;
    /**
     * @var ArrayCollection<EventUser>
     */
    #[Assert\Valid]
    #[ORM\OneToMany(targetEntity: 'Work', mappedBy: 'course', cascade: ['persist'], orphanRemoval: true)]
    #[Groups(['course'])]
    private $work;
    public function __construct()
    {
        parent::__construct();
        $this->eventRecur = new ArrayCollection();
        $this->educationCurriculum = new ArrayCollection();
        $this->students = new ArrayCollection();
        $this->timeline = new ArrayCollection();
        $this->attendanceBooking = new ArrayCollection();
    }
    /**
     * Adds timeline.
     * 
     * @param Course $course
     *       
     * @return $this
     */
    public function addTimeline(Course $course) {
        $this->timeline[] = $course;
    }
    /**
     * Removes timeline.
     * 
     * @param Course $course
     * 
     * @return $this
     */
    public function removeTimeline(Course $course) {
        $key = array_search($course, $this->timeline, true);
        if (false !== $key) {
            unset($this->timeline[$key]);
        }

        return $this;        
    }
    /**
     * Gets timeline.
     * 
     * @return ArrayCollection<Course>
     */
    public function getTimeline() {
        return $this->timeline;
    }
    /**
     * Get parent
     * 
     * @return Course
     */
    public function getParent() {
        return $this->parent;
    }
    /**
     * Set parent
     * 
     * @param Course $parent
     * @return $this
     */
    public function setParent(Course $parent=null) {
        $this->parent = $parent;
        
        return $this;
    }
    /**
     * Get type
     * 
     * @return string
     */
    public function getType() {
        return $this->type;
    }
    /**
     * Set type
     * 
     * @param string $type
     * @return $this
     */
    public function setType($type) {
        $this->type = $type;
        
        return $this;
    }
    /**
     * Sets isCanceled.
     * 
     * @param bool $isCanceled
     * 
     * @return $this
     */
    public function setIsCanceled($isCanceled)
    {
        $this->isCanceled = $isCanceled;

        return $this;
    }
    /**
     * Gets isCanceled.
     * 
     * @return bool
     */
    public function getIsCanceled()
    {
        return $this->isCanceled;
    }
    /**
     * Sets isDuplicate.
     *
     * @param bool $isDuplicate
     *
     * @return $this
     */
    public function setIsDuplicate($isDuplicate)
    {
        $this->isDuplicate = $isDuplicate;

        return $this;
    }
    /**
     * Gets isDuplicate.
     *
     * @return bool
     */
    public function getIsDuplicate()
    {
        return $this->isDuplicate;
    }
    /**
     * Set education
     *
     * @param Education $education
     *
     * @return Course
     */
    public function setEducation(Education $education = null)
    {
        $this->education = $education;

        return $this;
    }
    /**
     * Get education
     *
     * @return Education
     */
    public function getEducation()
    {
        return $this->education;
    }
    /**
     * Add educationCurriculum
     *
     * @param EducationCurriculum $educationCurriculum
     *
     * @return Course
     */
    public function addEducationCurriculum(EducationCurriculum $educationCurriculum)
    {
        $this->educationCurriculum[] = $educationCurriculum;

        return $this;
    }
    /**
     * Remove educationCurriculum
     *
     * @param EducationCurriculum $educationCurriculum
     */
    public function removeEducationCurriculum(EducationCurriculum $educationCurriculum)
    {
        $this->educationCurriculum->removeElement($educationCurriculum);
    }
    /**
     * Get educationCurriculum
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getEducationCurriculum()
    {
        return $this->educationCurriculum;
    }
    /**
     * Reset education curriculum
     *
     */
    public function resetEducationCurriculum()
    {
        foreach($this->getEducationCurriculum() as $educationCurriculum){
            $this->removeEducationCurriculum($educationCurriculum);
        }
        $this->educationCurriculum->clear();
    }
    /**
     * Add student
     *
     * @param Access $student
     *
     * @return Course
     */
    public function addStudent(Access $student)
    {
        $this->students[] = $student;

        return $this;
    }
    /**
     * Remove student
     *
     * @param Access $student
     */
    public function removeStudent(Access $student)
    {
        $this->students->removeElement($student);
    }
    /**
     * Get students
     *
     * @return ArrayCollection<Access>
     */
    public function getStudents()
    {
        return $this->students;
    }
    /**
     * Add attendanceBooking
     *
     * @param \AppBundle\Entity\Booking\AttendanceBooking $attendanceBooking
     *
     * @return AbstractBooking
     */
    public function addAttendanceBooking(\AppBundle\Entity\Booking\AttendanceBooking $attendanceBooking)
    {
        $attendanceBooking->setCourse($this);
        $this->attendanceBooking[] = $attendanceBooking;

        return $this;
    }
    /**
     * Remove attendanceBooking
     *
     * @param \AppBundle\Entity\Booking\AttendanceBooking $attendanceBooking
     */
    public function removeAttendanceBooking(\AppBundle\Entity\Booking\AttendanceBooking $attendanceBooking)
    {
        $this->attendanceBooking->removeElement($attendanceBooking);
    }
    /**
     * Get attendanceBooking
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAttendanceBooking()
    {
        return $this->attendanceBooking;
    }
    /**
     * {@inheritdoc}
     */
    public function getParticipants() {
        $participants = new ArrayCollection();
        array_map(function (Access $a) use ($participants) { $participants->add($a->getPerson());}, $this->getStudents()->toArray());
        return $participants;
    }
    /**
     * @return array
     */
    public function getTimeTemplate(){
        $dateTimeStart = $this->getDatetimeStart();
        if(!empty($dateTimeStart)){
            $days = [];
            if(!empty($this->getEventRecur()) && !empty($this->getEventRecur()->get(0))){
                $rule = $this->getEventRecur()->get(0)->getRule();
                $rrule = new Rule($rule);
                $string_days = [
                    0 => 'Monday',
                    1 => 'Tuesday',
                    2 => 'Wednesday',
                    3 => 'Thursday',
                    4 => 'Friday',
                    5 => 'Saturday',
                    6 => 'Sunday'
                ];
                /** @var Weekday $weekDay */
                foreach ($rrule->getByDayTransformedToWeekdays() as $weekDays){
                    $days[] = $string_days[$weekDays->weekday];
                }
            }else{
                $days[] = $dateTimeStart->format('l');
            }

            $timezone = 'Europe/Paris';
            $dateTimeStart->setTimezone(new \DateTimeZone($timezone));
            $time = [];
            foreach ($days as $day){
                $time[] = ['value' => $day , 'translate' => true];
            }
            $time[] = $dateTimeStart->format('à H:i');
            return $time;
        }else{
            return [];
        }
    }
    /**
     * @return string
     */
    public function getEducationComplementTemplate(){
        return $this->getEducation() ? $this->getEducation()->getEducationComplementTemplate() : '';
    }
    /**
     * @return array
     */
    public function getEducationCurricullumsTemplate(){
        $educationCurricullums = [];
        foreach ($this->getEducationCurriculum() as $edc){
            $educationCurricullums[] = ( $edc->getCycle() && $edc->getCycle()->getLabel() !== 'NO_CYCLE' ? $edc->getCycle()->getLabel() : '' );
            $educationCurricullums[] = ['value' => $edc->getYear(), 'translate' => true];
            $educationCurricullums[] = $edc->getLevel();
            $educationCurricullums[] = ', ';
        }

        return $educationCurricullums;
    }
    /**
     * @return string
     */
    public function getOrganizersTemplate(){
        $organizers = [];
        foreach($this->getOrganizer() as $organizer){
            $organizers[] = $organizer->getPerson()->getFullNameTemplate();
        }

        return ' avec ' . implode(", ", $organizers);
    }
    /**
     * Gets full label.
     *
     * @return array
     */
    public function getFullLabelTemplate()
    {

        if(is_null($this->getEducation())){
            return [];
        }

        $fullLabelTemplate = [
            $this->getName(),
            $this->getEducation()->getEducationCategory()->getLabel(),
            $this->getEducationComplementTemplate()
        ];

        $fullLabelTemplate = array_merge($fullLabelTemplate, $this->getEducationCurricullumsTemplate(),$this->getTimeTemplate(), [
            $this->getOrganizersTemplate(),
            $this->getRoom() ? $this->getRoom()->getName() : '',
            $this->getPlace() ? $this->getPlace()->getName() : ''
        ] );

        return $fullLabelTemplate;
    }
    /**
     * @return string
     */
    public function getOnlyOneStudentName()
    {
        return $this->onlyOneStudentName;
    }
    /**
     * @param string $name
     */
    public function setOnlyOneStudentName($name)
    {
        $this->onlyOneStudentName = $name;
    }
    /**
     * Add Work
     *
     * @param Work $work
     *
     * @return AbstractBooking
     */
    public function addWork(Work $work)
    {
        $work->setCourse($this);
        $this->work[] = $work;

        return $this;
    }
    /**
     * Get work
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getWork()
    {
        return $this->work;
    }
}
