<?php

namespace SugarCalendarBookings\Availability;

use DateTime;
use JsonSerializable;
use DateTimeImmutable;
use SugarCalendarBookings\Employees\EmployeeModel;

/**
 * Availability time slot.
 *
 * Always in UTC.
 *
 * @since 1.0.0
 */
class AvailabilityTimeSlot implements JsonSerializable {

	/**
	 * Start time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @var DateTimeImmutable
	 */
	protected $start;

	/**
	 * End time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @var DateTimeImmutable
	 */
	protected $end;

	/**
	 * Available.
	 *
	 * @since 1.0.0
	 *
	 * @var bool
	 */
	private $available;

	/**
	 * Employees.
	 *
	 * Employees that are available during this time slot.
	 *
	 * @since 1.0.0
	 *
	 * @var array<EmployeeModel>
	 */
	protected $employees;

	/**
	 * Constructor.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable    $start     Start time.
	 * @param DateTimeImmutable    $end       End time.
	 * @param bool                 $available Whether the slot is available.
	 * @param array<EmployeeModel> $employees Employees.
	 */
	public function __construct( $start, $end, $available, $employees ) {

		$this->start     = $start;
		$this->end       = $end;
		$this->available = $available;
		$this->employees = $employees;
	}

	/**
	 * Get start time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @return DateTimeImmutable Start time.
	 */
	public function start() {

		return $this->start;
	}

	/**
	 * Get end time in UTC.
	 *
	 * @since 1.0.0
	 *
	 * @return DateTimeImmutable End time.
	 */
	public function end() {

		return $this->end;
	}

	/**
	 * Check if the slot is available.
	 *
	 * @since 1.0.0
	 *
	 * @return bool True if the slot is available.
	 */
	public function is_available() {

		return $this->available;
	}

	/**
	 * Get employees.
	 *
	 * @since 1.0.0
	 *
	 * @return array<EmployeeModel> Employees.
	 */
	public function get_employees() {

		return $this->employees;
	}

	/**
	 * Specify data which should be serialized to JSON.
	 *
	 * @since 1.0.0
	 *
	 * @return array Data to be serialized.
	 */
	public function jsonSerialize(): array {

		return [
			'start'     => $this->start()->format( DateTime::ATOM ),
			'end'       => $this->end()->format( DateTime::ATOM ),
			'available' => $this->is_available(),
			'employees' => array_map( fn( $employee ) => $employee->id, $this->employees ),
		];
	}
}
