<?php
/**
 * Handles the Event details for all editors.
 *
 * @since   6.0.0
 *
 * @package TEC\Events\Custom_Tables\V1\Editors
 */

namespace TEC\Events_Pro\Custom_Tables\V1\Editors;

use TEC\Events\Custom_Tables\V1\Models\Event as Event_Model;
use TEC\Events\Custom_Tables\V1\Models\Occurrence;
use TEC\Events_Pro\Custom_Tables\V1\Editors\Classic\UI_Lock;
use TEC\Events_Pro\Custom_Tables\V1\Models\Occurrence as Occurrence_Model;
use TEC\Events_Pro\Custom_Tables\V1\Models\Series_Relationship;
use Tribe__Date_Utils as Dates;
use Tribe__Timezones as Timezones;
use WP_Post;

/**
 * Class Event
 *
 * @since   6.0.0
 *
 * @package TEC\Events\Custom_Tables\V1\Editors
 */
class Event {
	/**
	 * A flag to indicate whether a recurrence rule DSTART is off the occurrence
	 * pattern generated by the rule or not.
	 *
	 * @since 6.0.0
	 */
	const OFF_PATTERN_DTSTART_FLAG = 'isOffStart';

	/**
	 * Get event details from post ID provided.
	 *
	 * @since 7.0.3 Using `$id` to avoid PHP warnings if `$post` is `null`.
	 *
	 * @param int|null $id Post ID of the event.
	 *
	 * @return array<string,mixed> Details of the event.
	 */
	public function get_event_details( $id = null ) {
		$post       = get_post( $id );
		$occurrence = null;

		if ( $post instanceof WP_Post && isset( $post->_tec_occurrence ) && $post->_tec_occurrence instanceof Occurrence ) {
			$occurrence = $post->_tec_occurrence;
			$event      = Event_Model::find( $occurrence->event_id, 'event_id' );
		} else {
			$event = Event_Model::find( $id, 'post_id' );
			if ( $event instanceof Event_Model ) {
				$occurrence = Occurrence::where( 'event_id', $event->event_id )->first();
			}
		}

		$requires_first_save = $occurrence instanceof Occurrence
		                       && get_post_meta( $occurrence->post_id, '_tec_requires_first_save', true );
		/**
		 * This filter will lock the recurrence rules column with an overlay,
		 * and block all UI interactions with the recurrence rules fields.
		 *
		 * @since 6.0.0
		 *
		 * @param bool Whether to lock the interface or not.
		 */
		$lock_rules_ui = (bool) apply_filters( 'tec_events_pro_lock_rules_ui', false );

		/**
		 * This filter will lock the recurrence exclusions column with an overlay,
		 * and block all UI interactions with the recurrence exclusions fields.
		 *
		 * @since 6.0.0
		 *
		 * @param bool Whether to lock the interface or not.
		 */
		$lock_exclusions_ui = (bool) apply_filters( 'tec_events_pro_lock_exclusions_ui', false );

		$is_rdate = $this->is_request_for_rdate( $occurrence );

		$is_in_series = $occurrence instanceof Occurrence
		                && Series_Relationship::find( $occurrence->post_id, 'event_post_id' ) !== null;

		$tec_event_details = [
			'id'                => $id,
			'occurrence'        => $occurrence instanceof Occurrence ? $occurrence->to_array() : [],
			'event'             => [],
			'requiresFirstSave' => $requires_first_save,
			'isRdate'           => $is_rdate,
			'lockRulesUi'       => $lock_rules_ui,
			'lockExclusionsUi'  => $lock_exclusions_ui,
			'isInSeries'        => $is_in_series,
		];
		if ( $is_rdate && $lock_rules_ui ) {
			$ui_lock                                 = tribe( UI_Lock::class );
			$tec_event_details['isRdateNoticeParts'] = $ui_lock->get_notice_parts();
		}

		if ( $occurrence instanceof Occurrence ) {
			$tec_event_details['occurrence']            = $occurrence->to_array();
			$tec_event_details['occurrence']['isFirst'] = Occurrence::is_first( $occurrence );
		}

		if ( $event instanceof Event_Model ) {
			$tec_event_details['event'] = $event->to_array();
			try {
				$timezone                                = Timezones::build_timezone_object( $event->timezone );
				$start                                   = Dates::immutable( $event->start_date, $timezone );
				$end                                     = Dates::immutable( $event->end_date, $timezone );
				$format                                  = Dates::datepicker_formats(
				                                             tribe_get_option( 'datepickerFormat', 0 )
				                                           );
				$tec_event_details['event']['startDate'] = $start->format( $format );
				$tec_event_details['event']['endDate']   = $end->format( $format );
			} catch ( \Exception $exception ) {
				// TODO: Better handling of exception error messages.
				error_log( $exception->getMessage() );
			}
		}

		return $tec_event_details;
	}

	/**
	 * Get date, time, and text settings for the event.
	 *
	 * @return array<string,mixed>
	 */
	public function get_event_settings() {
		return [
			'textSubstitution'   => [
				'ruleEnds' => esc_html__( 'Ends', 'tribe-events-calendar-pro' ),
			],
			'dateFormat'         => tribe_get_date_format( true ),
			'dateTimeSeparator'  => tribe_get_option( 'dateTimeSeparator', ' @ ' ),
			'timeRangeSeparator' => tribe_get_option( 'timeRangeSeparator', ' - ' ),
			'datepickerFormat'   => Dates::datepicker_formats( tribe_get_option( 'datepickerFormat' ) ),
		];
	}

	/**
	 * Returns whether an Occurrence is generated from an RDATE or not.
	 *
	 * @since 6.0.0
	 *
	 * @param Occurrence|null $occurrence The Occurrence to check.
	 *
	 * @return bool Whether the Occurrence is generated from an RDATE or not.
	 */
	private function is_request_for_rdate( ?Occurrence $occurrence ): bool {
		if ( $occurrence === null ) {
			return false;
		}

		return $occurrence->is_rdate;
	}
}
