<?php
/**
 * FE Admin Events controller.
 *
 * @since 1.0
 * @since 1.4 Event authorization restriction
 */

declare( strict_types=1 );
namespace FeData\FastEvents\RestAPI\Public;

defined( 'ABSPATH' ) || exit;

use ArrayObject;
use FeData\FastEvents\Helpers\AuthHelper;
use FeData\FastEvents\Helpers\EventsHelper;
use FeData\FastEvents\Helpers\SeatsHelper;
use FeData\FastEvents\Storage\PluginSettings;
use FeData\FastEvents\Utilities\CheckHtml;
use FeData\FastEvents\Utilities\JsonUtil;
use FeData\FastEvents\Utilities\TimeUtil;
use FeData\FastEvents\Utilities\UniqIds;
use FeData\FastEvents\Utilities\WebhookUtil;
use HTMLPurifier;
use stdClass;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;


/**
 * FE Admin Orders class.
 */
class EventsController extends WP_REST_Controller {
	private const CREATE = 0;
	private const UPDATE = 1;

	/**
	 * Array of attachment ids for PDF templates.
	 *
	 * @since 1.0
	 *
	 * @var array
	 */
	private array $attachment_ids = array();

	/**
	 * HTML Purifier boot flag.
	 *
	 * @since 1.0
	 *
	 * @var bool
	 */
	private bool $purifier_booted = false;

	/**
	 * Purifier identifier.
	 *
	 * @since 1.0
	 *
	 * @var HTMLPurifier
	 */
	private HTMLPurifier $purifier;

	/**
	 * Admin Orders constructor.
	 *
	 * @param AuthHelper     $auth          The auth helper.
	 * @param SeatsHelper    $seats         The seats' helper.
	 * @param EventsHelper   $events_helper The events helper.
	 * @param PluginSettings $settings      The plugin settings.
	 *
	 * @since 1.0
	 */
	public function __construct(
		private readonly AuthHelper $auth,
		private readonly SeatsHelper $seats,
		private readonly EventsHelper $events_helper,
		private readonly PluginSettings $settings,
	) {
		$this->namespace = 'fast-events/v1';
		$this->rest_base = 'admin/events';
	}


