<?php
/**
 * Event post type registration and management.
 *
 * @package EventimUSEventListings
 */

defined( 'ABSPATH' ) || exit;

/**
 * Register Eventim US event post type.
 *
 * @return void
 */
function evusel_init_post_type() {
	global $evuselConfig;

	if ( ! isset( $evuselConfig ) || ! is_object( $evuselConfig ) ) {
		if ( ! isset( $GLOBALS['evuselConfig'] ) ) {
			return;
		}
		$evuselConfig = $GLOBALS['evuselConfig'];
	}

	$linkTitleAndImageTo = $evuselConfig->get( 'link_title_and_image_to' );

	register_post_type(
		'seetickets-event',
		array(
			'labels'             => array(
				'name'               => __( 'Eventim US Events', 'eventim-us-event-listings' ),
				'singular_name'      => __( 'Eventim US Event', 'eventim-us-event-listings' ),
				'menu_name'          => __( 'Eventim US Events', 'eventim-us-event-listings' ),
				'name_admin_bar'     => _x( 'Eventim US Event', 'Add New on Toolbar', 'eventim-us-event-listings' ),
				'add_new_item'       => __( 'Add New Event', 'eventim-us-event-listings' ),
				'add_new'            => __( 'Add New Event', 'eventim-us-event-listings' ),
				'new_item'           => __( 'New Eventim US Event', 'eventim-us-event-listings' ),
				'edit_item'          => __( 'Edit Event', 'eventim-us-event-listings' ),
				'new_item'           => __( 'New Event', 'eventim-us-event-listings' ),
				'view_item'          => __( 'View Event', 'eventim-us-event-listings' ),
				'search_items'       => __( 'Search Event', 'eventim-us-event-listings' ),
				'all_items'          => __( 'All Events', 'eventim-us-event-listings' ),
				'parent_item_colon'  => __( 'Parent Events:', 'eventim-us-event-listings' ),
				'not_found'          => __( 'No events found.', 'eventim-us-event-listings' ),
				'not_found_in_trash' => __( 'No events found in Trash.', 'eventim-us-event-listings' ),

				// 'featured_image'        => _x( 'See Tickets Event Cover Image', 'Overrides the "Featured Image" phrase for this post type.', 'seetickets' ),
				// 'set_featured_image'    => _x( 'Set cover image', 'Overrides the "Set featured image" phrase for this post type. Added in 4.3', 'recipe' ),
				// 'remove_featured_image' => _x( 'Remove cover image', 'Overrides the "Remove featured image" phrase for this post type. Added in 4.3', 'recipe' ),
				// 'use_featured_image'    => _x( 'Use as cover image', 'Overrides the "Use as featured image" phrase for this post type. Added in 4.3', 'recipe' ),
				// 'archives'              => _x( 'Recipe archives', 'The post type archive label used in nav menus. Default "Post Archives". Added in 4.4', 'recipe' ),
				// 'insert_into_item'      => _x( 'Insert into recipe', 'Overrides the "Insert into post"/"Insert into page" phrase (used when inserting media into a post). Added in 4.4', 'recipe' ),
				// 'uploaded_to_this_item' => _x( 'Uploaded to this recipe', 'Overrides the "Uploaded to this post"/"Uploaded to this page" phrase (used when viewing media attached to a post). Added in 4.4', 'recipe' ),
				// 'filter_items_list'     => _x( 'Filter recipes list', 'Screen reader text for the filter links heading on the post type listing screen. Default "Filter posts list"/"Filter pages list". Added in 4.4', 'recipe' ),
				// 'items_list_navigation' => _x( 'Recipes list navigation', 'Screen reader text for the pagination heading on the post type listing screen. Default "Posts list navigation"/"Pages list navigation". Added in 4.4', 'recipe' ),
				// 'items_list'            => _x( 'Recipes list', 'Screen reader text for the items list heading on the post type listing screen. Default "Posts list"/"Pages list". Added in 4.4', 'recipe' ),

			),
			'public'             => true,
			'has_archive'        => true,
			'hierarchial'        => true,
			'menu_icon'          => 'dashicons-calendar-alt',
			'supports'           => array( 'title', 'author', 'editor' ),
			'menu_position'      => 30,
			'show_in_rest'       => $linkTitleAndImageTo === 'postpage',
			'publicly_queryable' => $linkTitleAndImageTo === 'postpage',

			// 'capability_type'    => 'post',
			// 'rewrite'            => array( 'slug' => 'seetickets-events' ), // my custom slug
			// 'description'        => 'Recipe custom post type.',
			// 'show_ui'            => true,
			// 'show_in_menu'       => true,
			// 'query_var'          => true,
			// 'taxonomies'         => array( 'category', 'post_tag' ),
		)
	);
}
add_action( 'init', 'evusel_init_post_type' );
add_post_type_support( 'seetickets-event', 'thumbnail' );

/**
 * Register categories for Eventim US Events
 *
 * @return void
 */
function evusel_init_event_categories() {
	register_taxonomy(
		'seetickets-event-category',
		array(
			'seetickets-event',
		),
		array(
			'hierarchical'      => true,
			'label'             => 'Categories',
			'singular_label'    => 'Category',
			'rewrite'           => array(
				'slug'       => 'categories',
				'with_front' => false,
			),
			'show_admin_column' => true,
		)
	);
}
add_action( 'init', 'evusel_init_event_categories' );

/**
 * Register tags for Eventim US Events
 *
 * @return void
 */
