<?php

namespace App\Entity;

use App\Enums\NoteLocation;
use App\Enums\NoteMethod;
use App\Enums\NoteStatus;
use App\Repository\NoteRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\MappedSuperclass;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;

#[MappedSuperclass(NoteRepository::class)]
class Note
{
    #[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(type: Types::DATE_MUTABLE)]
    private ?\DateTimeInterface $date = null;

    #[ORM\ManyToOne(inversedBy: 'notes')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Referral $referral = null;

    #[ORM\Column(type: Types::TIME_MUTABLE)]
    private ?\DateTimeInterface $startTime = null;

    #[ORM\Column(type: Types::TIME_MUTABLE)]
    private ?\DateTimeInterface $endTime = null;

    #[ORM\Column(enumType: NoteStatus::class)]
    private ?NoteStatus $status = null;

    #[ORM\Column(enumType: NoteLocation::class)]
    private ?NoteLocation $location = null;

    #[ORM\Column(enumType: NoteMethod::class)]
    private ?NoteMethod $method = null;

    private ?array $members = null;

    public function __construct()
    {
        $this->members = [];
    }

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

    public function getDate(): ?\DateTimeInterface
    {
        return $this->date;
    }

    public function setDate(\DateTimeInterface $date): static
    {
        $this->date = $date;

        return $this;
    }

    public function getReferral(): ?Referral
    {
        return $this->referral;
    }

    public function setReferral(?Referral $referral): static
    {
        $this->referral = $referral;

        return $this;
    }

    public function getStartTime(): ?\DateTimeInterface
    {
        return $this->startTime;
    }

    public function setStartTime(\DateTimeInterface $startTime): static
    {
        $this->startTime = $startTime;

        return $this;
    }

    public function getEndTime(): ?\DateTimeInterface
    {
        return $this->endTime;
    }

    public function setEndTime(\DateTimeInterface $endTime): static
    {
        $this->endTime = $endTime;

        return $this;
    }

    public function getStatus(): ?NoteStatus
    {
        return $this->status;
    }

    public function setStatus(NoteStatus $status): static
    {
        $this->status = $status;

        return $this;
    }

    public function getLocation(): ?NoteLocation
    {
        return $this->location;
    }

    public function setLocation(NoteLocation $location): static
    {
        $this->location = $location;

        return $this;
    }

    public function getMethod(): ?NoteMethod
    {
        return $this->method;
    }

    public function setMethod(NoteMethod $method): static
    {
        $this->method = $method;

        return $this;
    }

    public function getMembers(): ?array
    {
        return $this->members;
    }

    public function setMembers(?array $members): static
    {
        $this->members = $members;

        return $this;
    }

    public function addMember(Member $member): static
    {
        $this->members[] = $member;

        return $this;
    }

    /**
     * Method to calculate the number of minutes used for a visit rounded to the nearest 15 min increment
     *
     * @param int $precision
     *      The number of minutes to round the time to defaulted to 15
     *
     * @return int
     *      The number of minutes calculated
     */
    public function calcTimeUsed(int $precision = 15): int
    {
        // get the number of seconds between the two times
        $timestamp = $this->endTime->getTimestamp() - $this->startTime->getTimestamp();

        // find out how many increments of precision there are between these two increments
        $increments = ($timestamp / 60) / $precision;

        // if the number of increments is a float that means there is a difference
        if (is_float($increments)) {
            // calculate the modulo
            $mod = ($timestamp / 60) % $precision;
            // if the modulo is higher than half the precision increment increase the increments by 1
            if ($mod >= ($precision / 2)) {
                $increments++;
            }
            // convert the increments to an integer
            $increments = (int) $increments;
        }

        // return the number of increments times the precision to the partials
        return $increments * $precision;
    }
}
