<?php

use EM\Archetypes;

class EM_Custom_Emails_Admin {
	public static $caps = array( 'custom_emails' => 'manage_bookings' );

	public static function init() {
		//Custom Event Emails
		if ( em_get_option( 'dbem_custom_emails_events' ) ) {
				add_action( 'add_meta_boxes', 'EM_Custom_Emails_Admin::meta_boxes' );
				// Present the metabox as an "Emails" tab in EM core's block-editor tab layout. No-op on core versions without the filter.
				add_filter( 'em_event_editor_tabs', 'EM_Custom_Emails_Admin::em_event_editor_tab' );
				add_action( 'em_enqueue_admin_scripts', 'EM_Custom_Emails_Admin::enqueue_editor_js' );
				add_filter( 'em_event_get_post_meta', 'EM_Custom_Emails_Admin::em_event_get_post_meta', 100, 2 );
			if ( em_get_option( 'dbem_custom_emails_events_admins' ) ) {
				add_filter( 'em_event_validate_meta', 'EM_Custom_Emails_Admin::em_event_validate_meta', 100, 2 );
			}
				add_filter( 'em_event_save_meta', 'EM_Custom_Emails_Admin::em_event_save_meta', 100, 2 );
				add_filter( 'em_event_save_events', 'EM_Custom_Emails_Admin::em_event_save_events', 100, 4 );
		}
		//Custom Gateway Emails
		if ( em_get_option( 'dbem_custom_emails_gateways' ) ) {
			add_filter( 'em_gateway_settings_tabs', 'EM_Custom_Emails_Admin::em_gateway_settings_tabs', 10, 2 );
			add_action( 'em_gateway_settings_tab_booking_emails', 'EM_Custom_Emails_Admin::em_gateway_settings_tab_booking_emails', 10, 1 );
			add_action( 'em_gateway_update', 'EM_Custom_Emails_Admin::em_gateway_update', 10, 1 );
		}
		//multilingual hook - this SHOULD fire after the EM_ML init hook as it's added after EM_ML is loaded
		add_action( 'em_ml_init', 'EM_Custom_Emails_Admin::em_ml_init' );
	}

	public static function em_ml_init() {
		include 'custom-emails-admin-ml.php'; }

	/*
	 * --------------------------------------------
	 * General Editor Functions for Overriding Emails
	 * --------------------------------------------
	 */

	/**
	 * Builds form for overriding booking emails
	 * @param array $emails_array_custom
	 * @param array $emails_values_custom
	 */
	public static function emails_editor( $emails_values_custom = array(), $emails_array_custom = array(), $admin_emails_custom = array(), $param = 'em_custom_email' ) {
		//build structure of emails to show
		$emails_array   = ! empty( $emails_array_custom ) ? $emails_array_custom : self::get_default_emails(); //override defaults
		$default_emails = self::get_default_email_values();
		$emails_values  = ! empty( $emails_values_custom ) ? $emails_values_custom : self::get_default_email_values(); //override defaults
		$group_count    = count( $emails_array );
		//$admin_emails_custom could be an array of email arrays or an array of comma-delimted emails
		if ( ! is_array( $admin_emails_custom ) ) {
			$admin_emails_custom = array();
		}
		foreach ( $admin_emails_custom as $k => $y ) {
			if ( is_array( $y ) ) {
				$admin_emails_custom[ $k ] = implode( ',', $y );
			}
		}
		//output the structure in an html form format
		?>
		<div class="emp-cet">
			<?php foreach ( $emails_array as $email_array_group_name => $email_array_group ) : ?>
			<h4 class="emp-cet-group-trigger">
				<a href="#" rel="<?php echo '#' . $param; ?>-<?php echo $email_array_group_name; ?>">
				<?php echo $email_array_group['title']; ?>
				<span>+</span></a>
			</h4>
			<div class="emp-cet-group" id="<?php echo $param; ?>-<?php echo $email_array_group_name; ?>">
				<div>
				<?php
				if ( ! empty( $email_array_group['text'] ) ) {
					echo $email_array_group['text'];}
				?>
				</div>
				
				<?php if ( is_array( $admin_emails_custom ) ) : ?>
				<label><?php _e( 'Also Send Event Owner Emails To:', 'em-pro' ); ?></label>
				<input type="text" class="emp-cet-email" name="<?php echo $param; ?>_admins[<?php echo $email_array_group_name; ?>]" value="<?php
					if ( ! empty( $admin_emails_custom[ $email_array_group_name ] ) ) {
						echo $admin_emails_custom[ $email_array_group_name ];}
					?>" /><br />
				<em><?php esc_html_e_emp( 'For multiple emails, seperate by commas (e.g. email1@test.com,email2@test.com,etc.)', 'events-manager' ); ?></em>
				<?php endif; ?>				
				
				<?php foreach ( $email_array_group['subgroups'] as $email_array_subgroup => $email_array ) : ?>
				<h5 class="emp-cet-subgroup-trigger"><a href="#" rel="<?php echo '#' . $param; ?>-<?php echo $email_array_subgroup; ?>"><?php echo $email_array['title']; ?> <span>+</span></a></h5>
				<div class="emp-cet-subgroup" id="<?php echo $param; ?>-<?php echo $email_array_subgroup; ?>" >
					<p><?php echo $email_array['text']; ?></p>
					<?php foreach ( $email_array['emails'] as $email_type_name => $email_type ) : ?>
					<div class="emp-cet-subgroup-email">
						<?php
							$status  = ! empty( $emails_values[ $email_array_subgroup ][ $email_type_name ]['status'] ) ? $emails_values[ $email_array_subgroup ][ $email_type_name ]['status'] : 0;
							$subject = ! empty( $emails_values[ $email_array_subgroup ][ $email_type_name ]['subject'] ) ? $emails_values[ $email_array_subgroup ][ $email_type_name ]['subject'] : $default_emails[ $email_array_subgroup ][ $email_type_name ]['subject'];
							$message = ! empty( $emails_values[ $email_array_subgroup ][ $email_type_name ]['message'] ) ? $emails_values[ $email_array_subgroup ][ $email_type_name ]['message'] : $default_emails[ $email_array_subgroup ][ $email_type_name ]['message'];
						?>
						<select class="emp-cet-status" name="<?php echo $param; ?>[<?php echo $email_array_subgroup; ?>][<?php echo $email_type_name; ?>][status]">
							<option value="0" class="emp-default"><?php esc_html_e( 'Default', 'em-pro' ); ?></option>
							<option value="1" class="emp-enabled" 
							<?php
							if ( $status == 1 ) {
								echo 'selected="selected"';}
							?>
							><?php esc_html_e( 'Enabled', 'em-pro' ); ?></option>
							<option value="2" class="emp-disabled" 
							<?php
							if ( $status == 2 ) {
								echo 'selected="selected"';}
							?>
							><?php esc_html_e( 'Disabled', 'em-pro' ); ?></option>
						</select> 
						<strong><?php echo $email_type['title']; ?></strong>
						<div class="emp-cet-vals">
							<div class="emp-cet-val">
								<label><?php _e( 'Subject', 'em-pro' ); ?></label>
								<input type="text" name="<?php echo $param; ?>[<?php echo $email_array_subgroup; ?>][<?php echo $email_type_name; ?>][subject]" value="<?php echo esc_attr( $subject ); ?>" />
							</div>
							<div class="emp-cet-val">
								<label><?php _e( 'Message', 'em-pro' ); ?></label>
								<textarea name="<?php echo $param; ?>[<?php echo $email_array_subgroup; ?>][<?php echo $email_type_name; ?>][message]"><?php echo esc_html( $message ); ?></textarea>
							</div>
						</div>
					</div>
					<?php endforeach; ?>
				</div>
				<?php endforeach; ?>
			</div>
			<?php endforeach; ?>
		</div>
		<?php
	}