function evusel_init_event_tags() {
	register_taxonomy(
		'seetickets-event-tag',
		array(
			'seetickets-event',
		),
		array(
			'hierarchical'          => false,
			'label'                 => 'Tags',
			'show_ui'               => true,
			'update_count_callback' => '_update_post_term_count',
			'query_var'             => true,
			'rewrite'               => array(
				'slug' => 'tag',
			),
			'show_admin_column'     => true,
		)
	);
}
add_action( 'init', 'evusel_init_event_tags' );

/**
 * Add extra columns to admin table.
 *
 * @param array $columns Columns array.
 * @return void
 */
function evusel_add_event_columns( $columns ) {
	$modifiedColumns = array();
	foreach ( $columns as $key => $column ) {
		$modifiedColumns[ $key ] = $column;
		if ( $key === 'title' ) {
			$modifiedColumns['sort_date']   = 'Sort Date';
			$modifiedColumns['event_time']  = 'Event Time';
			$modifiedColumns['is_multiday'] = 'Multiday Event';
		}
	}

	unset( $modifiedColumns['date'] );
	$modifiedColumns['see_publish_date'] = 'Publish Date';

	return $modifiedColumns;
}
add_filter( 'manage_seetickets-event_posts_columns', 'evusel_add_event_columns' );

/**
 * Add content to custom columns.
 *
 * @param string $column_key Column key.
 * @param int    $post_id    Post ID.
 * @return void
 */
function evusel_add_content_to_custom_columns( $column_key, $post_id ) {
	$displayDateTime = evusel_get_event_display_date_time( $post_id );
	$isMultiday      = get_post_meta( $post_id, 'is_multiday', true );

	if ( $column_key == 'sort_date' && ! empty( $displayDateTime ) ) {
		$displayDateTime = esc_attr( $displayDateTime->format( 'm/d/Y' ) );
		echo esc_attr( $displayDateTime );
	}

	if ( $column_key == 'event_time' && ! empty( $displayDateTime ) ) {
		echo esc_attr( $isMultiday ? '' : $displayDateTime->format( 'g:i A' ) );
	}
	if ( $column_key == 'is_multiday' ) {
		global $post;
		$echo  = $isMultiday ? 'Yes' : 'No';
		$echo .= ! empty( $post->post_parent ) ? ' (repeating of ' . get_the_title( $post->post_parent ) . ')' : '';
		echo esc_attr( $echo );
	}

	if ( $column_key === 'see_publish_date' ) {
		$publishDateTime = evusel_get_event_display_publish_date_time( $post_id );
		if ( ! empty( $publishDateTime ) ) {
			echo esc_attr( $publishDateTime->format( 'm/d/Y g:i A' ) );
		}
	}
}
add_action( 'manage_seetickets-event_posts_custom_column', 'evusel_add_content_to_custom_columns', 10, 2 );

/**
 * Make custom columns sortable.
 *
 * @param array $columns Columns array.
 * @return void
 */
function evusel_set_custom_seetickets_events_sortable_columns( $columns ) {
	$columns['sort_date'] = 'sort_date';
	return $columns;
}
add_filter( 'manage_edit-seetickets-event_sortable_columns', 'evusel_set_custom_seetickets_events_sortable_columns' );

/**
 * Custom columns sort logic.
 *
 * @param WP_Query $query WP_Query object.
 * @return void
 */
function evusel_events_custom_orderby( $query ) {
	if ( is_admin() && 'sort_date' == $query->get( 'orderby' ) ) {
		$query->set( 'meta_key', 'sort_date' );
		$query->set( 'orderby', 'meta_value' );
	}
}
add_action( 'pre_get_posts', 'evusel_events_custom_orderby' );

/**
 * Construct the DateTime object for displaying the events.
 *
 * @param int    $post_id Post ID.
 * @param string $timeType Time type.
 * @return DateTime|string DateTime object or empty string.
 */
