<?php

namespace SugarCalendarBookings\Calendar\Admin;

use DateTimeImmutable;

/**
 * Calendar slot data structure.
 *
 * @since 1.0.0
 */
class BaseCalendarSlot {

	/**
	 * Start date.
	 *
	 * @since 1.0.0
	 *
	 * @var DateTimeImmutable
	 */
	private $start;

	/**
	 * End date.
	 *
	 * @since 1.0.0
	 *
	 * @var DateTimeImmutable
	 */
	private $end;

	/**
	 * Constructor.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable $start Start date.
	 * @param DateTimeImmutable $end   End date.
	 */
	public function __construct( $start, $end ) {

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

	/**
	 * Get start datetime.
	 *
	 * @since 1.0.0
	 *
	 * @return DateTimeImmutable
	 */
	public function get_start() {

		return $this->start;
	}

	/**
	 * Set start datetime.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable $date_time Start datetime.
	 *
	 * @return BaseCalendarSlot;
	 */
	public function set_start( $date_time ) {

		$this->start = $date_time;

		return $this;
	}

	/**
	 * Get end datetime.
	 *
	 * @since 1.0.0
	 *
	 * @return DateTimeImmutable
	 */
	public function get_end() {

		return $this->end;
	}

	/**
	 * Set end datetime.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable $date_time End datetime.
	 *
	 * @return BaseCalendarSlot
	 */
	public function set_end( $date_time ) {

		$this->end = $date_time;

		return $this;
	}

	/**
	 * Convert to string.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function to_string() {

		return $this->start->format( 'Y-m-d H:i:s' ) . '-' . $this->end->format( 'Y-m-d H:i:s' );
	}

	/**
	 * Whether a date is included in this slot.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable $date Date.
	 *
	 * @return bool
	 */
	public function includes( $date ) {

		return $this->start <= $date && $this->end >= $date;
	}

	/**
	 * Whether this slot starts on the first day of the month.
	 *
	 * @since 1.0.0
	 *
	 * @return bool
	 */
	public function is_first_day_of_month() {

		return $this->get_start()->format( 'j' ) === '1';
	}

	/**
	 * Whether a date is in the same month as this slot.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable $date Date.
	 *
	 * @return bool
	 */
	public function is_same_month( $date ) {

		return $date->format( 'n' ) === $this->get_start()->format( 'n' );
	}

	/**
	 * Whether a data is the same day as this slot.
	 *
	 * @since 1.0.0
	 *
	 * @param DateTimeImmutable $date Date.
	 *
	 * @return bool
	 */
	public function is_same_day( $date ) {

		return $date->format( 'Y-m-d' ) === $this->get_start()->format( 'Y-m-d' );
	}

	/**
	 * Get the duration in seconds.
	 *
	 * @since 1.0.0
	 *
	 * @return int
	 */
	public function get_duration() {

		return $this->get_end()->getTimestamp() - $this->get_start()->getTimestamp();
	}

	/**
	 * Whether this slot overlaps with another one.
	 *
	 * @since 1.0.0
	 * @since 1.1.0 Added inclusive parameter.
	 *
	 * @param BaseCalendarSlot $slot      Slot to check for overlap.
	 * @param bool             $inclusive Whether to check inclusively.
	 *
	 * @return bool
	 */
	public function overlaps( $slot, $inclusive = false ) {

		if ( $inclusive ) {
			return (
				( $this->get_start() >= $slot->get_start() && $this->get_start() <= $slot->get_end() ) ||
				( $this->get_end() >= $slot->get_start() && $this->get_end() <= $slot->get_end() )
			);
		}

		return (
			( $this->get_start() > $slot->get_start() && $this->get_start() < $slot->get_end() ) ||
			( $this->get_end() > $slot->get_start() && $this->get_end() < $slot->get_end() )
		);
	}
}