	/**
	 * The custom-emails editor UI (collapsible groups/subgroups + per-email status toggles). Delivered as an inline script on the events-manager handle via em_enqueue_admin_scripts, so it loads in BOTH the classic admin and the Gutenberg canvas iframe. It (re)initialises per .emp-cet container on em_setup_ui_elements — and once on ready — so it binds the canvas-injected copy too. Idempotent via a per-container data flag.
	 */
	public static function enqueue_editor_js() {
		static $added = false;
		if ( $added ) { return; }
		$added = true;
		$js = <<<'JS'
( function () {
	if ( ! window.jQuery ) { return; }
	var $ = window.jQuery;
	function init( root ) {
		$( root || document ).find( '.emp-cet' ).addBack( '.emp-cet' ).each( function () {
			var box = $( this );
			if ( box.data( 'empCetBound' ) ) { return; }
			box.data( 'empCetBound', true );
			var trigger_selector = '.emp-cet-subgroup-trigger a';
			box.find( '.emp-cet-subgroup' ).hide();
			if ( box.find( '.emp-cet-group' ).length > 1 ) {
				box.find( '.emp-cet-group' ).hide();
				trigger_selector = '.emp-cet-group-trigger a, .emp-cet-subgroup-trigger a';
			} else {
				box.find( '.emp-cet-group-trigger span' ).hide();
			}
			box.on( 'click', trigger_selector, function ( e ) {
				e.preventDefault();
				var a = $( this );
				var target = box.find( a.attr( 'rel' ) );
				if ( a.children( 'span' ).text() === '+' ) { target.show(); a.children( 'span' ).text( '-' ); }
				else { target.hide(); a.children( 'span' ).text( '+' ); }
			} );
			box.find( 'select.emp-cet-status' ).on( 'change', function () {
				var el = $( this ), selected = el.find( 'option:selected' );
				el.attr( 'class', selected.attr( 'class' ) );
				if ( selected.val() != 1 ) { el.nextAll( '.emp-cet-vals' ).hide(); } else { el.nextAll( '.emp-cet-vals' ).show(); }
				if ( selected.val() != 0 ) {
					var subgroup = el.closest( '.emp-cet-subgroup' ).show();
					subgroup.prevAll( '.emp-cet-subgroup-trigger' ).first().find( 'a span' ).text( '-' );
					if ( box.find( '.emp-cet-group' ).length > 1 ) {
						var group = subgroup.closest( '.emp-cet-group' ).show();
						group.prevAll( '.emp-cet-group-trigger' ).first().find( 'a span' ).text( '-' );
					}
				}
			} ).trigger( 'change' );
			box.find( 'input.emp-cet-email' ).each( function () {
				if ( this.value != '' ) {
					var group = $( this ).closest( '.emp-cet-group' ).show();
					group.prevAll( '.emp-cet-group-trigger' ).first().find( 'a span' ).text( '-' );
				}
			} );
		} );
	}
	$( function () { init( document ); } );
	document.addEventListener( 'em_setup_ui_elements', function ( e ) { if ( e.detail && e.detail.container ) { init( e.detail.container ); } } );
} )();
JS;
		wp_add_inline_script( 'events-manager', $js );
	}