function evusel_get_event_display_date_time( $post_id, $timeType = 'event' ) {
	$metaKey             = $timeType . '_time';
	$eventDateTimeString = get_post_meta( $post_id, $metaKey, true );

	if ( ! empty( $eventDateTimeString ) ) {

		$eventDateTime = DateTime::createFromFormat( 'Y-m-d H:i:s', $eventDateTimeString, new DateTimeZone( 'UTC' ) );
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
		$acfTimezoneField = isset( $_POST['acf']['field_63696f6ebdb4e'] ) ? sanitize_text_field( wp_unslash( $_POST['acf']['field_63696f6ebdb4e'] ) ) : '';
		$displayTimeZone  = current_action() === 'editpost' && ! empty( $acfTimezoneField ) ? $acfTimezoneField : get_post_meta( $post_id, 'ianaTimezone', true );

		if ( ! empty( $displayTimeZone ) && ! empty( $eventDateTime ) && in_array( $displayTimeZone, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ) {
			$displayTimeZone = new DateTimeZone( $displayTimeZone );
			$eventDateTime->setTimezone( $displayTimeZone );
		}

		return $eventDateTime;
	}

	return '';
}

/**
 * Construct the DateTime object for displaying the publish date.
 *
 * @param int $post_id Post ID.
 * @return DateTime|string DateTime object or empty string.
 * @since 0.18.0
 */
function evusel_get_event_display_publish_date_time( $post_id ) {
	$eventPublishDateString = get_field( 'publish_date', $post_id );

	if ( ! empty( $eventPublishDateString ) ) {

		$eventPublishDateTime = DateTime::createFromFormat( 'Y-m-d H:i:s', $eventPublishDateString, new DateTimeZone( 'UTC' ) );
		$displayTimeZone      = get_post_meta( $post_id, 'ianaTimezone', true );

		if ( ! empty( $displayTimeZone && ! empty( $eventPublishDateTime ) && in_array( $displayTimeZone, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ) ) {
			$displayTimeZone = new DateTimeZone( $displayTimeZone );
			$eventPublishDateTime->setTimezone( $displayTimeZone );
		}

		return $eventPublishDateTime;
	}
	return '';
}

/**
 * Get event offsale display date time.
 *
 * @param int $post_id Post ID.
 * @return DateTime|string DateTime object or empty string.
 * @since 0.25.0b
 */
function evusel_see_get_event_offsale_display_date_time( $post_id ) {
	$offsaleDateTimeString = get_post_meta( $post_id, 'offsale_date_and_time', true );
	$wantFormat            = new DateTime( $offsaleDateTimeString, new DateTimeZone( 'UTC' ) );
	$formattedDate         = $wantFormat->format( 'Y-m-d H:i:s' );
	if ( ! empty( $formattedDate ) ) {
		$eventDateTimeZoneString = get_post_meta( $post_id, 'ianaTimezone', true );
		if ( ! empty( $eventDateTimeZoneString ) && in_array( $eventDateTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ) {
			$utcDateTimeZone = new DateTimeZone( $eventDateTimeZoneString );
			$offsaleDateTime = DateTime::createFromFormat( 'Y-m-d H:i:s', $formattedDate, $utcDateTimeZone );
			if ( ! empty( $offsaleDateTime ) ) {
				$eventDateTimeZone = new DateTimeZone( $eventDateTimeZoneString );
				$offsaleDateTime->setTimezone( $eventDateTimeZone );
				return $offsaleDateTime;
			}
		}
	}

	return '';
}

/**
 * Extract event datetime from event data.
 *
 * @param array $seeEvent Event data array.
 * @return DateTime|false DateTime object or false on failure.
 */
function evusel_extract_event_datetime( $seeEvent ) {
	$eventTimeZoneString = $seeEvent['ianaTimezone']; // Named "ianeTimezone" in the docs
	$eventDateTimeString = isset( $seeEvent['datesTimes']['times']['showTime'] ) ?
		str_replace( array( 'T', '.000Z' ), array( ' ', '' ), $seeEvent['datesTimes']['times']['showTime'] ) :
		substr( $seeEvent['sortdate'], 0, 4 ) . '-' . substr( $seeEvent['sortdate'], 4, 2 ) . '-' . substr( $seeEvent['sortdate'], 6, 2 ) . ' 00:00:00';

	if ( in_array( $eventTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ) {
		$eventDateTimeZone = new DateTimeZone( $eventTimeZoneString );
		$eventDateTime     = DateTime::createFromFormat( 'Y-m-d H:i:s', $eventDateTimeString, $eventDateTimeZone );

		return $eventDateTime;
	}

	return '';
}

/**
 * Get event UTC datetime.
 *
 * @param array $seeEvent Event data array.
 * @return DateTime|false DateTime object or false on failure.
 */
function evusel_get_event_utc_datetime( $seeEvent ) {
	$utcDateTimeZone     = new DateTimeZone( 'UTC' );
	$eventTimeZoneString = $seeEvent['ianaTimezone']; // Named "ianeTimezone" in the docs
	$eventDateTimeZone   = in_array( $eventTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ? new DateTimeZone( $eventTimeZoneString ) : $utcDateTimeZone;

	if ( ! empty( $seeEvent['isMultiDays'] ) && ! empty( $seeEvent['datesTimes']['dates'] ) ) {

		$eventDateTime = DateTime::createFromFormat( 'm/d/Y', $seeEvent['datesTimes']['dates'][0], $eventDateTimeZone );
		$eventDateTime->setTime( 0, 0 );
		$eventDateTime->setTimezone( $utcDateTimeZone );

		return $eventDateTime;

	} else {

		$eventDateTimeString = isset( $seeEvent['datesTimes']['times']['showTime'] ) ?
			$seeEvent['datesTimes']['times']['showTime'] :
			substr( $seeEvent['sortdate'], 0, 4 ) . '-' . substr( $seeEvent['sortdate'], 4, 2 ) . '-' . substr( $seeEvent['sortdate'], 6, 2 ) . ' 00:00:00';

		if ( ! empty( $eventDateTimeString ) ) {
			$eventDateTime = DateTime::createFromFormat( 'Y-m-d H:i:s', str_replace( array( 'T', '.000Z' ), array( ' ', '' ), $eventDateTimeString ), $eventDateTimeZone );
			$eventDateTime->setTimezone( $utcDateTimeZone );

			return $eventDateTime;
		}
	}

	return '';
}

/**
 * Get event UTC end datetime.
 *
 * @param array $seeEvent Event data array.
 * @return DateTime|false DateTime object or false on failure.
 */
function evusel_get_event_utc_end_datetime( $seeEvent ) {
	$utcDateTimeZone     = new DateTimeZone( 'UTC' );
	$eventTimeZoneString = $seeEvent['ianaTimezone'];
	$eventDateTimeZone   = in_array( $eventTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ? new DateTimeZone( $eventTimeZoneString ) : $utcDateTimeZone;
	$eventDateString     = $seeEvent['sortdate'];

	$eventEndTimeString = isset( $seeEvent['datesTimes']['times']['endTime'] ) ? $seeEvent['datesTimes']['times']['endTime'] : '';
	if ( ! empty( $eventEndTimeString ) && ! empty( $eventDateString ) ) {
		$eventEndTimeDateString = $eventDateString . ' ' . $eventEndTimeString;
		$eventEndDateTime       = DateTime::createFromFormat( 'Ymd g:i A', $eventEndTimeDateString, $eventDateTimeZone );
		$utcEventEndDateTime    = clone $eventEndDateTime;
		$utcEventEndDateTime->setTimezone( $utcDateTimeZone );

		return $utcEventEndDateTime;
	}

	return '';
}

/**
 * Get event UTC door datetime.
 *
 * @param array $seeEvent Event data array.
 * @return DateTime|false DateTime object or false on failure.
 */
function evusel_get_event_utc_door_datetime( $seeEvent ) {
	$utcDateTimeZone     = new DateTimeZone( 'UTC' );
	$eventTimeZoneString = $seeEvent['ianaTimezone'];
	$eventDateTimeZone   = in_array( $eventTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ? new DateTimeZone( $eventTimeZoneString ) : $utcDateTimeZone;
	$eventDateString     = $seeEvent['sortdate'];

	$eventDoorTimeString = isset( $seeEvent['datesTimes']['times']['doorTime'] ) ? $seeEvent['datesTimes']['times']['doorTime'] : '';
	if ( ! empty( $eventDoorTimeString ) ) {
		$eventDoorTimeDateString = $eventDateString . ' ' . $eventDoorTimeString;
		$eventDoorDateTime       = DateTime::createFromFormat( 'Ymd g:i A', $eventDoorTimeDateString, $eventDateTimeZone );
		$utcEventDoorDateTime    = clone $eventDoorDateTime;
		$utcEventDoorDateTime->setTimezone( $utcDateTimeZone );

		return $utcEventDoorDateTime;
	}

	return '';
}

/**
 * Get event UTC publish datetime.
 *
 * @param array $seeEvent Event data array.
 * @return DateTime|string DateTime object or empty string.
 * @since 0.18.0
 */
function evusel_get_event_utc_publish_datetime( $seeEvent ) {
	$publishDateString = substr( $seeEvent['publishDate'], 0, 19 ); // Cut the ".000Z" part, because with the full string we are not able to set the correct timezone.

	if ( ! empty( $publishDateString ) ) {

		$utcDateTimeZone      = new DateTimeZone( 'UTC' );
		$eventTimeZoneString  = $seeEvent['ianaTimezone'];
		$eventDateTimeZone    = in_array( $eventTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ? new DateTimeZone( $eventTimeZoneString ) : $utcDateTimeZone;
		$eventPublishDateTime = DateTime::createFromFormat( 'Y-m-d\TH:i:s', $publishDateString, $eventDateTimeZone );
		$eventPublishDateTime->setTimezone( $utcDateTimeZone );

		return $eventPublishDateTime;
	}

	return '';
}

/**
 * Get event UTC offsale datetime.
 *
 * @param array $seeEvent Event data array.
 * @return DateTime|string DateTime object or empty string.
 * @since 0.25.0b
 */
function evusel_get_event_utc_offsale_datetime( $seeEvent ) {
	$offsaleDateTimeString = trim( $seeEvent['offsale'] ); // The string has a trailing space, we remove that
	if ( ! empty( $offsaleDateTimeString ) ) {
		$utcDateTimeZone      = new DateTimeZone( 'UTC' );
		$eventTimeZoneString  = $seeEvent['ianaTimezone'];
		$eventDateTimeZone    = in_array( $eventTimeZoneString, EVUSEL_TIMEZONE_IDENTIFIERS_LIST ) ? new DateTimeZone( $eventTimeZoneString ) : $utcDateTimeZone;
		$eventOffsaleDateTime = DateTime::createFromFormat( 'm/d/Y gA', $offsaleDateTimeString, $eventDateTimeZone );
		$eventOffsaleDateTime->setTimezone( $utcDateTimeZone );

		return $eventOffsaleDateTime;
	}

	return '';
}

/**
 * Update event meta data.
 *
 * @param int    $id         Post ID.
 * @param array  $seeEvent   Event data array.
 * @param bool   $createMode Whether in create mode.
 * @return void
 */
function evusel_update_event_meta( $id, $seeEvent, $createMode = false ) {
	global $evuselConfig;

	$isMultiDay = $seeEvent['isMultiDays'];

	$eventDateTime        = evusel_extract_event_datetime( $seeEvent );
	$utcEventDateTime     = evusel_get_event_utc_datetime( $seeEvent );
	$utcEventEndDateTime  = evusel_get_event_utc_end_datetime( $seeEvent );
	$utcEventDoorDateTime = evusel_get_event_utc_door_datetime( $seeEvent );
	$publishDateTime      = evusel_get_event_utc_publish_datetime( $seeEvent );
	$utcOffsaleDateTime   = evusel_get_event_utc_offsale_datetime( $seeEvent );

	$fieldsToExclude = array_keys( $evuselConfig->get( 'api.api_exclude_list' ) );

	$headliners       = str_replace( ',', ', ', $seeEvent['headliners'] ); // This is called "headliner" in the docs
	$supportingTalent = str_replace( ',', ', ', $seeEvent['talent'] );

	if ( ! in_array( 'event_header', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604943f03ed1f', $seeEvent['header'], $id );
	}
	if ( ! in_array( 'event_title', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a1100c013', $seeEvent['title'], $id );
	}
	if ( ! in_array( 'event_subtitle', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604944043ed20', $seeEvent['subtitle'], $id );
	}
	if ( ! in_array( 'headliners', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a1300c014', $headliners, $id );
	}
	if ( ! in_array( 'supporting_talent', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a13b0c015', $supportingTalent, $id );
	}
	if ( ! in_array( 'venue', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604944153ed22', $seeEvent['venue'], $id );
	}
	if ( ! in_array( 'venue_id', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a19e0c01a', $seeEvent['venueid'], $id );
	}
	if ( ! in_array( 'room', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a1c10c01b', $seeEvent['room'], $id );
	}
	if ( ! in_array( 'age', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604944243ed24', $seeEvent['age'], $id );
	}
	if ( ! in_array( 'price_range', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6049444e3ed28', $seeEvent['ticketpricerange'], $id );
	}
	if ( ! in_array( 'genre', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a1dc0c01c', $seeEvent['genre'], $id );
	}
	if ( ! in_array( 'ticket_link', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6049442f3ed25', $seeEvent['link'], $id );
	}
	if ( ! in_array( 'sort_date', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6049443d3ed27', ! empty( $eventDateTime ) ? $eventDateTime->format( 'Ymd' ) : $seeEvent['sortdate'], $id );
	}
	if ( ! in_array( 'publish_date', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_612faf19a93a4', ! empty( $publishDateTime ) ? $publishDateTime->format( 'Y-m-d H:i:s' ) : '', $id );
	}
	if ( ! in_array( 'event_date', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604944113ed21', $seeEvent['eventdate'], $id );
	}
	if ( ! in_array( 'door_time_core', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_6053a14a0c017', $seeEvent['eventtime'], $id );
	}
	if ( ! in_array( 'offsale_date_and_time', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604944203e444', $seeEvent['offsaleDateAndTime'], $id );
	}

	/**In v0.21.0b the status field was changed to advancedStatus field */
	$ticketStatus = $seeEvent['advancedStatus'] ?: 'buytickets';

	if ( ! in_array( 'ticket_status', $fieldsToExclude ) || $createMode ) {
		update_field( 'field_604944373ed26', $ticketStatus, $id );
	}

	if ( ! empty( $utcEventDoorDateTime ) && ! $isMultiDay && ( ! in_array( 'door_time', $fieldsToExclude ) || $createMode ) ) {
		update_field( 'field_6053a14a0c016', $utcEventDoorDateTime->format( 'Y-m-d H:i:s' ), $id );
	}
	if ( ! empty( $utcEventDateTime ) && ( ! in_array( 'event_time', $fieldsToExclude ) || $createMode ) ) {
		update_field( 'field_604944203ed23', $utcEventDateTime->format( 'Y-m-d H:i:s' ), $id );
	}
	if ( ! empty( $utcEventEndDateTime ) && ! $isMultiDay && ( ! in_array( 'end_time', $fieldsToExclude ) || $createMode ) ) {
		update_field( 'field_6053a1550c017', $utcEventEndDateTime->format( 'Y-m-d H:i:s' ), $id );
	}

	update_post_meta( $id, 'ianaTimezone', $seeEvent['ianaTimezone'] );
	update_post_meta( $id, 'is_multiday', $isMultiDay );
	update_post_meta( $id, 'eventyear', $seeEvent['eventyear'] );
	update_post_meta( $id, 'offsale', ! empty( $utcOffsaleDateTime ) && $utcOffsaleDateTime instanceof DateTime ? $utcOffsaleDateTime->format( 'Y-m-d H:i:s' ) : '' );

	if ( ! in_array( 'image', $fieldsToExclude ) || $createMode ) {
		update_post_meta( $id, 'image', $seeEvent['image'] );
		update_post_meta( $id, 'image_sm', $seeEvent['image-sm'] );
	}
}

/**
 * Add information metabox to Eventim US event type edit screen_icon()
 * Not all event fields will be editable, but certain feilds may affect displaying of events
 * Such fields are displayed in separate meta box
 *
 * @return void
 */
function evusel_add_events_additional_info_meta_box() {
	add_meta_box( 'seetickets-events-additional-info', 'Additional Event Information', 'evusel_events_additional_info_metabox_content', 'seetickets-event' );
}
/**
 * Render additional info metabox content.
 *
 * @return void
 */
function evusel_events_additional_info_metabox_content() {
	global $post;
	$isMultiday     = get_post_meta( $post->ID, 'is_multiday', true );
	$repeatingDates = get_post_meta( $post->ID, 'repeating_dates', true ) ?: array();
	$repeatingDates = implode( '<br>', $repeatingDates );
	?>
	<table>
		<tr>
			<td>Is multiday:</td>
			<td><?php echo esc_html( $isMultiday ? 'Yes' : 'No' ); ?></td>
		</tr>
		<?php if ( $isMultiday ) : ?>
			<tr>
				<td>Dates: </td>
				<td>
                    <?php // phpcs:ignore WordPressVIPMinimum.Security.ProperEscapingFunction.notAttrEscAttr
								esc_attr( $repeatingDates )
					?>
				</td>
			</tr>
		<?php endif; ?>
	</table>
	<?php
}
add_action( 'add_meta_boxes', 'evusel_add_events_additional_info_meta_box' );

/**
 * Hide repeating events on admin panel list view.
 *
 * @param WP_Query $query WP_Query object.
 * @return void
 */
function evusel_hide_repeating_events( $query ) {
	global $pagenow, $evuselConfig;
	$hideRepeatingEvents = '';
	if ( $query->get( 'post_type' ) == 'seetickets-event' && $pagenow == 'edit.php' && ! $evuselConfig->get( 'show_repeating_events' ) ) {
		$hideRepeatingEvents = $query->set( 'post_parent', 0 );
	}
	return $hideRepeatingEvents;
}
add_filter( 'parse_query', 'evusel_hide_repeating_events' );

/**
 * Delete all repeating events for multiday events.
 *
 * @param int      $id   Post ID.
 * @param WP_Post  $post Post object.
 * @return void
 */
function evusel_delete_repeating_events( $id, $post ) {
	if ( $post->post_type === 'seetickets-event' && get_post_meta( $id, 'is_multiday', true ) ) {
		$children = get_children( $id, ARRAY_A );
		foreach ( array_keys( $children ) as $childId ) {
			wp_delete_post( $childId );
		}
	}
}
add_action( 'before_delete_post', 'evusel_delete_repeating_events', 10, 2 );

/**
 * Exclude repeating events from admin post counters.
 *
 * @param object $counts Post counts object.
 * @param string $type   Post type.
 * @param string $perm   Permission level.
 * @return object Modified counts object.
 */
function evusel_modify_events_admin_counters( $counts, $type, $perm ) {
	global $evuselConfig;
	if ( $type === 'seetickets-event' && ! $evuselConfig->get( 'show_repeating_events' ) ) {

		global $wpdb;

		$drafts = wp_cache_get( 'seetickets_found_repeating_draft', 'seetickets' );
		if ( $drafts === false ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Necessary for post count, cached above
			$drafts = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->prefix}posts
                WHERE post_type = %s
                AND post_status = %s
                AND post_parent != 0",
					'seetickets-event',
					'draft'
				)
			);
			wp_cache_set( 'seetickets_found_repeating_draft', $drafts, 'seetickets' );
		}

		$publish = wp_cache_get( 'seetickets_found_repeating_publish', 'seetickets' );
		if ( $publish === false ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Necessary for post count, cached above
			$publish = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->prefix}posts
                WHERE post_type = %s
                AND post_status = %s
                AND post_parent != 0",
					'seetickets-event',
					'publish'
				)
			);
			wp_cache_set( 'seetickets_found_repeating_publish', $publish, 'seetickets' );
		}

		$trash = wp_cache_get( 'seetickets_found_repeating_trash', 'seetickets' );
		if ( $trash === false ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Necessary for post count, cached above
			$trash = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->prefix}posts
                WHERE post_type = %s
                AND post_status = %s
                AND post_parent != 0",
					'seetickets-event',
					'trash'
				)
			);
			wp_cache_set( 'seetickets_found_repeating_trash', $trash, 'seetickets' );
		}

		$counts->draft   = (string) ( $counts->draft - $drafts );
		$counts->publish = (string) ( $counts->publish - $publish );
		$counts->trash   = (string) ( $counts->trash - $trash );
	}

	return $counts;
}
add_filter( 'wp_count_posts', 'evusel_modify_events_admin_counters', 10, 3 );

/**
 * Update repeating events with parent.
 *
 * @param int      $post_ID    Post ID.
 * @param WP_Post  $post_after Post object after update.
 * @param WP_Post  $post_before Post object before update.
 * @return void
 */
function evusel_update_repeating_events( $post_ID, $post_after, $post_before ) {
	if ( $post_after->post_type === 'seetickets-event' && $post_after->post_parent === 0 && get_post_meta( $post_ID, 'is_multiday', true ) ) {

		global $evuselConfig;

		$attachmentId = get_post_thumbnail_id( $post_ID );
		$children     = get_children( $post_ID, ARRAY_A );

		$fieldsToExclude = array_keys( $evuselConfig->get( 'api.api_exclude_list' ) );

		foreach ( array_keys( $children ) as $childId ) {

			$args = array(
				'ID'          => $childId,
				'post_status' => $post_after->post_status,
			);

			if ( ! in_array( 'event_title', $fieldsToExclude ) ) {
				$args['post_title'] = $post_after->post_title;
			}

			wp_update_post( $args );
			set_post_thumbnail( $childId, $attachmentId );
		}
	}
}
add_action( 'post_updated', 'evusel_update_repeating_events', 100, 3 );

/**
 * Update repeating event meta.
 *
 * @param int $post_ID Post ID.
 * @return void
 * @since 0.10.0
 */
function evusel_update_repeating_event_meta( $post_ID ) {
	$eventTitle = get_post_meta( $post_ID, 'event_title', true );
	$children   = get_children( $post_ID, ARRAY_A );
	foreach ( array_keys( $children ) as $childId ) {
		update_post_meta( $childId, 'event_title', $eventTitle );
	}
}
add_action( 'acf/save_post', 'evusel_update_repeating_event_meta' );

/**
 * Get custom ticket status button text.
 *
 * @param WP_Post $event Event post object.
 * @return string Button text.
 * @since 0.10.0
 */
function evusel_get_ticket_status_button_text( $event ) {
	global $evuselConfig;
	$id                   = has_post_parent( $event ) ? $event->post_parent : $event->ID; // If the post has a parent, it is a recurring event
	$ticketStatusOverride = $evuselConfig->get( 'button_status_override' );

	$now                      = evusel_GetNowDateTimeForEvent( $event );
	$offsaleDateTime          = evusel_see_get_event_offsale_display_date_time( $event->ID );
	$shouldDisplayEventPassed = false;
	if ( ! empty( $offsaleDateTime ) && strtotime( $now->format( 'Y-m-d H:i:s' ) ) > strtotime( $offsaleDateTime->format( 'Y-m-d H:i:s' ) ) ) {
		$shouldDisplayEventPassed = true;
	}

	if ( $shouldDisplayEventPassed ) {
		$btnText = 'Event passed';
	} elseif ( ! empty( $ticketStatusOverride ) ) {
		$btnText = $ticketStatusOverride;
	} else {
		$ticketStatusLabel = get_field( 'ticket_status', $id );
		$ticketStatusValue = get_post_meta( $id, 'ticket_status', true );
		$btnText           = $ticketStatusValue === 'custom' ? get_post_meta( $id, 'custom_ticket_status', true ) : $ticketStatusLabel;
	}

	return $btnText;
}

/**
 * Get custom ticket status button classes.
 *
 * @param WP_Post $event Event post object.
 * @return string Button classes.
 * @since 0.13.0
 */
function evusel_get_ticket_status_button_classes( $event ) {
	global $evuselConfig;
	$id           = has_post_parent( $event ) ? $event->post_parent : $event->ID; // If the post has a parent, it is a recurring event
	$ticketStatus = get_post_meta( $id, 'ticket_status', true );
	return ! empty( $ticketStatus ) ?
		$evuselConfig->get( 'button_status_classes' )[ $ticketStatus ] . ' ' :
		'';
}

/**
 * Get ticket link for event.
 *
 * @param WP_Post|object $event       Event post object.
 * @param bool           $getOriginal Whether to get original link.
 * @return string Ticket link URL.
 * @since 0.10.0
 */
function evusel_get_ticket_link( $event, $getOriginal = false ) {
	global $evuselConfig;
	@$id = has_post_parent( $event ) ? $event->post_parent : $event->ID; // If the post has a parent, it is a recurring event

	return $evuselConfig->get( 'link_title_and_image_to' ) === 'seepage' || $getOriginal ?
		get_post_meta( $id, 'ticket_link', true ) :
		get_permalink( $event->ID );
}

/**
 * @param WP_Post $event
 * @since 0.10.0
 * @return string
 */
function evusel_get_headliners( $event ) {
	$id = has_post_parent( $event ) ? $event->post_parent : $event->ID; // If the post has a parent, it is a recurring event
	return get_post_meta( $id, 'headliners', true );
}

/**
 * @param bool     $dispevliIsInPast
 * @param string   $eventTitle
 * @param DateTime $eventDate
 * @since 0.10.0
 * @return string
 */
function evusel_get_ticket_button_aria_label( $dispevliIsInPast, $eventTitle, $eventDate ) {
	if ( ! empty( $eventDate ) ) {
		$eventDateString = $eventDate->format( 'M d' );
	} else {
		return 'Event Passed';
	}
	return $dispevliIsInPast ? 'Event Passed' : "Buy Tickets for $eventTitle on $eventDateString";
}

/**
 * @param array $views
 * @since 0.15.0
 * @return array
 */
function evusel_custom_views_for_events( $views ) {
	unset( $views['mine'] );
	return $views;
}
add_filter( 'views_edit-seetickets-event', 'evusel_custom_views_for_events' );

/**
 * Extend admin search for events to certain meta values
 *
 * @param WP_Query $query
 * @since 0.16.1
 * @return void
 */
function evusel_custom_search_query( $posts, $query ) {
	if (
		$query->is_main_query() &&
		is_admin() &&
		$query->get( 'post_type' ) === 'seetickets-event' &&
		$query->is_search &&
		! empty( $query->get( 's' ) )
	) {
		$metaKeys = array( 'event_header', 'event_title', 'event_subtitle', 'headliners', 'supporting_talent' );
		$args     = array(
			'numberposts'   => -1,
			'post_type'     => 'seetickets-event',
			// 'post_status'   => [''],
			'meta_query'    => array( 'relation' => 'OR' ),
			'no_found_rows' => false,
		);
		foreach ( $metaKeys as $metaKey ) {
			$args['meta_query'][] = array(
				'key'     => $metaKey,
				'value'   => $query->get( 's' ),
				'compare' => 'LIKE',
			);
		}

		$results = array_merge( $posts, get_posts( $args ) );
		return array_unique( $results, SORT_REGULAR );
	}
	return $posts;
}
add_filter( 'posts_results', 'evusel_custom_search_query', 10, 2 );

/**
 * Add custom layout for Eventim US Post type
 *
 * @param string $template
 * @return string
 * @since 0.22.0b
 */
function evusel_render_see_tickets_post_template( $content ) {

	global $post, $evuselConfig;

	if ( $post->post_type !== 'seetickets-event' ) {
		return $content;
	}

	$event            = $post;
	$eventDateTime    = evusel_get_event_display_date_time( $event->ID );
	$dispevliIsInPast = ! empty( $eventDateTime ) ? ( time() > strtotime( $eventDateTime->format( 'Ymd' ) ) ) : false;

	$ticketLink = evusel_get_ticket_link( $event );
	$eventTitle = get_post_meta( $event->ID, 'event_title', true );

	$btnText   = evusel_get_ticket_status_button_text( $event );
	$ariaLabel = evusel_get_ticket_button_aria_label( $dispevliIsInPast, $eventTitle, $eventDateTime );

	$classes  = $dispevliIsInPast ? 'disabled ' : '';
	$classes .= evusel_get_ticket_status_button_classes( $event );

	$containerClasses  = 'seetickets-list-event-container mdc-card ';
	$containerClasses .= $evuselConfig->get( 'shortcodes.list_view.material_list_style' ) === 'outlined' ? 'mdc-card--outlined ' : '';

	$gridImageContainerStyle = $evuselConfig->get( 'event_image_style' ) === 'square' ?
		'object-fit: cover; ' :
		'object-fit: contain; ';

	$image = evusel_anchorize( '<img src="' . esc_url( evusel_get_event_image( $event->ID ) ) . '" style="' . esc_attr( $gridImageContainerStyle . ' width: 275px; height: 275px;' ) . '" class="seetickets-list-view-event-image">', $event, '', true );

	$socialClasses = $evuselConfig->get( 'social_icon_circles' ) === 'on' ? 'social-circle ' : 'social-icon ';

	$openEventPageToNewTab = $evuselConfig->get( 'open_event_page_to_new_tab' );

	$isMultiday = get_post_meta( $event->ID, 'is_multiday', true );

	if ( $isMultiday && $dispevliIsInPast ) {
		$classes   = evusel_get_ticket_status_button_classes( $event );
		$ariaLabel = evusel_get_ticket_button_aria_label( false, $eventTitle, $eventDateTime );
	}

	$ticketButtonLink           = evusel_get_ticket_link( $event, true );
	$seeticketEventButtonTarget = '';
	if ( $openEventPageToNewTab == 'on' ) {
		$seeticketEventButtonTarget = "target='_blank'";
	}
	$seetiketEventButton = "<a href='" . esc_url( $ticketButtonLink ) . "' " . esc_attr( $seeticketEventButtonTarget ) . " aria-label='" . esc_attr( $ariaLabel ) . "' class='seetickets-buy-btn fs-16 " . esc_attr( $classes ) . "'>" . esc_html( $btnText ) . '</a>';

	$content = '<div id="list-view-events"><div class="seetickets-list-events">' .
		str_replace(
			array(
				'{%image%}',
				'{%cardLabels%}',
				'{%buttonClasses%}',
				'{%eventButtonText%}',
				'{%eventContainerClass%}',
				'{%eventContainerStyle%}',
				'{%pluginDirUrl%}',
				'{%facebookShareText%}',
				'{%twitterSharetext%}',
				'{%ticketLink%}',
				'{%socialClasses%}',
				'{%ariaLabel%}',
				'{%facebookIcon%}',
				'{%twitterIcon%}',
				'{%openEventPageToNewTab%}',
			),
			array(
				$image,
				evusel_getCardLabelsHtml( $event, $eventTitle, 'list', true, $eventDateTime ),
				esc_attr( $classes ),
				esc_html( $btnText ),
				esc_attr( $containerClasses ),
				'',
				esc_url( EVUSEL_PLUGIN_DIR_URL ),
				esc_url( urldecode( $ticketLink ) ),
				esc_url( urldecode( $ticketLink ) ),
				esc_url( $ticketLink ),
				esc_attr( $socialClasses ),
				esc_attr( $ariaLabel ),
				'<span class="d-inline-block ' . esc_attr( $socialClasses ) . '">' . file_get_contents( EVUSEL_PLUGIN_DIR . '/images/facebook-icon.svg' ) . '</span>',
				'<span class="d-inline-block ' . esc_attr( $socialClasses ) . '">' . file_get_contents( EVUSEL_PLUGIN_DIR . '/images/x-twitter-brands-solid.svg' ) . '</span>',
				$seetiketEventButton,
			),
			file_get_contents( EVUSEL_PLUGIN_DIR . 'includes/templates/event_list_element.html' )
		);

	$content .= get_field( 'video', $event->ID );
	$content .= $event->post_content;

	$content .= '</div></div>';

	return $content;
}
add_filter( 'the_content', 'evusel_render_see_tickets_post_template' );

/**
 * @param int|string $eventID
 * @return string
 * @since 0.23.1b
 */
function evusel_get_venue_text( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	$venue = get_post_meta( $idToGet, 'venue', true );
	return ! empty( $venue ) ? 'at ' . $venue : '';
}

/**
 * @param int|string $eventID
 * @return string
 * @since 0.23.1b
 */
function evusel_get_ages_price_text( $eventID ) {
	global $evuselConfig;

	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	$agesPrice = get_post_meta( $idToGet, 'age', true );
	$agesPrice = ! empty( $agesPrice ) ? '<span class="' . $evuselConfig->get( 'event_data_classes.ages' ) . '">' . $agesPrice . '</span>, ' : '';

	$priceRange = get_post_meta( $idToGet, 'price_range', true );
	$agesPrice .= ! empty( $priceRange ) ? '<span class="' . $evuselConfig->get( 'event_data_classes.price' ) . '">' . $priceRange . '</span>' : '';

	return $agesPrice;
}

/**
 * @param int|string $eventID
 * @return string
 * @since 0.23.1b
 */
function evusel_get_supporting_talent_text( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	$supportingTalent = get_post_meta( $idToGet, 'supporting_talent', true );

	return ! empty( $supportingTalent ) ? evusel_get_supporting_talent_label() . $supportingTalent : '';
}

/**
 * @param int|string $eventID
 * @return string
 * @since 0.34.0.0b
 */
function evusel_get_door_time_core( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	$doorTimeCore = get_post_meta( $idToGet, 'door_time_core', true );

	return $doorTimeCore;
}

/**
 * Get event time.
 *
 * @param int $eventID Event post ID.
 * @return string|false Event time string or false on failure.
 */
function evusel_get_event_time( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	$evenTime = get_post_meta( $eventID, 'event_time', true );

	return $evenTime;
}

/**
 * @param int|string $eventID
 * @return string
 * @since 0.30.1b
 */
function evusel_get_event_header_text( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	return get_post_meta( $idToGet, 'event_header', true );
}

/**
 * @param int|string $eventID
 * @return string
 * @since 0.30.1b
 */
function evusel_subtitle_text( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	return get_post_meta( $idToGet, 'event_subtitle', true );
}

/**
 * @param int|string $eventID
 * @return string
 * @since 0.30.1b
 */
function evusel_get_genre_text( $eventID ) {
	$isMultiday = (bool) get_post_meta( $eventID, 'is_multiday', true );
	$idToGet    = $isMultiday && has_post_parent( $eventID ) ? wp_get_post_parent_id( $eventID ) : $eventID;

	return get_post_meta( $idToGet, 'genre', true );
}