<?php

namespace App\Entity;


use App\Entity\IFace\IEntity;
use App\Utils\Utils;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Config\Definition\Exception\Exception;

/**
 * @ORM\Entity
 * @ORM\Table(name="service_meeting", indexes={@ORM\Index(name="search_service_idx", columns={"service_id", "owner_user_id", "service_contact_id"})})
 */
class EntServiceMeeting implements IEntity
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="integer", nullable=false, options={"unsigned" = true})
     */
    protected $service_id;

    /**
     * @ORM\Column(type="integer", nullable=false, options={"unsigned" = true})
     */
    protected $creation_user_id;

    /**
     * @ORM\Column(type="integer", nullable=false, options={"unsigned" = true})
     */
    protected $owner_user_id;

    /**
     * @ORM\Column(type="integer", nullable=false, options={"unsigned" = true})
     */
    protected $meeting_type_id;
    /**
     * @ORM\Column(type="string", nullable=false)
     */
    protected $title;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $description;

    /**
     * @ORM\Column(type="datetime", nullable=false)
     */
    protected $start_date;

    /**
     * @ORM\Column(type="datetime", nullable=false)
     */
    protected $end_date;

    /**
     * @ORM\Column(type="integer", nullable=true, options={"unsigned" = true})
     */
    protected $service_contact_id;

    /**
     * @ORM\Column(name="gender", type="string", columnDefinition="enum('male', 'female', 'diverse')")
     */
    protected $gender;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $firstname;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $lastname;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $email;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $phone_no;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $mobile_no;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $department;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $street;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $street_no;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $zip;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $city;

    /**
     * @ORM\Column(type="integer", nullable=true, options={"unsigned" = true})
     */
    protected $country_id;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $report;

    /**
     * @ORM\Column(type="boolean", nullable=false)
     */
    protected $first_reminder_sent;

    /**
     * @ORM\Column(type="boolean", nullable=false)
     */
    protected $second_reminder_sent;

    /**
     * @ORM\Column(type="boolean", nullable=false)
     */
    protected $report_reminder_sent;

    /**
     * @ORM\Column(type="datetime", nullable=false)
     */
    protected $creation_date;


    /**
     * EntServiceMeeting constructor.
     * @param ObjectManager $em
     * @param EntService $entService
     * @param EntUser $entCreationUser
     * @param EntUser $entOwnerUser
     * @param EntMeetingType $entMeetingType
     * @param $title
     * @param $startDate
     * @param $endDate
     * @throws \Exception
     */
    public function __construct(ObjectManager  $em, EntService $entService, EntUser $entCreationUser, EntUser $entOwnerUser,
                                EntMeetingType $entMeetingType, $title, $startDate, $endDate)
    {
        if (is_null($entService->getId())) {
            throw new Exception('no id found');
        }

        if (is_null($entCreationUser->getId())) {
            throw new Exception('no id found');
        }

        if (is_null($entOwnerUser->getId())) {
            throw new Exception('no id found');
        }

        $meetingTypesById = EntMeetingType::getMeetingTypesById($em);
        if (is_null($entMeetingType->getId()) || !array_key_exists($entMeetingType->getId(), $meetingTypesById)) {
            throw new Exception('no id found');
        }

        $this->service_id = $entService->getId();
        $this->creation_user_id = $entCreationUser->getId();
        $this->owner_user_id = $entOwnerUser->getId();
        $this->meeting_type_id = $entMeetingType->getId();
        $this->title = $title;
        $this->setStartDate($startDate);
        $this->setEndDate($endDate);
        $this->first_reminder_sent = false;
        $this->second_reminder_sent = false;
        $this->report_reminder_sent = false;
        $this->creation_date = new \DateTime();
    }

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return mixed
     */
    public function getServiceId()
    {
        return $this->service_id;
    }

    /**
     * @return mixed
     */
    public function getCreationUserId()
    {
        return $this->creation_user_id;
    }

    /**
     * @return mixed
     */
    public function getOwnerUserId()
    {
        return $this->owner_user_id;
    }

    /**
     * @return mixed
     */
    public function getMeetingTypeId()
    {
        return $this->meeting_type_id;
    }

    /**
     * @return mixed
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @return mixed
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @return mixed
     */
    public function getStartDate()
    {
        return $this->start_date;
    }

    /**
     * @return mixed
     */
    public function getEndDate()
    {
        return $this->end_date;
    }

    /**
     * @return mixed
     */
    public function getServiceContactId()
    {
        return $this->service_contact_id;
    }

    /**
     * @return mixed
     */
    public function getGender()
    {
        return $this->gender;
    }

    /**
     * @return mixed
     */
    public function getFirstname()
    {
        return $this->firstname;
    }

    /**
     * @return mixed
     */
    public function getLastname()
    {
        return $this->lastname;
    }

    /**
     * @return mixed
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @return mixed
     */
    public function getPhoneNo()
    {
        return $this->phone_no;
    }

    /**
     * @return mixed
     */
    public function getMobileNo()
    {
        return $this->mobile_no;
    }

    /**
     * @return mixed
     */
    public function getDepartment()
    {
        return $this->department;
    }

    /**
     * @return mixed
     */
    public function getStreet()
    {
        return $this->street;
    }

    /**
     * @return mixed
     */
    public function getStreetNo()
    {
        return $this->street_no;
    }

    /**
     * @return mixed
     */
    public function getZip()
    {
        return $this->zip;
    }

    /**
     * @return mixed
     */
    public function getCity()
    {
        return $this->city;
    }

    /**
     * @return mixed
     */
    public function getCountryId()
    {
        return $this->country_id;
    }

    /**
     * @return mixed
     */
    public function getReport()
    {
        return $this->report;
    }

    /**
     * @return bool
     */
    public function isFirstReminderSent(): bool
    {
        return $this->first_reminder_sent;
    }

    /**
     * @return bool
     */
    public function isSecondReminderSent(): bool
    {
        return $this->second_reminder_sent;
    }

    /**
     * @param mixed $owner_user_id
     */
    public function setOwnerUserId($owner_user_id): void
    {
        $this->owner_user_id = $owner_user_id;
    }

    /**
     * @param mixed $gender
     */
    public function setGender($gender): void
    {
        if (!is_null($gender) && !Utils::isValidGender($gender)) {
            throw new Exception('invalid gender');
        }
        $this->gender = $gender;
    }

    /**
     * @param mixed $meeting_type_id
     */
    public function setMeetingTypeId($meeting_type_id): void
    {
        $this->meeting_type_id = $meeting_type_id;
    }

    /**
     * @param mixed $title
     */
    public function setTitle($title): void
    {
        $this->title = $title;
    }

    /**
     * @param mixed $description
     */
    public function setDescription($description): void
    {
        $this->description = $description;
    }

    /**
     * @param mixed $start_date
     */
    public function setStartDate($start_date): void
    {
        $this->start_date = \DateTime::createFromFormat('Y-m-d H:i:s', $start_date);
    }

    /**
     * @param mixed $end_date
     */
    public function setEndDate($end_date): void
    {
        $this->end_date = \DateTime::createFromFormat('Y-m-d H:i:s', $end_date);
    }

    /**
     * @param ObjectManager $em
     * @param $service_contact_id
     */
    public function setServiceContactId(ObjectManager $em, $service_contact_id): void
    {
        if ($service_contact_id == 0) {
            $this->service_contact_id = $service_contact_id;
        } else {
            /** @var EntServiceContact $entServiceContact */
            $entServiceContact = $em->getRepository(EntServiceContact::class)->find($service_contact_id);
            // NOTE: Check if contact still exists
            $this->service_contact_id = !is_null($entServiceContact) ? $service_contact_id : null;
        }
    }

    /**
     * @param mixed $firstname
     */
    public function setFirstname($firstname): void
    {
        $this->firstname = $firstname;
    }

    /**
     * @param mixed $lastname
     */
    public function setLastname($lastname): void
    {
        $this->lastname = $lastname;
    }

    /**
     * @param mixed $email
     */
    public function setEmail($email): void
    {
        $this->email = $email;
    }

    /**
     * @param mixed $phone_no
     */
    public function setPhoneNo($phone_no): void
    {
        $this->phone_no = $phone_no;
    }

    /**
     * @param mixed $mobile_no
     */
    public function setMobileNo($mobile_no): void
    {
        $this->mobile_no = $mobile_no;
    }

    /**
     * @param mixed $department
     */
    public function setDepartment($department): void
    {
        $this->department = $department;
    }

    /**
     * @param mixed $street
     */
    public function setStreet($street): void
    {
        $this->street = $street;
    }

    /**
     * @param mixed $street_no
     */
    public function setStreetNo($street_no): void
    {
        $this->street_no = $street_no;
    }

    /**
     * @param mixed $zip
     */
    public function setZip($zip): void
    {
        $this->zip = $zip;
    }

    /**
     * @param mixed $city
     */
    public function setCity($city): void
    {
        $this->city = $city;
    }

    /**
     * @param mixed $country_id
     */
    public function setCountryId($country_id): void
    {
        $this->country_id = $country_id;
    }

    /**
     * @param $report
     * @throws \Exception
     */
    public function setReport($report): void
    {
        $now = new \DateTime();
        if ($now < $this->getStartDate()) {
            throw new Exception('meeting has not started yet');
        }
        $this->report = $report;
    }

    /**
     * @param mixed $first_reminder_sent
     */
    public function setFirstReminderSent($first_reminder_sent): void
    {
        $this->first_reminder_sent = $first_reminder_sent;
    }

    /**
     * @param mixed $second_reminder_sent
     */
    public function setSecondReminderSent($second_reminder_sent): void
    {
        $this->second_reminder_sent = $second_reminder_sent;
    }

    /**
     * @param mixed $report_reminder_sent
     */
    public function setReportReminderSent($report_reminder_sent): void
    {
        $this->report_reminder_sent = $report_reminder_sent;
    }

    /**
     * Checks if meeting is editable or deletable
     * @return bool
     * @throws \Exception
     */
    public function isEditDeletable()
    {
        $now = new \DateTime();
        return $now < $this->getStartDate();
    }

    /**
     * Sets client data
     * @param ObjectManager $em
     * @param $clientData
     */
    public function setClientData(ObjectManager $em, $clientData)
    {
        $this->setOwnerUserId($clientData->owner_user_id);
        $this->setMeetingTypeId($clientData->meeting_type_id);
        $this->setTitle($clientData->title);
        $this->setDescription($clientData->description);
        $this->setStartDate($clientData->start_date);
        $this->setEndDate($clientData->end_date);
        $this->setStreet($clientData->street);
        $this->setStreetNo($clientData->street_no);
        $this->setZip($clientData->zip);
        $this->setCity($clientData->city);
        $this->setCountryId($clientData->country_id);
        $this->setServiceContactId($em, $clientData->service_contact_id);

        if (is_null($this->service_contact_id)) {
            $this->setGender(null);
            $this->setFirstname(null);
            $this->setLastname(null);
            $this->setEmail(null);
            $this->setPhoneNo(null);
            $this->setMobileNo(null);
            $this->setDepartment(null);
        } else {
            $this->setGender($clientData->gender);
            $this->setFirstname($clientData->firstname);
            $this->setLastname($clientData->lastname);
            $this->setEmail($clientData->email);
            $this->setPhoneNo($clientData->phone_no);
            $this->setMobileNo($clientData->mobile_no);
            $this->setDepartment($clientData->department);
        }
    }

    /**
     * Client mapper
     * @param ObjectManager $em
     * @param bool $fullMapping
     * @return array
     * @throws \Exception
     */
    public function clientMapper(ObjectManager $em, $fullMapping = false)
    {
        $now = new \DateTime();
        return [
            'id' => $this->id,
            'service_id' => (int)$this->service_id,
            'creation_user_id' => (int)$this->creation_user_id,
            'owner_user_id' => (int)$this->owner_user_id,
            'meeting_type_id' => (int)$this->meeting_type_id,
            'title' => $this->title,
            'description' => $this->description,
            'start_date' => !is_null($this->start_date) ? $this->start_date->format('Y-m-d H:i:s'): null,
            'end_date' => !is_null($this->end_date) ? $this->end_date->format('Y-m-d H:i:s'): null,
            'service_contact_id' => $this->service_contact_id,
            'gender' => $this->gender,
            'firstname' => $this->firstname,
            'lastname' => $this->lastname,
            'email' => $this->email,
            'phone_no' => $this->phone_no,
            'mobile_no' => $this->mobile_no,
            'department' => $this->department,
            'street' => $this->street,
            'street_no' => $this->street_no,
            'zip' => $this->zip,
            'city' => $this->city,
            'country_id' => $this->country_id,
            'report' => $this->report,
            'first_reminder_sent' => $this->first_reminder_sent,
            'second_reminder_sent' => $this->second_reminder_sent,
            'report_reminder_sent' => $this->report_reminder_sent,
            'creation_date' => !is_null($this->creation_date) ? $this->creation_date->format('Y-m-d H:i:s'): null,
            'v_participants' => Utils::clientMap($em, $em->getRepository(EntServiceMeetingParticipant::class)->findBy(['service_meeting_id' => $this->id])),
            'v_is_editable' => $now < $this->start_date,
        ];
    }

}