	public static function get_default_emails() {
		$emails = array(
			'default' => array(
				'title'     => __( 'Default or Free Booking Emails', 'em-pro' ),
				'subgroups' => array(
					'admin' => array(
						'title'  => __( 'Event Owner Emails', 'em-pro' ),
						'text'   => __( 'These emails get sent to the event owners when a person has made a booking.', 'em-pro' ),
						'emails' => apply_filters(
							'em_custom_emails_admin_default_emails_subgroup',
							array(
								0 => array( 'title' => emp__( 'Pending booking email', 'events-manager' ) ),
								1 => array( 'title' => emp__( 'Confirmed booking email', 'events-manager' ) ),
								2 => array( 'title' => emp__( 'Rejected booking email', 'events-manager' ) ),
								3 => array( 'title' => emp__( 'Booking cancelled', 'events-manager' ) ),
							),
							'admin'
						),
					),
					'user'  => array(
						'title'  => __( 'Attendee Emails', 'em-pro' ),
						'text'   => __( 'These emails will be sent to the person who booked a place at your event.', 'em-pro' ),
						'emails' => apply_filters(
							'em_custom_emails_admin_default_emails_subgroup',
							array(
								0 => array( 'title' => emp__( 'Pending booking email', 'events-manager' ) ),
								1 => array( 'title' => emp__( 'Confirmed booking email', 'events-manager' ) ),
								2 => array( 'title' => emp__( 'Rejected booking email', 'events-manager' ) ),
								3 => array( 'title' => emp__( 'Booking cancelled', 'events-manager' ) ),
							),
							'user'
						),
					),
				),
			),
		);
		// apply filters here so we don't have
		$emails = apply_filters( 'em_custom_emails_admin_default_emails', $emails );
		if ( em_get_option( 'dbem_custom_emails_gateways' ) ) {
			$emails = array_merge( $emails, self::get_gateway_default_emails() );
		}
		return $emails;
	}