	/**
	 * Register the routes for the objects of the controller.
	 *
	 * @since 1.0
	 * @since 2.0 Refactored for a new permission system
	 */
	public function register_routes(): void {

		// Get events.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base,
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_items' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::EVENT_READ );
					},
					'args'                => $this->get_collection_params(),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_item' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::EVENT_ADD );
					},
					'args'                => $this->get_endpoint_args_for_item_schema(),
				),
				'schema' => array( $this, 'get_public_item_schema' ),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
			array(
				'args'   => array(
					'id' => array(
						'description'       => __( 'The unique id of the event', 'fast-events' ),
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
					),
				),
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_item' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::EVENT_READ );
					},
					'args'                => array(
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
					),
				),
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_item' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::EVENT_UPDATE );
					},
					'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
				),
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_item' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::EVENT_DELETE );
					},
				),
				'schema' => array( $this, 'get_public_item_schema' ),
			)
		);
	}


	/**
	 * Get the authorization for the Events endpoints.
	 *
	 * @param int $action The action on the controller.
	 * @return WP_Error|bool
	 *
	 * @since 1.0
	 * @since 2.0 Refactored for a new permission system
	 */
	public function fast_events_admin_permissions( int $action ): WP_Error|bool {
		return $this->auth->authorize( $action );
	}


	/**
	 * Get multiple events.
	 *
	 * @param WP_REST_Request $request Request instance.
	 * @return WP_REST_Response|WP_Error
	 *
	 * @since 1.0
	 * @since 1.4 Event authorization restriction
	 */
	public function get_items( $request ): WP_Error|WP_REST_Response {
		global $wpdb;

		// Look up the events.
		$event_table = $wpdb->prefix . 'fe_events';
		$auth_query  = $this->auth->get_restricted_events( $this->auth::FAST_EVENTS_AUTH_QUERY_EVENTS );

		// Get selected events.
		$where = empty( $auth_query ) ? 'WHERE id > 0' : $auth_query;

		// Include specific order ids.
		if ( ! empty( $request['include'] ) ) {
			$where .= ' AND id IN (' . implode( ',', $request['include'] ) . ')';
		}

		// Exclude specific order ids.
		if ( ! empty( $request['exclude'] ) ) {
			$where .= ' AND id NOT IN (' . implode( ',', $request['exclude'] ) . ')';
		}

		// Include a possible search clause.
		if ( ! empty( $request['search'] ) ) {
			$where .= " AND event_name LIKE '%%" . $request['search'] . "%%'";
		}

		// Get the sort-order.
		$order = ' ORDER BY ' . $request['orderby'] . ' ' . $request['order'];

		// Set pagination.
		$limit = 'LIMIT ' . $request['per_page'] . ' OFFSET ';
		if ( ! empty( $request['offset'] ) ) {
			$limit .= $request['offset'];
			$offset = $request['offset'];
		} else {
			$limit .= ( $request['page'] - 1 ) * $request['per_page'];
			$offset = ( $request['page'] - 1 ) * $request['per_page'];
		}

		$result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $event_table $where $order $limit" ) ); // phpcs:ignore
		if ( empty( $result ) ) {
			return new WP_Error( 'no_event_found', __( 'No events found', 'fast-events' ), array( 'status' => 404 ) );
		}

		$events = array();

		foreach ( $result as $order ) {
			$events[] = $this->prepare_response_for_collection(
				$this->prepare_item_for_response( $order, $request )
			);
		}

		$response = rest_ensure_response( $events );

		// Generate the totals headers.
		$per_page     = (int) $request['per_page'];
		$page         = (int) ceil( ( $offset / $per_page ) + 1 );
		$total_orders = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $event_table $where" ) ); // phpcs:ignore

		$max_pages = ceil( (int) $total_orders / $per_page );
		$response->header( 'X-WP-Total', (int) $total_orders );
		$response->header( 'X-WP-TotalPages', ceil( (int) $max_pages ) );

		$base = add_query_arg( urlencode_deep( $request->get_query_params() ), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) );
		if ( $page > 1 ) {
			$prev_page = $page - 1;

			if ( $prev_page > $max_pages ) {
				$prev_page = $max_pages;
			}

			$prev_link = add_query_arg( 'page', $prev_page, $base );
			$response->link_header( 'prev', $prev_link );
		}
		if ( $max_pages > $page ) {
			$next_page = $page + 1;
			$next_link = add_query_arg( 'page', $next_page, $base );

			$response->link_header( 'next', $next_link );
		}

		return $response;
	}


	/**
	 * Retrieve a single event.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
	 *
	 * @since 1.4 Event authorization restriction
	 */
	public function get_item( $request ): WP_Error|WP_REST_Response {
		global $wpdb;

		// Check the event authorization.
		$resp = $this->auth->check_event_authorization( absint( $request['id'] ) );
		if ( is_wp_error( $resp ) ) {
			return $resp;
		}

		// Look up the event.
		$event = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}fe_events WHERE id = %d", $request['id'] ) );
		if ( empty( $event ) ) {
			return new WP_Error( 'not_found', __( 'Event not found', 'fast-events' ), array( 'status' => 404 ) );
		}

		return rest_ensure_response( $this->prepare_item_for_response( $event, $request ) );
	}


	/**
	 * Create a new event.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error|array|string Response object on success, or WP_Error object on failure.
	 *
	 * @since 1.0
	 * @since 2.3.0 Use fast_events_json_encode.
	 */
	public function create_item( $request ): WP_Error|WP_REST_Response|array|string {
		global $wpdb;

		// Check if 'id' is empty.
		if ( ! empty( $request['id'] ) ) {
			return new WP_Error( 'event_exists', __( 'Cannot create existing event', 'fast-events' ), array( 'status' => 400 ) );
		}

		$db_fields = $this->set_db_fields( $request, self::CREATE );
		if ( is_wp_error( $db_fields ) ) {
			return $db_fields;
		}

		if ( 0 < $db_fields['group_type'] && empty( $db_fields['event_group'] ) ) {
			return new WP_Error( 'empty_group', __( 'Groupname empty', 'fast-events' ), array( 'status' => 400 ) );
		}

		// Set empty scan_keys.
		$db_fields['scan_keys'] = JsonUtil::fast_events_json_encode( new stdClass() );

		// Get the seats fields. If none, stick to default.
		$num_seats    = 0;
		$seats_format = '';
		$seats_config = '';
		$linked_event = 0;
		if ( isset( $request['seats']['number'] ) ) {
			$num_seats = $request['seats']['number'];
		}
		if ( isset( $request['seats']['format'] ) ) {
			$seats_format = sanitize_text_field( $request['seats']['format'] );
		}
		if ( isset( $request['seats']['config'] ) ) {
			$seats_config = sanitize_text_field( $request['seats']['config'] );
		}
		if ( isset( $request['seats']['linked_event'] ) && 0 !== $request['seats']['linked_event'] ) {
			$cnt = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->prefix}fe_events WHERE id = %d",
					$request['seats']['linked_event']
				)
			); // phpcs:ignore
			if ( 0 === (int) $cnt ) {
				$wpdb->query( 'ROLLBACK' );

				return new WP_Error( 'not_found', __( 'Linked seats event not found', 'fast-events' ), array( 'status' => 404 ) );
			}
			$linked_event = $request['seats']['linked_event'];
		}

		// If we use seats, validate the configuration.
		if ( isset( $db_fields['seats_needed'] ) && 1 === $db_fields['seats_needed'] ) {
			$resp = $this->seats->validate_config( $num_seats, $seats_format, $seats_config );
			if ( is_wp_error( $resp ) ) {
				return $resp;
			}
		}

		// Start the transaction.
		$wpdb->query( 'START TRANSACTION' );

		$result = $wpdb->insert( $wpdb->prefix . 'fe_events', $db_fields );

		// Analyse the insert.
		if ( false === $result ) {
			$wpdb->query( 'ROLLBACK' );

			return new WP_Error( 'failed', __( 'Create new event failed: ', 'fast-events' ) . $wpdb->last_error, array( 'status' => 400 ) );
		}
		$row_id = $wpdb->insert_id;

		// Create empty seats' config.
		$resp = $this->seats->create_entry_for_event( $row_id, $num_seats, $seats_format, $seats_config, $linked_event );
		if ( is_wp_error( $resp ) ) {
			$wpdb->query( 'ROLLBACK' );

			return $resp;
		}

		$wpdb->query( 'COMMIT' );

		// Read the new event and report.
		$event = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}fe_events WHERE id = %d", $row_id ) );
		if ( empty( $event ) ) {
			return new WP_Error( 'not_found', __( 'Event not found', 'fast-events' ), array( 'status' => 404 ) );
		}

		// Fire webhook. There is no setting yet.
		WebhookUtil::create_webhook( 'event.created', $row_id );

		$request->set_param( 'context', 'view' );

		return rest_ensure_response( $this->prepare_item_for_response( $event, $request ) );
	}


	/**
	 * Update a single event.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error|array|string Response object on success, or WP_Error object on failure.
	 *
	 * @since 1.0
	 * @since 1.4 Event authorization restriction
	 */
	public function update_item( $request ): WP_Error|WP_REST_Response|array|string {
		global $wpdb;

		// Check the event authorization.
		$resp = $this->auth->check_event_authorization( absint( $request['id'] ) );
		if ( is_wp_error( $resp ) ) {
			return $resp;
		}

		// Look up the event.
		$event = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}fe_events WHERE id = %d  FOR UPDATE", $request['id'] ) );
		if ( empty( $event ) ) {
			return new WP_Error( 'not_found', __( 'Event not found', 'fast-events' ), array( 'status' => 404 ) );
		}

		$db_fields = $this->set_db_fields( $request, self::UPDATE, $event->pdf_info, $event->input_fields, $event->tracking_info );
		if ( is_wp_error( $db_fields ) ) {
			$wpdb->query( 'ROLLBACK' );

			return $db_fields;
		}

		// Copy DB fields to the event for reporting.
		foreach ( $db_fields as $key => $value ) {
			$event->{$key} = $value;
		}

		if ( 0 < $event->group_type && empty( $event->event_group ) ) {
			return new WP_Error( 'empty_group', __( 'Groupname empty', 'fast-events' ), array( 'status' => 400 ) );
		}

		// Get the seats fields. If none, stick to current values.
		$seats = $this->seats->get_entry_for_event( (int) $event->id );
		if ( is_wp_error( $seats ) ) {
			$wpdb->query( 'ROLLBACK' );

			return $seats;
		}
		$seat_change  = false;
		$num_seats    = (int) $seats->num_seats;
		$seats_format = $seats->seat_format;
		$seats_config = $seats->seat_config;
		$linked_event = (int) $seats->linked_event;
		if ( isset( $request['seats']['number'] ) && $num_seats !== $request['seats']['number'] ) {
			$seat_change = true;
			$num_seats   = $request['seats']['number'];
		}
		if ( isset( $request['seats']['format'] ) && $seats_format !== $request['seats']['format'] ) {
			$seat_change  = true;
			$seats_format = sanitize_text_field( $request['seats']['format'] );
		}
		if ( isset( $request['seats']['config'] ) && $seats_config !== $request['seats']['config'] ) {
			$seat_change  = true;
			$seats_config = sanitize_text_field( $request['seats']['config'] );
		}
		if ( isset( $request['seats']['linked_event'] ) && $linked_event !== $request['seats']['linked_event'] ) {
			if ( 0 !== $request['seats']['linked_event'] ) {
				$cnt = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}fe_events WHERE id = %d", $request['seats']['linked_event'] ) );
				if ( 0 === (int) $cnt ) {
					$wpdb->query( 'ROLLBACK' );

					return new WP_Error( 'not_found', __( 'Linked seats event not found', 'fast-events' ), array( 'status' => 404 ) );
				}
			}
			$seat_change  = true;
			$linked_event = $request['seats']['linked_event'];
		}

		// If we use seats, validate the configuration.
		if ( 1 === (int) $event->seats_needed ) {
			$resp = $this->seats->validate_config( $num_seats, $seats_format, $seats_config );
			if ( is_wp_error( $resp ) ) {
				$wpdb->query( 'ROLLBACK' );

				return $resp;
			}
		}

		// Update seats if needed.
		if ( $seat_change ) {
			$resp = $this->seats->update_entry_for_event( (int) $event->id, $num_seats, $seats_format, $seats_config, $linked_event );
			if ( is_wp_error( $resp ) ) {
				$wpdb->query( 'ROLLBACK' );

				return $resp;
			}
		}

		// Update the data.
		if ( 0 === count( $db_fields ) && ! $seat_change ) {
			$wpdb->query( 'ROLLBACK' );

			return new WP_Error( 'nothing_to_update', __( 'Event update: nothing to update', 'fast-events' ), array( 'status' => 400 ) );

		}
		if ( 0 !== count( $db_fields ) ) {
			$result = $wpdb->update( $wpdb->prefix . 'fe_events', $db_fields, array( 'id' => $request['id'] ) );

			// Analyse the update.
			if ( false === $result ) {
				$wpdb->query( 'ROLLBACK' );

				return new WP_Error( 'failed', __( 'Event update failed: ', 'fast-events' ) . $wpdb->last_error, array( 'status' => 400 ) );
			}
			if ( 0 === $result && ! $seat_change ) {
				$wpdb->query( 'ROLLBACK' );

				return new WP_Error( 'nothing_to_update', __( 'Event update: nothing to update', 'fast-events' ), array( 'status' => 400 ) );
			}
		}
		$wpdb->query( 'COMMIT' );

		// Fire webhooks if needed.
		if ( 1 === (int) $event->webhooks_needed ) {
			WebhookUtil::create_webhook( 'event.updated', (int) $request['id'] );
		}

		$request->set_param( 'context', 'edit' );

		return rest_ensure_response( $this->prepare_item_for_response( $event, $request ) );
	}

	/**
	 * Set event DB fields for adding or updating an event.
	 *
	 * @param WP_REST_Request $request      Full details about the request.
	 * @param int             $method       Method (Create or Update).
	 * @param string          $pdf_info     PDF JSON string.
	 * @param string          $input_fields Input JSON string.
	 * @param string          $tracking     Tracking JSON string.
	 * @return array|WP_Error|string Array with fields, or WP_Error object on failure.
	 *
	 * @since 1.0
	 * @since 1.4.0 Added saas_fee, saas_user_id, sender_name and sender_email to query
	 * @since 2.2.1 An event cannot refer to itself as a linked-event
	 */
	private function set_db_fields( WP_REST_Request $request, int $method, string $pdf_info = '', string $input_fields = '', string $tracking = '' ): WP_Error|array|string {
		global $wpdb;

		if ( self::CREATE === $method ) {
			$params = $request->get_params(); // This returns all params (JSON and defaults).
		} else {
			$params       = $request->get_json_params();
			$params['id'] = $request['id'];
		}
		if ( null === $params ) {
			return new WP_Error( 'not_found', __( 'No parameters found', 'fast-events' ), array( 'status' => 404 ) );
		}

		$changed_event = array();

		if ( isset( $params['event_name'] ) ) {
			$changed_event['event_name'] = sanitize_text_field( $params['event_name'] );
		}

		if ( isset( $params['event_date'] ) ) {
			$changed_event['event_date'] = date_format( date_create( $params['event_date'] ), 'Y-m-d H:i:s' );
		}

		if ( isset( $params['event_date_format'] ) ) {
			$changed_event['event_date_format'] = sanitize_text_field( $params['event_date_format'] );
		}

		if ( isset( $params['start_date'] ) ) {
			$changed_event['start_date'] = date_format( date_create( $params['start_date'] ), 'Y-m-d H:i:s' );
		}

		if ( isset( $params['end_date'] ) ) {
			$changed_event['end_date'] = date_format( date_create( $params['end_date'] ), 'Y-m-d H:i:s' );
		}

		if ( isset( $params['event_type'] ) ) {
			$changed_event['event_type'] = $params['event_type'];
		}

		if ( isset( $params['stock'] ) ) {
			$changed_event['stock'] = $params['stock'];
		}

		if ( isset( $params['stock_link'] ) ) {
			if ( 0 !== $params['stock_link'] ) {
				$cnt = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}fe_events WHERE id = %d", (int) $params['stock_link'] ) );
				if ( 0 === (int) $cnt ) {
					return new WP_Error( 'not_found', __( 'Event for stock_link parameter not found', 'fast-events' ), array( 'status' => 404 ) );
				}
				if ( self::UPDATE === $method && (int) $params['stock_link'] === (int) $params['id'] ) {
					return new WP_Error( 'invalid_event', __( 'An event cannot refer to itself as a linked-event', 'fast-events' ), array( 'status' => 400 ) );
				}
				$changed_event['stock_link'] = $params['stock_link'];
			} else {
				$changed_event['stock_link'] = 0;
			}
		}

		if ( array_key_exists( 'saas_fee', $params ) ) {
			$changed_event['saas_fee'] = ! empty( $params['saas_fee'] ) ? number_format( floatval( $params['saas_fee'] ), 2, '.', '' ) : null;
		}

		if ( isset( $params['saas_user_id'] ) ) {
			$changed_event['saas_user_id'] = $params['saas_user_id'];
		}

		if ( isset( $params['group_type'] ) ) {
			$changed_event['group_type'] = $params['group_type'];
		}

		if ( isset( $params['event_group'] ) ) {
			$changed_event['event_group'] = sanitize_text_field( $params['event_group'] );
		}

		if ( isset( $params['redirect'] ) ) {
			$tmp = sanitize_text_field( $params['redirect'] );
			if ( ! wp_http_validate_url( $tmp ) || ! str_starts_with( $tmp, 'https' ) ) {
				return new WP_Error( 'failed', __( 'Illegal redirect URL', 'fast-events' ), array( 'status' => 400 ) );
			}
			$changed_event['redirect'] = $tmp;
		}

		if ( isset( $params['email']['sender_name'] ) ) {
			$changed_event['sender_name'] = sanitize_text_field( $params['email']['sender_name'] );
		}

		if ( isset( $params['email']['sender_email'] ) ) {
			if ( ! is_email( $params['email']['sender_email'] ) && ! empty( $params['email']['sender_email'] ) ) {
				return new WP_Error( 'failed', __( 'Invalid sender_email', 'fast-events' ), array( 'status' => 400 ) );
			}
			$changed_event['sender_email'] = $params['email']['sender_email'];
		}

		if ( isset( $params['email']['bcc'] ) ) {
			if ( ! is_email( $params['email']['bcc'] ) && ! empty( $params['email']['bcc'] ) ) {
				return new WP_Error( 'failed', __( 'Invalid email bcc', 'fast-events' ), array( 'status' => 400 ) );
			}
			$changed_event['email_bcc'] = $params['email']['bcc'];
		}

		if ( isset( $params['email']['subject'] ) ) {
			$changed_event['email_subject'] = sanitize_text_field( $params['email']['subject'] );
		}

		if ( isset( $params['email']['body'] ) ) {
			$changed_event['email_body'] = $this->purify_html( $params['email']['body'] );
		}

		if ( isset( $params['email_confirmation']['bcc'] ) ) {
			if ( ! empty( $params['email_confirmation']['bcc'] && ! is_email( $params['email_confirmation']['bcc'] ) ) ) {
				return new WP_Error( 'failed', __( 'Invalid email_confirmation bcc', 'fast-events' ), array( 'status' => 400 ) );
			}
			$changed_event['confirm_bcc'] = sanitize_email( $params['email_confirmation']['bcc'] );
		}

		if ( isset( $params['email_confirmation']['subject'] ) ) {
			$changed_event['confirm_subject'] = sanitize_text_field( $params['email_confirmation']['subject'] );
		}

		if ( isset( $params['email_confirmation']['body'] ) ) {
			$changed_event['confirm_body'] = $this->purify_html( $params['email_confirmation']['body'] );
		}

		if ( ! empty( $params['email_confirmation']['redirect'] ) ) {
			$tmp = sanitize_text_field( $params['email_confirmation']['redirect'] );
			if ( ! wp_http_validate_url( $tmp ) || ! str_starts_with( $tmp, 'https' ) ) {
				return new WP_Error( 'failed', __( 'Illegal confirmation_email redirect URL', 'fast-events' ), array( 'status' => 400 ) );
			}
			$changed_event['confirm_redirect'] = $tmp;
		}

		if ( isset( $params['emails_needed'] ) ) {
			$changed_event['emails_needed'] = true === $params['emails_needed'] ? 1 : 0;
		}

		if ( isset( $params['tickets_needed'] ) ) {
			$changed_event['tickets_needed'] = true === $params['tickets_needed'] ? 1 : 0;
		}

		if ( isset( $params['invoice_needed'] ) ) {
			$changed_event['invoice_needed'] = true === $params['invoice_needed'] ? 1 : 0;
		}

		if ( isset( $params['unique_users_needed'] ) ) {
			$changed_event['unique_users_needed'] = true === $params['unique_users_needed'] ? 1 : 0;
		}

		if ( isset( $params['user_groups_needed'] ) ) {
			$changed_event['user_groups_needed'] = true === $params['user_groups_needed'] ? 1 : 0;
		}

		if ( isset( $params['recaptcha_needed'] ) ) {
			$changed_event['recaptcha_needed'] = true === $params['recaptcha_needed'] ? 1 : 0;
		}

		if ( isset( $params['confirmation_emails_needed'] ) ) {
			$changed_event['confirmation_emails_needed'] = true === $params['confirmation_emails_needed'] ? 1 : 0;
		}

		if ( isset( $params['confirmation_timeout'] ) ) {
			$changed_event['confirmation_timeout'] = $params['confirmation_timeout'];
		}

		if ( isset( $params['add_dashboard_orders_needed'] ) ) {
			$changed_event['add_dashboard_orders_needed'] = true === $params['add_dashboard_orders_needed'] ? 1 : 0;
		}

		if ( isset( $params['test_payments_needed'] ) ) {
			$changed_event['test_payments_needed'] = true === $params['test_payments_needed'] ? 1 : 0;
		}

		if ( isset( $params['seats_needed'] ) ) {
			$changed_event['seats_needed'] = true === $params['seats_needed'] ? 1 : 0;
		}

		if ( isset( $params['webhooks_needed'] ) ) {
			$changed_event['webhooks_needed'] = true === $params['webhooks_needed'] ? 1 : 0;
		}

		if ( isset( $params['reload_on_exit_needed'] ) ) {
			$changed_event['reload_on_exit_needed'] = true === $params['reload_on_exit_needed'] ? 1 : 0;
		}

		if ( isset( $params['tracking_needed'] ) ) {
			$changed_event['tracking_needed'] = true === $params['tracking_needed'] ? 1 : 0;
		}

		if ( isset( $params['coupons_needed'] ) ) {
			$changed_event['coupons_needed'] = true === $params['coupons_needed'] ? 1 : 0;
		}

		if ( isset( $params['terms'] ) ) {
			$changed_event['terms'] = strip_tags( $params['terms'], array( 'a', 'b', 'i', 'u' ) );
		}

		$tmp = $this->get_pdf_fields( $params, $pdf_info, $input_fields );
		if ( is_wp_error( $tmp ) ) {
			return $tmp;
		}
		$changed_event['pdf_info'] = $tmp;

		$tmp = $this->get_input_fields( $params, $input_fields );
		if ( is_wp_error( $tmp ) ) {
			return $tmp;
		}
		$changed_event['input_fields'] = $tmp;

		$tmp = $this->get_tracking_fields( $params, $tracking );
		if ( is_wp_error( $tmp ) ) {
			return $tmp;
		}
		$changed_event['tracking_info'] = $tmp;

		return $changed_event;
	}


	/**
	 * Purify an HTML string.
	 *
	 * @param string $html Raw HTML string.
	 * @return string Purifier HTML string.
	 *
	 * @since 1.0
	 */
	private function purify_html( string $html ): string {
		if ( ! $this->purifier_booted ) {
			$this->purifier = CheckHtml::purify();
		}

		return $this->purifier->purify( $html );
	}


	/**
	 * Get PDF fields JSON structure.
	 *
	 * @param array  $params       Array with the parameters.
	 * @param string $pdf_info     PDF JSON string.
	 * @param string $input_fields Input JSON string.
	 *
	 * @return WP_Error|string WP_Error or JSON string.
	 *
	 * @since 1.0
	 * @since 2.0.1 Removed pertype
	 * @since 2.3.0 Use fast_events_json_encode.
	 */
	private function get_pdf_fields( array $params, string $pdf_info, string $input_fields ): WP_Error|string {
		$pdf = json_decode( $pdf_info, true );
		if ( empty( $pdf ) ) {
			$pdf = array(
				'ticket'  => array(
					'id'        => 0,
					'x'         => 13,
					'y'         => 58,
					'rotate'    => 0,
					'scale'     => 100,
					'no_border' => 0,
					'types'     => new ArrayObject(),
				),
				'invoice' => array(
					'id'        => 0,
					'vat'       => 0,
					'name'      => array(
						'x' => 27,
						'y' => 60,
					),
					'invoiceno' => array(
						'x' => 127,
						'y' => 65,
					),
					'line'      => array(
						'x' => 25,
						'y' => 92,
						'w' => 158,
					),
				),
			);

			// Add the ticket types.
			$inp = json_decode( $input_fields );
			if ( null !== $inp ) {
				$tmp = array();
				foreach ( $inp->tickets as $ticket ) {
					$tmp[ $ticket->name ] = $pdf['ticket']['id'];
				}
				$pdf['ticket']['types'] = $tmp;
			}
		}

		if ( isset( $params['pdf_fields']['ticket']['attachment_id'] ) ) {
			if ( 0 !== (int) $params['pdf_fields']['ticket']['attachment_id'] && ! $this->events_helper->check_pdf_template_id( (int) $params['pdf_fields']['ticket']['attachment_id'] ) ) {
				return new WP_Error( 'not_found', __( 'PDF ticket template not found', 'fast-events' ), array( 'status' => 404 ) );
			}
			$pdf['ticket']['id'] = $params['pdf_fields']['ticket']['attachment_id'];
		}

		if ( isset( $params['pdf_fields']['ticket']['x_position'] ) ) {
			$pdf['ticket']['x'] = $params['pdf_fields']['ticket']['x_position'];
		}

		if ( isset( $params['pdf_fields']['ticket']['y_position'] ) ) {
			$pdf['ticket']['y'] = $params['pdf_fields']['ticket']['y_position'];
		}

		if ( isset( $params['pdf_fields']['ticket']['rotation'] ) ) {
			$pdf['ticket']['rotate'] = $params['pdf_fields']['ticket']['rotation'];
		}

		if ( isset( $params['pdf_fields']['ticket']['scale'] ) ) {
			$pdf['ticket']['scale'] = $params['pdf_fields']['ticket']['scale'];
		}

		if ( isset( $params['pdf_fields']['ticket']['no_border'] ) ) {
			$pdf['ticket']['no_border'] = true === $params['pdf_fields']['ticket']['no_border'] ? 1 : 0;
		}

		if ( isset( $params['pdf_fields']['invoice']['attachment_id'] ) ) {
			if ( 0 !== $params['pdf_fields']['invoice']['attachment_id'] && ! $this->events_helper->check_pdf_template_id( $params['pdf_fields']['invoice']['attachment_id'] ) ) {
				return new WP_Error( 'not_found', __( 'PDF invoice template not found', 'fast-events' ), array( 'status' => 404 ) );
			}
			$pdf['invoice']['id'] = $params['pdf_fields']['invoice']['attachment_id'];
		}

		if ( isset( $params['pdf_fields']['invoice']['use_vat'] ) ) {
			$pdf['invoice']['vat'] = true === $params['pdf_fields']['invoice']['use_vat'] ? 1 : 0;
		}

		if ( isset( $params['pdf_fields']['invoice']['name_position']['x_position'] ) ) {
			$pdf['invoice']['name']['x'] = $params['pdf_fields']['invoice']['name_position']['x_position'];
		}

		if ( isset( $params['pdf_fields']['invoice']['name_position']['y_position'] ) ) {
			$pdf['invoice']['name']['y'] = $params['pdf_fields']['invoice']['name_position']['y_position'];
		}

		if ( isset( $params['pdf_fields']['invoice']['invoice_number_position']['x_position'] ) ) {
			$pdf['invoice']['invoiceno']['x'] = $params['pdf_fields']['invoice']['invoice_number_position']['x_position'];
		}

		if ( isset( $params['pdf_fields']['invoice']['invoice_number_position']['y_position'] ) ) {
			$pdf['invoice']['invoiceno']['y'] = $params['pdf_fields']['invoice']['invoice_number_position']['y_position'];
		}

		if ( isset( $params['pdf_fields']['invoice']['first_line_position']['x_position'] ) ) {
			$pdf['invoice']['line']['x'] = $params['pdf_fields']['invoice']['first_line_position']['x_position'];
		}

		if ( isset( $params['pdf_fields']['invoice']['first_line_position']['y_position'] ) ) {
			$pdf['invoice']['line']['y'] = $params['pdf_fields']['invoice']['first_line_position']['y_position'];
		}

		if ( isset( $params['pdf_fields']['invoice']['first_line_position']['line_width'] ) ) {
			$pdf['invoice']['line']['w'] = $params['pdf_fields']['invoice']['first_line_position']['line_width'];
		}

		return JsonUtil::fast_events_json_encode( $pdf );
	}


	/**
	 * Get input fields JSON structure.
	 *
	 * @param array  $params       Array with the parameters.
	 * @param string $input_fields Input JSON string.
	 * @return string|WP_Error JSON string or WP_Error.
	 *
	 * @since 1.0
	 * @since 2.3.0 Use fast_events_json_encode.
	 */
	private function get_input_fields( array $params, string $input_fields ): WP_Error|string {
		$inp = json_decode( $input_fields, true );
		if ( JSON_ERROR_NONE !== json_last_error() || empty( $inp ) ) {
			$inp = array(
				'fields'       => array(),
				'tickets'      => array(),
				'submit'       => array(
					'name' => __( 'Pay', 'fast-events' ),
				),
				'unique_users' => array(
					'master_eventids' => '',
				),
				'user_group'   => array(
					'id'          => 0,
					'eventid'     => '',
					'roles'       => '',
					'rest_url'    => '',
					'rest_header' => '',
				),
			);

		}

		if ( isset( $params['unique_event_ids'] ) ) {
			$inp['unique_users']['master_eventids'] = sanitize_text_field( $params['unique_event_ids'] );
		}

		if ( isset( $params['order_submit_text'] ) ) {
			$inp['submit']['name'] = sanitize_text_field( $params['order_submit_text'] );
		}

		if ( isset( $params['user_groups']['group_type'] ) ) {
			$inp['user_group']['id'] = $params['user_groups']['group_type'];
		}

		if ( isset( $params['user_groups']['event_id'] ) ) {
			$inp['user_group']['eventid'] = sanitize_text_field( $params['user_groups']['event_id'] );
		}

		if ( isset( $params['user_groups']['wordpress_roles'] ) ) {
			$inp['user_group']['roles'] = sanitize_text_field( $params['user_groups']['wordpress_roles'] );
		}

		if ( isset( $params['user_groups']['rest_header'] ) ) {
			$inp['user_group']['rest_header'] = sanitize_text_field( $params['user_groups']['rest_header'] );
		}

		if ( isset( $params['user_groups']['rest_url'] ) ) {
			$tmp = sanitize_text_field( $params['user_groups']['rest_url'] );
			if ( '' !== $tmp && ( ! wp_http_validate_url( $tmp ) || ! str_starts_with( $tmp, 'https' ) ) ) {
				return new WP_Error( 'failed', __( 'Illegal REST URL', 'fast-events' ), array( 'status' => 400 ) );
			}
			$inp['user_group']['rest_url'] = sanitize_text_field( $params['user_groups']['rest_url'] );
		}

		return JsonUtil::fast_events_json_encode( $inp );
	}


	/**
	 * Get tracking fields JSON structure.
	 *
	 * @param array  $params        Array with the parameters.
	 * @param string $tracking_info PDF JSON string.
	 * @return WP_Error|string WP_Error or JSON string.
	 *
	 * @since 1.0
	 * @since 2.3.0 Use fast_events_json_encode.
	 */
	private function get_tracking_fields( array $params, string $tracking_info ): WP_Error|string {
		$tracking = json_decode( $tracking_info, true );
		if ( empty( $tracking ) ) {
			$tracking = array(
				'start_tracking'     => wp_date( 'Y-m-d' ) . ' 00:00:00',
				'stop_tracking'      => wp_date( 'Y-m-d' ) . ' 23:59:59',
				'geofence_radius'    => 200,
				'distance_filter'    => 10,
				'no_entry_scan'      => false,
				'force_tracking_app' => false,
				'tr_help_url'        => home_url(),
				'tr_help_tel'        => '',
				'tr_help_txt'        => '',
				'tracks'             => array(),
			);
		}

		if ( isset( $params['tracking']['start_tracking'] ) ) {
			$tracking['start_tracking'] = $params['tracking']['start_tracking'];
		}

		if ( isset( $params['tracking']['stop_tracking'] ) ) {
			$tracking['stop_tracking'] = $params['tracking']['stop_tracking'];
		}

		if ( isset( $params['tracking']['geofence_radius'] ) ) {
			$tracking['geofence_radius'] = $params['tracking']['geofence_radius'];
		}

		if ( isset( $params['tracking']['distance_filter'] ) ) {
			$tracking['distance_filter'] = $params['tracking']['distance_filter'];
		}

		if ( isset( $params['tracking']['no_entry_scan'] ) ) {
			$tracking['no_entry_scan'] = $params['tracking']['no_entry_scan'];
		}

		if ( isset( $params['tracking']['force_tracking_app'] ) ) {
			$tracking['force_tracking_app'] = $params['tracking']['force_tracking_app'];
		}

		if ( isset( $params['tracking']['tr_help_url'] ) ) {
			$tracking['tr_help_url'] = $params['tracking']['tr_help_url'];
		}

		if ( isset( $params['tracking']['tr_help_tel'] ) ) {
			$tracking['tr_help_tel'] = $params['tracking']['tr_help_tel'];
		}

		if ( isset( $params['tracking']['tr_help_txt'] ) ) {
			$tracking['tr_help_txt'] = $this->purify_html( $params['tracking']['tr_help_txt'] );
		}

		return JsonUtil::fast_events_json_encode( $tracking );
	}


	/**
	 * Delete a single event.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
	 *
	 * @since 1.0
	 * @since 1.4 Event authorization restriction
	 */
	public function delete_item( $request ): WP_Error|WP_REST_Response {
		global $wpdb;

		// Check the event authorization.
		$resp = $this->auth->check_event_authorization( absint( $request['id'] ) );
		if ( is_wp_error( $resp ) ) {
			return $resp;
		}

		// Look up the event.
		$event = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}fe_events WHERE id = %d", $request['id'] ) );
		if ( empty( $event ) ) {
			return new WP_Error( 'not_found', __( 'Event not found', 'fast-events' ), array( 'status' => 404 ) );
		}

		$request->set_param( 'context', 'edit' );

		$previous = $this->prepare_item_for_response( $event, $request );

		// Delete the data.
		$result = $this->events_helper->fast_events_event_delete_helper( $request, true );
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		$response = new WP_REST_Response();
		$response->set_data(
			array(
				'deleted'  => true,
				'previous' => $previous->get_data(),
			)
		);

		return $response;
	}


	/**
	 * Prepares a single event output for response.
	 *
	 * @param mixed           $item Event object.
	 * @param WP_REST_Request $request Request object.
	 *
	 * @return WP_REST_Response|WP_Error Response object.
	 *
	 * @since 1.0
	 * @since 2.2.0 Added 'coupons_needed'
	 */
	public function prepare_item_for_response( $item, $request ): WP_Error|WP_REST_Response {

		$data   = array();
		$fields = $this->get_fields_for_response( $request );

		// Get seats configuration.
		$seats_config = array();
		$seats        = $this->seats->get_entry_for_event( (int) $item->id );
		if ( is_wp_error( $seats ) ) {
			return $seats;
		}
		$seats_config['number']       = (int) $seats->num_seats;
		$seats_config['format']       = $seats->seat_format;
		$seats_config['config']       = $seats->seat_config;
		$seats_config['linked_event'] = (int) $seats->linked_event;

		$uniq   = '';
		$group  = array();
		$submit = '';
		$input  = json_decode( $item->input_fields );
		if ( null !== $input ) {
			$submit = $input->submit->name;
			$uniq   = $input->unique_users->master_eventids;

			// User group info.
			$group_type          = (int) $input->user_group->id;
			$group['group_type'] = $group_type;
			if ( 1 === $group_type ) {
				$group['wordpress_roles'] = '' !== $input->user_group->roles ? explode( ',', $input->user_group->roles ) : array();
			} elseif ( 2 === $group_type ) {
				if ( '' !== $input->user_group->eventid ) {
					$group['event_id'] = (int) $input->user_group->eventid;
				}
			} elseif ( 3 === $group_type ) {
				$group['rest_header'] = $input->user_group->rest_header;
				$group['rest_url']    = $input->user_group->rest_url;
			}
		}

		// Set pdf fields.
		$pdf      = array();
		$pdf_info = json_decode( $item->pdf_info );
		if ( null !== $pdf_info ) {
			$this->attachment_ids[] = (int) $pdf_info->ticket->id;
			$this->attachment_ids[] = (int) $pdf_info->invoice->id;

			$pdf = array(
				'ticket'  => array(
					'attachment_id' => (int) $pdf_info->ticket->id,
					'x_position'    => (int) $pdf_info->ticket->x,
					'y_position'    => (int) $pdf_info->ticket->y,
					'rotation'      => (int) $pdf_info->ticket->rotate,
					'scale'         => isset( $pdf_info->ticket->scale ) ? (int) $pdf_info->ticket->scale : 100,
					'no_border'     => isset( $pdf_info->ticket->no_border ) && ! ( 0 === (int) $pdf_info->ticket->no_border ),
				),
				'invoice' => array(
					'attachment_id'           => (int) $pdf_info->invoice->id,
					'use_vat'                 => 1 === (int) $pdf_info->invoice->vat,
					'name_position'           => array(
						'x_position' => (int) $pdf_info->invoice->name->x,
						'y_position' => (int) $pdf_info->invoice->name->y,
					),
					'invoice_number_position' => array(
						'x_position' => (int) $pdf_info->invoice->invoiceno->x,
						'y_position' => (int) $pdf_info->invoice->invoiceno->y,
					),
					'first_line_position'     => array(
						'x_position' => (int) $pdf_info->invoice->line->x,
						'y_position' => (int) $pdf_info->invoice->line->y,
						'line_width' => (int) $pdf_info->invoice->line->w,
					),
				),
			);
		}

		// Tracking info.
		$tracking      = array();
		$tracking_info = json_decode( $item->tracking_info );
		if ( null !== $tracking_info ) {
			$tracking = array(
				'start_tracking'     => $tracking_info->start_tracking ?? null,
				'stop_tracking'      => $tracking_info->stop_tracking ?? null,
				'geofence_radius'    => $tracking_info->geofence_radius ?? 200,
				'distance_filter'    => $tracking_info->distance_filter ?? 10,
				'no_entry_scan'      => $tracking_info->no_entry_scan ?? false,
				'force_tracking_app' => $tracking_info->force_tracking_app ?? false,
				'tr_help_url'        => $tracking_info->tr_help_url ?? home_url(),
				'tr_help_tel'        => $tracking_info->tr_help_tel ?? '',
				'tr_help_txt'        => $tracking_info->tr_help_txt ?? '',
			);
			$tracks   = array();
			if ( isset( $tracking_info->tracks ) ) {
				foreach ( $tracking_info->tracks as $track ) {
					if ( isset( $track->name ) ) {
						$tracks[] = $track->name;
					}
				}
			}
			$tracking['tracks'] = $tracks;
		}

		if ( rest_is_field_included( 'id', $fields ) ) {
			$data['id'] = (int) $item->id;
		}

		if ( rest_is_field_included( 'event_name', $fields ) ) {
			$data['event_name'] = $item->event_name;
		}

		if ( rest_is_field_included( 'event_date', $fields ) ) {
			$data['event_date'] = $item->event_date;
		}

		if ( rest_is_field_included( 'event_date_format', $fields ) ) {
			$data['event_date_format'] = $item->event_date_format;
		}

		if ( rest_is_field_included( 'start_date', $fields ) ) {
			$data['start_date'] = $item->start_date;
		}

		if ( rest_is_field_included( 'end_date', $fields ) ) {
			$data['end_date'] = $item->end_date;
		}

		if ( rest_is_field_included( 'event_type', $fields ) ) {
			$data['event_type'] = (int) $item->event_type;
		}

		if ( rest_is_field_included( 'stock', $fields ) ) {
			$data['stock'] = (int) $item->stock;
		}

		if ( rest_is_field_included( 'sold', $fields ) ) {
			$data['sold'] = (int) $item->sold;
		}

		if ( rest_is_field_included( 'stock_link', $fields ) ) {
			$data['stock_link'] = (int) $item->stock_link;
		}

		if ( $this->settings->saas_mode() ) {
			if ( rest_is_field_included( 'saas_fee', $fields ) ) {
				$data['saas_fee'] = is_null( $item->saas_fee ) ? '' : (float) $item->saas_fee;
			}

			if ( rest_is_field_included( 'saas_user_id', $fields ) ) {
				$data['saas_user_id'] = (int) $item->saas_user_id;
			}
		}

		if ( rest_is_field_included( 'group_type', $fields ) ) {
			$data['group_type'] = (int) $item->group_type;
		}

		if ( rest_is_field_included( 'event_group', $fields ) ) {
			$data['event_group'] = $item->event_group;
		}

		if ( rest_is_field_included( 'redirect', $fields ) ) {
			$data['redirect'] = $item->redirect;
		}

		if ( rest_is_field_included( 'email', $fields ) ) {
			$email                 = array();
			$email['sender_name']  = $item->sender_name;
			$email['sender_email'] = $item->sender_email;
			$email['bcc']          = $item->email_bcc;
			$email['subject']      = $item->email_subject;
			$email['body']         = $item->email_body;
			$data['email']         = $email;
		}

		if ( rest_is_field_included( 'email_confirmation', $fields ) ) {
			$email                      = array();
			$email['bcc']               = $item->confirm_bcc;
			$email['subject']           = $item->confirm_subject;
			$email['body']              = $item->confirm_body;
			$email['redirect']          = $item->confirm_redirect;
			$data['email_confirmation'] = $email;
		}

		if ( rest_is_field_included( 'emails_needed', $fields ) ) {
			$data['emails_needed'] = 1 === (int) $item->emails_needed;
		}

		if ( rest_is_field_included( 'tickets_needed', $fields ) ) {
			$data['tickets_needed'] = 1 === (int) $item->tickets_needed;
		}

		if ( rest_is_field_included( 'invoice_needed', $fields ) ) {
			$data['invoice_needed'] = 1 === (int) $item->invoice_needed;
		}

		if ( rest_is_field_included( 'unique_users_needed', $fields ) ) {
			$data['unique_users_needed'] = 1 === (int) $item->unique_users_needed;
		}

		if ( rest_is_field_included( 'unique_event_ids', $fields ) ) {
			$data['unique_event_ids'] = $uniq;
		}

		if ( rest_is_field_included( 'user_groups_needed', $fields ) ) {
			$data['user_groups_needed'] = 1 === (int) $item->user_groups_needed;
		}

		if ( rest_is_field_included( 'recaptcha_needed', $fields ) ) {
			$data['recaptcha_needed'] = 1 === (int) $item->recaptcha_needed;
		}

		if ( rest_is_field_included( 'confirmation_emails_needed', $fields ) ) {
			$data['confirmation_emails_needed'] = 1 === (int) $item->confirmation_emails_needed;
		}

		if ( rest_is_field_included( 'confirmation_timeout', $fields ) ) {
			$data['confirmation_timeout'] = (int) $item->confirmation_timeout;
		}

		if ( rest_is_field_included( 'add_dashboard_orders_needed', $fields ) ) {
			$data['add_dashboard_orders_needed'] = 1 === (int) $item->add_dashboard_orders_needed;
		}

		if ( rest_is_field_included( 'test_payments_needed', $fields ) ) {
			$data['test_payments_needed'] = 1 === (int) $item->test_payments_needed;
		}

		if ( rest_is_field_included( 'seats_needed', $fields ) ) {
			$data['seats_needed'] = 1 === (int) $item->seats_needed;
		}

		if ( rest_is_field_included( 'webhooks_needed', $fields ) ) {
			$data['webhooks_needed'] = 1 === (int) $item->webhooks_needed;
		}

		if ( rest_is_field_included( 'reload_on_exit_needed', $fields ) ) {
			$data['reload_on_exit_needed'] = 1 === (int) $item->reload_on_exit_needed;
		}

		if ( rest_is_field_included( 'tracking_needed', $fields ) ) {
			$data['tracking_needed'] = 1 === (int) $item->tracking_needed;
		}

		if ( rest_is_field_included( 'coupons_needed', $fields ) ) {
			$data['coupons_needed'] = 1 === (int) $item->coupons_needed;
		}

		if ( rest_is_field_included( 'terms', $fields ) ) {
			$data['terms'] = $item->terms;
		}

		if ( rest_is_field_included( 'pdf_fields', $fields ) ) {
			$data['pdf_fields'] = $pdf;
		}

		if ( rest_is_field_included( 'order_submit_text', $fields ) ) {
			$data['order_submit_text'] = $submit;
		}

		if ( rest_is_field_included( 'user_groups', $fields ) ) {
			$data['user_groups'] = $group;
		}

		if ( rest_is_field_included( 'seats', $fields ) ) {
			$data['seats'] = $seats_config;
		}

		if ( rest_is_field_included( 'tracking', $fields ) ) {
			$data['tracking'] = $tracking;
		}
		$context = ! empty( $request['context'] ) ? $request['context'] : 'embed';

		$data = $this->add_additional_fields_to_object( $data, $request );
		$data = $this->filter_response_by_context( $data, $context );

		// Wrap the data in a response object.
		$response = rest_ensure_response( $data );

		if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
			$response->add_links( $this->prepare_links( $item ) );
		}

		return $response;
	}


	/**
	 * Prepares links for the event request.
	 *
	 * @param stdClass $event Event object.
	 * @return array Links for the given event.
	 *
	 * @since 1.0
	 */
	protected function prepare_links( stdClass $event ): array {
		$links = array(
			'self'         => array(
				'href' => rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $event->id ) ),
			),
			'collection'   => array(
				'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
			),
			'input_fields' => array(
				'embeddable' => true,
				'href'       => rest_url( sprintf( '%s/admin/events/%d/input-fields', $this->namespace, $event->id ) ),
			),
			'ticket_types' => array(
				'embeddable' => true,
				'href'       => rest_url( sprintf( '%s/admin/events/%d/ticket-types', $this->namespace, $event->id ) ),
			),
			'scan_keys'    => array(
				'embeddable' => true,
				'href'       => rest_url( sprintf( '%s/admin/events/%d/scan-keys', $this->namespace, $event->id ) ),
			),
			'email_list'   => array(
				'embeddable' => true,
				'href'       => rest_url( sprintf( '%s/admin/emaillists/%d', $this->namespace, $event->id ) ),
			),
			'sales_totals' => array(
				'embeddable' => true,
				'href'       => rest_url( sprintf( '%s/admin/events/%d/sales', $this->namespace, $event->id ) ),
			),
			'scan_totals'  => array(
				'embeddable' => true,
				'href'       => rest_url( sprintf( '%s/admin/events/%d/scans', $this->namespace, $event->id ) ),
			),
		);

		$ids = array_diff( array_unique( $this->attachment_ids ), array( 0 ) );
		if ( 0 < count( $ids ) ) {
			$media = array();
			foreach ( $ids as $id ) {
				$media[] = array(
					'href'       => rest_url( 'wp/v2/media/' . $id ),
					'embeddable' => true,
				);
			}
			$links['wp:attachment'] = $media;
		}

		return $links;
	}


	/**
	 * Retrieves the query params for event collections.
	 *
	 * @return array
	 *
	 * @since 1.0
	 */
	public function get_collection_params(): array {
		$query_params = parent::get_collection_params();

		$query_params['context']['default'] = 'view';

		$query_params['exclude'] = array(
			'description' => __( 'Ensure result set excludes specific IDs.' ),
			'type'        => 'array',
			'items'       => array(
				'type' => 'integer',
			),
			'default'     => array(),
		);

		$query_params['include'] = array(
			'description' => __( 'Limit result set to specific IDs.' ),
			'type'        => 'array',
			'items'       => array(
				'type' => 'integer',
			),
			'default'     => array(),
		);

		$query_params['offset'] = array(
			'description' => __( 'Offset the result set by a specific number of items.' ),
			'type'        => 'integer',
		);

		$query_params['order'] = array(
			'default'     => 'asc',
			'description' => __( 'Order sort attribute ascending or descending.' ),
			'enum'        => array( 'asc', 'desc' ),
			'type'        => 'string',
		);

		$query_params['orderby'] = array(
			'default'     => 'id',
			'description' => __( 'Sort collection by object attribute.' ),
			'enum'        => array(
				'id',
				'start_date',
				'end_date',
				'event_date',
			),
			'type'        => 'string',
		);

		return $query_params;
	}


	/**
	 * Return the events' schema.
	 *
	 * @return array
	 * @since 1.4.0 Added saas_fee, saas_user_id, sender_name and sender_email to query
	 * @since 2.0.0 Corrected terms field type
	 * @since 2.2.0 Added 'coupons_needed'
	 *
	 * @since 1.0
	 */
	public function get_item_schema(): array {
		if ( $this->schema ) {
			return $this->add_additional_fields_schema( $this->schema );
		}

		$this->schema = array(
			'$schema'              => 'http://json-schema.org/draft-04/schema#',
			'title'                => 'events',
			'type'                 => 'object',
			'additionalProperties' => false,
			'properties'           => array(
				'id'                          => array(
					'description' => __( 'The unique id of the event.', 'fast-events' ),
					'context'     => array( 'view' ),
					'type'        => 'integer',
					'readonly'    => true,
				),
				'event_name'                  => array(
					'description' => __( 'The name of the event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'minLength'   => 1,
					'maxLength'   => 50,
					'required'    => true,
				),
				'event_date'                  => array(
					'description' => __( 'The date of the event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'format'      => 'date-time',
					'default'     => wp_date( 'Y-m-d', TimeUtil::local_time() + ( DAY_IN_SECONDS * 14 ) ) . ' 14:00:00',
				),
				'event_date_format'           => array(
					'description' => __( 'The format of the date.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'maxLength'   => 32,
					'default'     => 'Y-m-d H:i',
				),
				'start_date'                  => array(
					'description' => __( 'Start date for selling tickets.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'format'      => 'date-time',
					'default'     => wp_date( 'Y-m-d' ) . ' 00:00:00',
				),
				'end_date'                    => array(
					'description' => __( 'End date for selling tickets.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'format'      => 'date-time',
					'default'     => wp_date( 'Y-m-d', TimeUtil::local_time() + ( DAY_IN_SECONDS * 14 ) ) . ' 14:00:00',
				),
				'event_type'                  => array(
					'description' => __( 'The type of event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'integer',
					'enum'        => array( 0, 1 ),
					'default'     => 1,
				),
				'stock'                       => array(
					'description' => __( 'The stock of the event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'integer',
					'minimum'     => 0,
					'default'     => 0,
				),
				'sold'                        => array(
					'description' => __( 'The number of tickets sold.', 'fast-events' ),
					'context'     => array( 'view' ),
					'type'        => 'integer',
					'readonly'    => true,
				),
				'stock_link'                  => array(
					'description' => __( 'The event-id of the linked event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'integer',
					'minimum'     => 0,
					'default'     => 0,
				),
				'saas_fee'                    => array(
					'description' => __( 'The fee charged by the seller.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => array( 'null', 'number' ),
					'default'     => null,
				),
				'saas_user_id'                => array(
					'description' => __( 'The user-id for usage of SaaS.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'integer',
					'minimum'     => 0,
					'default'     => 0,
				),
				'group_type'                  => array(
					'description' => __( 'The group-type of event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'integer',
					'enum'        => array( 0, 1, 2, 3 ),
					'default'     => 0,
				),
				'event_group'                 => array(
					'description' => __( 'The group-name the event belongs to.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'maxLength'   => 16,
					'default'     => '',
				),
				'redirect'                    => array(
					'description' => __( 'Redirect URL after a successful order.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'format'      => 'uri',
					'maxLength'   => 256,
					'default'     => home_url(),
				),
				'email'                       => array(
					'description' => __( 'Email send after a successful order.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'object',
					'properties'  => array(
						'sender_name'  => array(
							'description' => __( 'Sender name.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'maxLength'   => 100,
							'default'     => '',
						),
						'sender_email' => array(
							'description' => __( 'Sender email.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'maxLength'   => 100,
							'default'     => '',
						),
						'bcc'          => array(
							'description' => __( 'BCC email address.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'maxLength'   => 100,
							'default'     => '',
						),
						'subject'      => array(
							'description' => __( 'Subject of the email.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'maxLength'   => 100,
							'default'     => '',
						),
						'body'         => array(
							'description' => __( 'Body of the email.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'default'     => '',
						),
					),
				),
				'email_confirmation'          => array(
					'description' => __( 'Email confirmation.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'object',
					'properties'  => array(
						'bcc'      => array(
							'description' => __( 'BCC email address.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'maxLength'   => 100,
							'default'     => '',
						),
						'subject'  => array(
							'description' => __( 'Subject of the email.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'maxLength'   => 100,
							'default'     => '',
						),
						'body'     => array(
							'description' => __( 'Body of the email.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'default'     => '',
						),
						'redirect' => array(
							'description' => __( 'Redirect URL after confirmation.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'maxLength'   => 256,
							'default'     => '',
						),
					),
				),
				'emails_needed'               => array(
					'description' => __( 'Does the event uses emails.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => true,
				),
				'tickets_needed'              => array(
					'description' => __( 'Does the event uses tickets.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => true,
				),
				'invoice_needed'              => array(
					'description' => __( 'Does the event uses invoices.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => true,
				),
				'unique_users_needed'         => array(
					'description' => __( 'Can users only place a single order', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'unique_event_ids'            => array(
					'description' => __( 'String of event_ids separated by a comma', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => array( 'string', 'null' ),
					'pattern'     => '^(\d+(\\,\d+)*)*$',
				),
				'user_groups_needed'          => array(
					'description' => __( 'Does the event uses user groups.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'recaptcha_needed'            => array(
					'description' => __( 'Does the event uses Google ReCaptcha to protect order input.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'confirmation_emails_needed'  => array(
					'description' => __( 'Does the event uses confirmation emails.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'confirmation_timeout'        => array(
					'description' => __( 'Time in minutes before the reservation is deleted.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'integer',
					'minimum'     => 0,
					'default'     => 0,
				),
				'add_dashboard_orders_needed' => array(
					'description' => __( 'New order created in the orders dashboard.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => true,
				),
				'test_payments_needed'        => array(
					'description' => __( 'Are test payments used.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => true,
				),
				'seats_needed'                => array(
					'description' => __( 'Is a seating plan used.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'webhooks_needed'             => array(
					'description' => __( 'Does the event uses webhooks.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'reload_on_exit_needed'       => array(
					'description' => __( 'Increase stock if someone leaves event.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'tracking_needed'             => array(
					'description' => __( 'Does the event support the FE Tracking App.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'coupons_needed'              => array(
					'description' => __( 'Does the event support discount codes.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'boolean',
					'default'     => false,
				),
				'terms'                       => array(
					'description' => __( 'Text for terms and conditions.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => array( 'null', 'string' ),
					'maxLength'   => 256,
					'default'     => '',
				),
				'pdf_fields'                  => array(
					'description' => __( 'PDF fields for creating tickets and invoices.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'object',
					'properties'  => array(
						'ticket'  => array(
							'description' => __( 'PDF ticket fields.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'object',
							'properties'  => array(
								'attachment_id' => array(
									'description' => __( 'Media id used as PDF template.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'integer',
									'default'     => 0,
								),
								'x_position'    => array(
									'description' => __( 'X-position of the qrcode block.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'integer',
									'default'     => 13,
								),
								'y_position'    => array(
									'description' => __( 'Y-position of the qrcode block.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'integer',
									'default'     => 58,
								),
								'rotation'      => array(
									'description' => __( 'Rotation degrees of the qrcode block.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'integer',
									'default'     => 0,
								),
								'scale'         => array(
									'description' => __( 'Scaling percentage of the qrcode-block.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'integer',
									'default'     => 100,
								),
								'no_border'     => array(
									'description' => __( 'Borderline around qrcode-block.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'boolean',
									'default'     => false,
								),
							),
						),
						'invoice' => array(
							'description' => __( 'PDF invoice fields.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'object',
							'properties'  => array(
								'attachment_id'           => array(
									'description' => __( 'Media id used as PDF template.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'integer',
									'default'     => 0,
								),
								'use_vat'                 => array(
									'description' => __( 'Use VAT lines in the invoice.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'boolean',
									'default'     => false,
								),
								'name_position'           => array(
									'description' => __( 'Position of the name.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'object',
									'properties'  => array(
										'x_position' => array(
											'description' => __( 'X-position of the name.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 27,
										),
										'y_position' => array(
											'description' => __( 'Y-position of the name.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 60,
										),
									),
								),
								'invoice_number_position' => array(
									'description' => __( 'Position of the invoice number.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'object',
									'properties'  => array(
										'x_position' => array(
											'description' => __( 'X-position of the invoice number.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 127,
										),
										'y_position' => array(
											'description' => __( 'Y-position of the invoice number.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 65,
										),
									),
								),
								'first_line_position'     => array(
									'description' => __( 'Position of the first detailed invoice line.', 'fast-events' ),
									'context'     => array( 'view', 'edit' ),
									'type'        => 'object',
									'properties'  => array(
										'x_position' => array(
											'description' => __( 'X-position of the first detailed invoice line.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 25,
										),
										'y_position' => array(
											'description' => __( 'Y-position of the first detailed invoice line.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 92,
										),
										'line_width' => array(
											'description' => __( 'Line width of a detailed invoice line.', 'fast-events' ),
											'context'     => array( 'view', 'edit' ),
											'type'        => 'integer',
											'default'     => 158,
										),
									),
								),
							),
						),
					),
				),
				'order_submit_text'           => array(
					'description' => __( 'Label-text for submitting a new order.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'string',
					'maxLength'   => 32,
					'default'     => __( 'Pay', 'fast-events' ),
				),
				'user_groups'                 => array(
					'description' => __( 'User group information.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'object',
					'properties'  => array(
						'group_type'      => array(
							'description' => __( 'The type of user group.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'integer',
							'enum'        => array( 0, 1, 2, 3 ),
							'default'     => 0,
						),
						'event_id'        => array(
							'description' => __( 'The unique id of the event.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
						'wordpress_roles' => array(
							'description' => __( 'The roles the user should belong to.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
						'rest_url'        => array(
							'description' => __( 'The REST URL to verify if order is allowed.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
						'rest_header'     => array(
							'description' => __( 'The HTTP header used by the REST URL.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
					),
				),
				'seats'                       => array(
					'description' => __( 'Seatingplan information.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'object',
					'properties'  => array(
						'number'       => array(
							'description' => __( 'The total number of seats available.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'integer',
							'minimum'     => 0,
							'default'     => 0,
						),
						'format'       => array(
							'description' => __( 'Print format appended to ticket type in qrcode block.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'maxLength'   => 32,
							'default'     => ", row %s table %'02d",
						),
						'config'       => array(
							'description' => __( 'The seats configuration string.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'maxLength'   => 16777215,
							'default'     => '',
						),
						'linked_event' => array(
							'description' => __( 'The linked event for seats reservation.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'integer',
							'minimum'     => 0,
							'default'     => 0,
						),
					),
				),
				'tracking'                    => array(
					'description' => __( 'Tracking information.', 'fast-events' ),
					'context'     => array( 'view', 'edit' ),
					'type'        => 'object',
					'properties'  => array(
						'start_tracking'     => array(
							'description' => __( 'The start time the App can use tracking.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'format'      => 'date-time',
							'default'     => wp_date( 'Y-m-d' ) . ' 00:00:00',
						),
						'stop_tracking'      => array(
							'description' => __( 'The end time the App can use tracking.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'string',
							'format'      => 'date-time',
							'default'     => wp_date( 'Y-m-d' ) . ' 23:00:00',
						),
						'geofence_radius'    => array(
							'description' => __( 'The radius in meters around a checkpoint.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'integer',
							'minimum'     => 0,
							'default'     => 200,
						),
						'distance_filter'    => array(
							'description' => __( 'Triggers a location update after travelling this distance.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'integer',
							'minimum'     => 0,
							'default'     => 10,
						),
						'no_entry_scan'      => array(
							'description' => __( 'Is an entry scan needed.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'boolean',
							'default'     => false,
						),
						'force_tracking_app' => array(
							'description' => __( 'Force the usage of the Tracking App.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => 'boolean',
							'default'     => false,
						),
						'tr_help_url'        => array(
							'description' => __( 'The information URL for dynamic information.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
						'tr_help_tel'        => array(
							'description' => __( 'The emergency phone number.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
						'tr_help_txt'        => array(
							'description' => __( 'Help text.', 'fast-events' ),
							'context'     => array( 'view', 'edit' ),
							'type'        => array( 'null', 'string' ),
							'default'     => '',
						),
						'tracks'             => array(
							'description' => __( 'List of track names.', 'fast-events' ),
							'context'     => array( 'view' ),
							'type'        => 'array',
							'items'       => array(
								'type' => 'string',
							),
						),
					),
				),
			),
		);

		return $this->add_additional_fields_schema( $this->schema );
	}
}