	/**
	 * @param EM\Payments\Gateway|false $Gateway
	 * @param boolean $multiple_bookings
	 *
	 * @return array
	 */
	public static function get_default_email_values( $Gateway = false, $multiple_bookings = false ) {
		//build structure of values to add to these emails
		$mb_opt       = $multiple_bookings ? 'multiple_' : '';
		$mb_key       = $multiple_bookings ? 'mb-' : '';
		$email_values = array(
			$mb_key . 'admin' => apply_filters(
				'em_custom_emails_admin_default_email_values',
				array(
					0 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_pending_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_pending_body' ),
						'status'  => 0,
					),
					1 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_confirmed_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_confirmed_body' ),
						'status'  => 0,
					),
					2 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_rejected_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_rejected_body' ),
						'status'  => 0,
					),
					3 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_cancelled_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_cancelled_body' ),
						'status'  => 0,
					),
				),
				$multiple_bookings,
				'admin'
			),
			$mb_key . 'user'  => apply_filters(
				'em_custom_emails_admin_default_email_values',
				array(
					0 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_pending_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_pending_body' ),
						'status'  => 0,
					),
					1 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_confirmed_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_confirmed_body' ),
						'status'  => 0,
					),
					2 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_rejected_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_rejected_body' ),
						'status'  => 0,
					),
					3 => array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_cancelled_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_cancelled_body' ),
						'status'  => 0,
					),
				),
				$multiple_bookings,
				'user'
			),
		);
		//handle gateways, and only return a single gateway value if requested by $Gateway parameter
		if ( em_get_option( 'dbem_custom_emails_gateways' ) ) {
			$email_values_template = $email_values;
			if ( ! empty( $Gateway ) ) {
				$email_values = array();
				$gateways     = array( $Gateway::$gateway => $Gateway::$title );
			} else {
				$gateways = \EM\Payments\Gateways::active_gateways();
			}
			foreach ( $gateways as $gateway => $Gateway ) {
				//default values are - by default - the general settings values, overriden further down by $possible_email_values
				$gateway_email_defaults = array(
					$gateway . '-' . $mb_key . 'admin' => $email_values_template[ $mb_key . 'admin' ],
					$gateway . '-' . $mb_key . 'user'  => $email_values_template[ $mb_key . 'user' ],
				);
				//temporary fix, we assume everything is online except for offline - maybe a good reason for split offline/online base gateway subclasses
				if ( $gateway == 'offline' ) {
					$gateway_email_defaults[ $gateway . '-' . $mb_key . 'admin' ][5] = array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_pending_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_contact_email_pending_body' ),
						'status'  => 0,
					);
					$gateway_email_defaults[ $gateway . '-' . $mb_key . 'user' ][5]  = array(
						'subject' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_pending_subject' ),
						'message' => em_get_option( 'dbem_' . $mb_opt . 'bookings_email_pending_body' ),
						'status'  => 0,
					);
				}
				//get custom values if applicable
				$possible_email_values = maybe_unserialize( em_get_option( 'em_' . $gateway . '_emails' ) );
				$gateway_email_values  = self::merge_gateway_default_values( $gateway, $gateway_email_defaults, $possible_email_values, true ); //merge in only messages here not statuses
				//apply filters here to get all emails included for filtering
				$gateway_email_values[ $gateway . '-' . $mb_key . 'admin' ] = apply_filters( 'em_custom_emails_admin_default_email_values', $gateway_email_values[ $gateway . '-' . $mb_key . 'admin' ], $multiple_bookings, 'admin', $gateway );
				$gateway_email_values[ $gateway . '-' . $mb_key . 'user' ]  = apply_filters( 'em_custom_emails_admin_default_email_values', $gateway_email_values[ $gateway . '-' . $mb_key . 'user' ], $multiple_bookings, 'user', $gateway );
				$email_values = array_merge( $email_values, $gateway_email_values );
			}
		}
		return $email_values;
	}

	public static function editor_get_post( $custom_email_defaults = array(), $param = 'em_custom_email' ) {
		global $allowedposttags;
		$emails        = ! empty( $custom_email_defaults ) ? $custom_email_defaults : self::get_default_emails(); //override defaults
		$custom_emails = array();
		foreach ( $emails as $email_group_name => $email_group ) {
			foreach ( $email_group['subgroups'] as $email_subgroup_name => $email_subgroup ) {
				foreach ( $email_subgroup['emails'] as $email_type_name => $email_type ) {
					if ( ! empty( $_REQUEST[ $param ][ $email_subgroup_name ][ $email_type_name ]['status'] ) ) {
						//status is set, save it and message if needed
						$custom_emails[ $email_subgroup_name ][ $email_type_name ]['status'] = $_REQUEST[ $param ][ $email_subgroup_name ][ $email_type_name ]['status'];
						if ( $_REQUEST[ $param ][ $email_subgroup_name ][ $email_type_name ]['status'] == 1 ) {
							//only if enabled do we need to save an email format
							$custom_emails[ $email_subgroup_name ][ $email_type_name ]['subject'] = wp_kses_data( wp_unslash( $_REQUEST[ $param ][ $email_subgroup_name ][ $email_type_name ]['subject'] ) );
							$custom_emails[ $email_subgroup_name ][ $email_type_name ]['message'] = wp_unslash( $_REQUEST[ $param ][ $email_subgroup_name ][ $email_type_name ]['message'] );
						}
					}
				}
			}
		}
		return $custom_emails;
	}

	/**
	 * Gets posted admin email values and mnerges it into the passed array of emails.
	 * @param array $custom_email_defaults Supplied array of admin emails.
	 * @param string $param Parameter name in $_REQUEST containing admin email addresses.
	 * @return array
	 */
	public static function editor_admin_emails_get_post( $custom_email_defaults = array(), $param = 'em_custom_email_admins' ) {
		$emails              = ! empty( $custom_email_defaults ) ? $custom_email_defaults : self::get_default_emails(); //override defaults
		$custom_admin_emails = array();
		foreach ( $emails as $email_group_name => $email_group ) {
			if ( isset( $_REQUEST[ $param ][ $email_group_name ] ) && ! empty( $_REQUEST[ $param ][ $email_group_name ] ) ) {
				$custom_admin_emails[ $email_group_name ] = str_replace( ' ', '', $_REQUEST[ $param ][ $email_group_name ] );
			}
		}
		return $custom_admin_emails;
	}

	/*
	 * --------------------------------------------
	 * Custom Gateway Booking Emails
	 * --------------------------------------------
	 */

	public static function em_gateway_settings_tabs( $tabs, $Gateway ) {
		$tabs['booking_emails'] = esc_html__( 'Custom Booking Email Templates', 'em-pro' );
		return $tabs;
	}
	/**
	 * @param \EM\Payments\Gateway $Gateway
	 */
	public static function em_gateway_settings_tab_booking_emails( $Gateway ) {
		//get default email structures and values
		$default_emails       = self::get_gateway_default_emails( $Gateway );
		$default_email_values = self::get_default_email_values( $Gateway );
		$gateway              = $Gateway::$gateway;
		//get custom values if applicable and merge them into $email_values
		$gateway_email_values = maybe_unserialize( $Gateway::get_option( 'emails' ) );
		$email_values         = self::merge_gateway_default_values( $gateway, $default_email_values, $gateway_email_values );
		$admin_emails         = false;
		if ( em_get_option( 'dbem_custom_emails_gateways_admins' ) ) {
			$admin_emails = EM_Custom_Emails::get_gateway_admin_emails( $Gateway );
		}
		echo '<h3>' . esc_html__( 'Custom Booking Email Templates', 'em-pro' ) . '</h3>';
		$default_emails[ $gateway ]['title'] = __( 'Booking Email Templates', 'em-pro' );
		$default_emails[ $gateway ]['text']  = '<p>' . sprintf( __( 'Below you can modify the emails that are sent when bookings are made. This will override the default emails located in your %s settings page.', 'em-pro' ), '<a href="' . admin_url( 'edit.php?post_type=event&page=events-manager-options#emails:booking-emails' ) . '">' . esc_html__emp( 'Booking Email Templates', 'events-manager' ) . '</a>' );
		$default_emails[ $gateway ]['text'] .= __( 'Additionally, you can also override these emails at an event level when editing an event. Should you choose not to, any overriden emails on this page will be considered the default email for this gateway.', 'em-pro' ) . '</p>';
		$default_emails[ $gateway ]['text'] .= '<p>' . __( 'Note that some gateways do not automatically send pending or confirmed emails, in these cases they may only apply to when event admins manually change the status of a booking resulting in an automated email getting sent.', 'em-pro' ) . '</p>';
		$default_emails[ $gateway ]['text'] .= '<p>' . __( 'Click on the title texts with a plus (+) next to them to reveal further options, and the minus (-) sign to hide them.', 'em-pro' ) . '</p>';
		if ( get_option( 'dbem_multiple_bookings' ) ) {
			$default_emails[ $gateway ]['text'] = '<p><strong>' . __( 'Important:', 'em-pro' ) . '</strong> ' . __( 'You are in Multiple Booking Mode. These emails will only be used when individually modifying bookings which trigger these individual event booking emails.', 'em-pro' ) . '</p>' . $default_emails[ $gateway ]['text'];
			//duplicate default emails array and give them different keys
			$default_emails = self::add_gateway_mb_default_emails( $default_emails, $Gateway );
			//alter texts
			$default_emails[ $gateway . '-mb' ]['title'] = __( 'Multiple Booking Email Templates', 'em-pro' );
			$default_emails[ $gateway . '-mb' ]['text']  = '<p>' . sprintf( __( 'Below you can modify the emails that are sent when bookings are made. This will override the default emails located in your %s settings page.', 'em-pro' ), '<a href="' . admin_url( 'edit.php?post_type=event&page=events-manager-options#emails:multiple-booking-emails' ) . '">' . __( 'Multiple Booking Email Templates', 'em-pro' ) . '</a>' );
			$default_emails[ $gateway . '-mb' ]['text'] .= '<p>' . __( 'Note that some gateways do not automatically send pending or confirmed emails, in these cases they may only apply to when event admins manually change the status of a booking resulting in an automated email getting sent.', 'em-pro' ) . '</p>';
			$default_emails[ $gateway . '-mb' ]['text'] .= '<p>' . __( 'Click on the title texts with a plus (+) next to them to reveal further options, and the minus (-) sign to hide them.', 'em-pro' ) . '</p>';
			//get default mb values and merge them into email values
			$mb_default_email_values = self::get_default_email_values( $Gateway, true );
			//get custom values if applicable
			$mb_email_values = self::merge_gateway_default_values( $gateway, $mb_default_email_values, $gateway_email_values );
			//merge them all together
			$email_values = array_merge( $email_values, $mb_email_values );
		}
		self::emails_editor( $email_values, $default_emails, $admin_emails );
		do_action( 'after_gatweay_custom_emails', $Gateway, $email_values, $default_emails, $default_email_values, $admin_emails );
	}

	/**
	 * @param $default_emails
	 * @param \EM\Payments\Gateway $Gateway
	 *
	 * @return mixed
	 */
	public static function add_gateway_mb_default_emails( $default_emails, $Gateway ) {
		$gateway                            = $Gateway::$gateway;
		$default_emails[ $gateway . '-mb' ] = $default_emails[ $gateway ];
		$default_emails[ $gateway . '-mb' ]['subgroups'][ $gateway . '-mb-admin' ] = $default_emails[ $gateway . '-mb' ]['subgroups'][ $gateway . '-admin' ];
		$default_emails[ $gateway . '-mb' ]['subgroups'][ $gateway . '-mb-user' ]  = $default_emails[ $gateway . '-mb' ]['subgroups'][ $gateway . '-user' ];
		unset( $default_emails[ $gateway . '-mb' ]['subgroups'][ $gateway . '-admin' ] );
		unset( $default_emails[ $gateway . '-mb' ]['subgroups'][ $gateway . '-user' ] );
		return $default_emails;
	}

	/**
	 * Updates the custom email settings for a gateway when a gateway settings page is updated.
	 *
	 * @param \EM\Payments\Gateway $Gateway
	 */
	public static function em_gateway_update( $Gateway ) {
		//update templates
		$default_emails = self::get_gateway_default_emails( $Gateway );
		if ( get_option( 'dbem_multiple_bookings' ) ) {
			$default_emails = self::add_gateway_mb_default_emails( $default_emails, $Gateway );
		}
		$custom_booking_emails = self::editor_get_post( $default_emails );
		$Gateway::update_option( 'emails', serialize( $custom_booking_emails ) );
		//update admin email addresses
		$custom_admin_emails = array();
		if ( em_get_option( 'dbem_custom_emails_gateways_admins' ) ) {
			$custom_admin_emails = self::update_gateway_admin_emails( $Gateway, $default_emails );
			if ( $custom_admin_emails === false ) {
				global $EM_Notices;
				$EM_Notices->add_error( __( 'An invalid admin email was supplied for your custom emails and was not saved in your settings.', 'em-pro' ), true );
			} else {
				$Gateway::update_option( 'emails_admins', serialize( $custom_admin_emails ) );
			}
		}
		do_action( 'em_custom_emails_admin_gateway_update', $Gateway, $default_emails, $custom_booking_emails, $custom_admin_emails );
	}

	/**
	 * @param \EM\Payments\Gateway $Gateway
	 * @param array $default_emails
	 * @param string $param
	 *
	 * @return array|false
	 */
	public static function update_gateway_admin_emails( $Gateway, $default_emails = array(), $param = 'em_custom_email_admins' ) {
		$custom_admin_emails = self::editor_admin_emails_get_post( $default_emails, $param );
		//validate emails, strip out invalid emails
		$email_errors = false;
		if ( ! empty( $custom_admin_emails ) && is_array( $custom_admin_emails ) ) {
			foreach ( $custom_admin_emails as $group_key => $emails ) {
				if ( ! empty( $emails ) ) {
					$emails = explode( ',', $emails );
					foreach ( $emails as $email ) {
						if ( ! is_email( $email ) ) {
							unset( $custom_admin_emails[ $group_key ] );
							$email_errors = true;
						}
					}
				} else {
					$custom_admin_emails[ $group_key ] = ''; //empty = no email
				}
			}
		}
		if ( $email_errors ) {
			return false;
		} else {
			return $custom_admin_emails;
		}
	}

	/**
	 * @param \EM\Payments\Gateway | string $Gateway
	 *
	 * @return mixed|null
	 */
	public static function get_gateway_default_emails( $Gateway = null ) {
		$emails   = array();
		$gateways = $Gateway && class_exists( $Gateway ) ? array( $Gateway::$gateway => $Gateway ) : \EM\Payments\Gateways::active_gateways();
		foreach ( $gateways as $gateway => $Gateway ) {
			$emails[ $gateway ] = array(
				'title'     => sprintf( __( '%s Gateway Emails', 'em-pro' ), $Gateway::$title ),
				'subgroups' => array(
					$gateway . '-admin' => array(
						'title'  => __( 'Event Owner Emails', 'em-pro' ),
						'text'   => __( 'These emails get sent to the event owners when a person has made a booking using this specific gateway.', 'em-pro' ),
						'emails' => array(
							0 => array( 'title' => emp__( 'Pending booking email', 'events-manager' ) ),
							1 => array( 'title' => emp__( 'Confirmed booking email', 'events-manager' ) ),
							2 => array( 'title' => emp__( 'Rejected booking email', 'events-manager' ) ),
							3 => array( 'title' => emp__( 'Booking cancelled', 'events-manager' ) ),
						),
					),
					$gateway . '-user'  => array(
						'title'  => __( 'Attendee Emails', 'em-pro' ),
						'text'   => __( 'These emails will be sent to the person who booked a place at your event and selected this specific gateway.', 'em-pro' ),
						'emails' => array(
							0 => array( 'title' => emp__( 'Pending booking email', 'events-manager' ) ),
							1 => array( 'title' => emp__( 'Confirmed booking email', 'events-manager' ) ),
							2 => array( 'title' => emp__( 'Rejected booking email', 'events-manager' ) ),
							3 => array( 'title' => emp__( 'Booking cancelled', 'events-manager' ) ),
						),
					),
				),
			);
			//temporary fix, we assume everything is online except for offline - maybe a good reason for split offline/online base gateway subclasses
			if ( $gateway == 'offline' ) {
				$emails[ $gateway ]['subgroups'][ $gateway . '-admin' ]['emails'][5] = array( 'title' => __( 'Awaiting Offline Payment', 'em-pro' ) );
				$emails[ $gateway ]['subgroups'][ $gateway . '-user' ]['emails'][5]  = array( 'title' => __( 'Awaiting Offline Payment', 'em-pro' ) );
			}
			// apply generic filters afterwards so the workaround above is applied too
			$emails[ $gateway ]['subgroups'][ $gateway . '-user' ]['emails']  = apply_filters( 'em_custom_emails_admin_default_emails_subgroup', $emails[ $gateway ]['subgroups'][ $gateway . '-user' ]['emails'], 'user', $gateway );
			$emails[ $gateway ]['subgroups'][ $gateway . '-admin' ]['emails'] = apply_filters( 'em_custom_emails_admin_default_emails_subgroup', $emails[ $gateway ]['subgroups'][ $gateway . '-admin' ]['emails'], 'admin', $gateway );
		}
		return apply_filters( 'em_custom_emails_gateway_admin_gateway_default_emails', $emails, $Gateway );
	}

	/**
	 * @param string $gateway
	 * @param array $email_values
	 * @param array $possible_email_values
	 * @param bool $messages_only
	 *
	 * @return array
	 */
	public static function merge_gateway_default_values( $gateway, $email_values, $possible_email_values, $messages_only = false ) {
		if ( is_array( $possible_email_values ) ) {
			foreach ( $possible_email_values as $subgroup_name => $subgroup_msgs ) {
				foreach ( $subgroup_msgs as $msg_key => $msg_data ) {
					if ( isset( $email_values[ $subgroup_name ][ $msg_key ]['status'] ) && $email_values[ $subgroup_name ][ $msg_key ]['status'] != 1 ) {
						if ( $msg_data['status'] == 1 ) {
							if ( ! $messages_only ) {
								//gateway default is either disabled or set to the default, so we just override the status
								$email_values[ $subgroup_name ][ $msg_key ]['status'] = 1;
							}
							//add the new default subject/message to email values (without changing the status)
							$email_values[ $subgroup_name ][ $msg_key ]['subject'] = $msg_data['subject'];
							$email_values[ $subgroup_name ][ $msg_key ]['message'] = $msg_data['message'];
						} else {
							if ( ! $messages_only ) {
								//gateway default is either disabled or set to the default, so we just override the status
								$email_values[ $subgroup_name ][ $msg_key ] = array_merge( $email_values[ $subgroup_name ][ $msg_key ], $msg_data );
							}
						}
					}
				}
			}
		}
		return $email_values;
	}

	/*
	 * --------------------------------------------
	 * Custom Event Booking Emails
	 * --------------------------------------------
	 */

	public static function meta_boxes() {
		if ( current_user_can( self::$caps['custom_emails'] ) ) {
			// All event CPTs including repeating variants (event-recurring, event-<archetype>-repeating)
			$screens = Archetypes::get_cpts( ['location'] );
			add_meta_box( 'em-event-custom-emails', __( 'Custom Automated Emails', 'em-pro' ), array( 'EM_Custom_Emails_Admin', 'event_meta_box' ), $screens, 'normal', 'low' );
		}
	}

	/**
	 * Register the Custom Automated Emails metabox as an "Emails" tab in the event editor (EM core's em_event_editor_tabs registry). canvas_support is false because the message TinyMCE editors don't survive the Gutenberg canvas iframe — in the tabs layout it folds in natively; in the canvas/metaboxes layouts it renders as a normal metabox. If the user lacks the custom-emails cap the metabox isn't registered, so the engine simply skips this tab.
	 */
	public static function em_event_editor_tab( $tabs ) {
		if ( ! current_user_can( self::$caps['custom_emails'] ) ) {
			return $tabs; // no cap => the metabox isn't registered, so don't advertise the tab either
		}
		$tabs['emails'] = array(
			'label'          => __( 'Emails', 'em-pro' ),
			'priority'       => 50,
			'icon'           => 'dashicons-email',
			'canvas_support' => true,
			'metaboxes'      => array( 'em-event-custom-emails' ),
		);
		return $tabs;
	}

	public static function event_meta_box() {
		global $EM_Event;
		//get custom email values if they exist
		$custom_email_values = EM_Custom_Emails::get_event_emails( $EM_Event );
		$custom_admin_emails = false;
		if ( em_get_option( 'dbem_custom_emails_events_admins' ) ) {
			$custom_admin_emails = EM_Custom_Emails::get_event_admin_emails( $EM_Event );
		}
		if ( get_option( 'dbem_multiple_bookings' ) ) {
			//warn users that these emails only apply when resending emails in multipl bookings mode
			echo '<p class="em-event-custom-emails-multiple-bookings-warning" style="font-style:italic; font-weight:bold;">';
			echo sprintf( esc_html__( 'Since %s is enabled, these emails will only be sent when individual bookings are modified afterwards, such as changing the status of the booking individually or resending an email.', 'em-pro' ), esc_html__( 'Multiple Bookings Mode', 'em-pro' ) );
			echo '</p>';
		}
		echo '<p>' . sprintf( __( 'Below you can modify the emails that are sent when bookings are made. This will override the default emails located in your %s settings page.', 'em-pro' ), '<a href="' . admin_url( 'edit.php?post_type=event&page=events-manager-options#emails:booking-emails' ) . '">' . esc_html__emp( 'Booking Email Templates', 'events-manager' ) . '</a>' );
		if ( em_get_option( 'dbem_custom_emails_gateways' ) ) {
			echo '<p>' . sprintf( __( 'You can also create default emails for specific gateways in your individual %s settings page.', 'em-pro' ), '<a href="' . admin_url( 'edit.php?post_type=event&page=events-manager-gateways' ) . '">' . __( 'Gateway Settings', 'em-pro' ) . '</a>' );
		}
		echo '<p>' . __( 'Click on the title texts with a plus (+) next to them to reveal further options, and the minus (-) sign to hide them.', 'em-pro' ) . '</p>';
		self::emails_editor( $custom_email_values, array(), $custom_admin_emails );
	}

	public static function em_event_get_post_meta( $result, $EM_Event ) {
		if ( current_user_can( self::$caps['custom_emails'] ) ) {
			$EM_Event->custom_booking_emails = self::editor_get_post();
			if ( em_get_option( 'dbem_custom_emails_events_admins' ) ) {
				$EM_Event->custom_admin_emails = self::editor_admin_emails_get_post();
			}
		}
		return $result;
	}

	public static function em_event_validate_meta( $result, $EM_Event ) {
		//validate emails
		$email_errors = false;
		if ( ! empty( $EM_Event->custom_admin_emails ) && is_array( $EM_Event->custom_admin_emails ) ) {
			foreach ( $EM_Event->custom_admin_emails as $group_key => $emails ) {
				if ( ! empty( $emails ) ) {
					$emails = explode( ',', $emails );
					foreach ( $emails as $email ) {
						if ( ! is_email( $email ) ) {
							unset( $EM_Event->custom_admin_emails[ $group_key ] );
							$email_errors = true;
						}
					}
				}
			}
		}
		if ( $email_errors ) {
			global $EM_Notices;
			$EM_Notices->add_error( __( 'An invalid admin email was supplied for your custom emails and was not saved in your settings.', 'em-pro' ), true );
		}
		return $result;
	}

	public static function em_event_save_meta( $result, $EM_Event ) {
		global $wpdb;
		if ( current_user_can( self::$caps['custom_emails'] ) && ! empty( $EM_Event->post_id ) ) {
			if ( ! empty( $EM_Event->custom_booking_emails ) ) {
				$sql     = $wpdb->prepare( 'SELECT meta_id FROM ' . EM_META_TABLE . ' WHERE object_id = %d AND meta_key = %s LIMIT 1', $EM_Event->event_id, 'event-emails' );
				$meta_id = $wpdb->get_var( $sql );
				if ( $meta_id > 0 ) {
					$wpdb->update( EM_META_TABLE, array( 'meta_value' => serialize( $EM_Event->custom_booking_emails ) ), array( 'meta_id' => $meta_id ), array( '%s' ) );
				} else {
					$wpdb->insert(
						EM_META_TABLE,
						array(
							'object_id'  => $EM_Event->event_id,
							'meta_key'   => 'event-emails',
							'meta_value' => serialize( $EM_Event->custom_booking_emails ),
						),
						array( '%d', '%s', '%s' )
					);
				}
			} elseif ( isset( $EM_Event->custom_booking_emails ) ) {
				//only delete if custom_booking_emails property is set, since that only happens when populating a specific event in the admin, not another event on the side
				$sql = $wpdb->prepare( 'DELETE FROM ' . EM_META_TABLE . ' WHERE object_id = %d AND meta_key = %s LIMIT 1', $EM_Event->event_id, 'event-emails' );
				$wpdb->query( $sql );
			}
			if ( em_get_option( 'dbem_custom_emails_events_admins' ) ) {
				if ( ! empty( $EM_Event->custom_admin_emails ) ) {
					$sql     = $wpdb->prepare( 'SELECT meta_id FROM ' . EM_META_TABLE . ' WHERE object_id = %d AND meta_key = %s LIMIT 1', $EM_Event->event_id, 'event-admin-emails' );
					$meta_id = $wpdb->get_var( $sql );
					if ( $meta_id > 0 ) {
						$wpdb->update( EM_META_TABLE, array( 'meta_value' => serialize( $EM_Event->custom_admin_emails ) ), array( 'meta_id' => $meta_id ), array( '%s' ) );
					} else {
						$wpdb->insert(
							EM_META_TABLE,
							array(
								'object_id'  => $EM_Event->event_id,
								'meta_key'   => 'event-admin-emails',
								'meta_value' => serialize( $EM_Event->custom_admin_emails ),
							),
							array( '%d', '%s', '%s' )
						);
					}
				} elseif ( isset( $EM_Event->custom_admin_emails ) ) {
					//only delete if custom_admin_emails property is set, since that only happens when populating a specific event in the admin, not another event on the side
					$sql = $wpdb->prepare( 'DELETE FROM ' . EM_META_TABLE . ' WHERE object_id = %d AND meta_key = %s LIMIT 1', $EM_Event->event_id, 'event-admin-emails' );
					$wpdb->query( $sql );
				}
			}
		}
		return $result;
	}

	public static function em_event_save_events( $result, $EM_Event, $event_ids, $post_ids ) {
		global $wpdb;
		if ( $result && current_user_can( self::$caps['custom_emails'] ) ) {
			//delete all previous records of event coupons
			if ( ! empty( $event_ids ) ) {
				$wpdb->query( 'DELETE FROM ' . EM_META_TABLE . " WHERE (meta_key='event-admin-emails' OR meta_key='event-emails') AND object_id IN (" . implode( ',', $event_ids ) . ')' );
			}
			//create inserts
			$inserts = array();
			if ( ! empty( $EM_Event->custom_booking_emails ) ) {
				foreach ( $event_ids as $event_id ) {
					$inserts[] = $wpdb->prepare( "(%d, 'event-emails', %s)", array( $event_id, serialize( $EM_Event->custom_booking_emails ) ) );
				}
			}
			if ( ! empty( $EM_Event->custom_admin_emails ) ) {
				foreach ( $event_ids as $event_id ) {
					$inserts[] = $wpdb->prepare( "(%d, 'event-admin-emails', %s)", array( $event_id, serialize( $EM_Event->custom_admin_emails ) ) );
				}
			}
			if ( ! empty( $inserts ) ) {
				$sql = 'INSERT INTO ' . EM_META_TABLE . ' (object_id, meta_key, meta_value) VALUES ' . implode( ', ', $inserts );
				$wpdb->query( $sql );
			}
		}
		return $result;
	}
}
EM_Custom_Emails_Admin::init();
