<?php
namespace SabaiApps\Directories\Component\Notification\Sender;

use SabaiApps\Directories\Component\Form\Form;
use SabaiApps\Directories\Component\Field\Type\IEmail;

class EmailSender extends AbstractSender {

	protected function _notificationSenderInfo() {
		return array(
			'label'                 => __( 'Email', 'directories-pro' ),
			'default_settings'      => array(
				'recipients' => array(
					'event'  => null,
					'site'   => null,
					'role'   => null,
					'roles'  => null,
					'email'  => null,
					'emails' => null,
				),
				'subject'    => null,
				'body'       => null,
			),
			'event_recipient_types' => array( 'author', 'parent_author', 'user', 'email' ),
		);
	}

	public function notificationSenderSettingsForm( array $settings, array $messageMeta, array $parents = array() ) {
		return array(
			'recipients' => array(
				'#title' => __( 'E-mail recipients', 'directories-pro' ),
				'site'   => array(
					'#type'          => 'checkbox',
					'#title'         => __( 'Site E-mail', 'directories-pro' ) . ' - ' . $this->_application->getPlatform()->getSiteEmail(),
					'#default_value' => ! empty( $settings['recipients']['site'] ),
					'#weight'        => 2,
					'#switch'        => false,
					'#class'         => DRTS_BS_PREFIX . 'mb-0',
				),
				'role'   => array(
					'#type'          => 'checkbox',
					'#title'         => __( 'Select user roles', 'directories-pro' ),
					'#default_value' => ! empty( $settings['recipients']['role'] ),
					'#weight'        => 3,
					'#switch'        => false,
					'#class'         => DRTS_BS_PREFIX . 'mb-0',
				),
				'roles'  => array(
					'#type'          => 'checkboxes',
					'#columns'       => 4,
					'#multiple'      => true,
					'#multiselect'   => true,
					'#default_value' => $settings['recipients']['roles'],
					'#weight'        => 4,
					'#options'       => $this->_application->getPlatform()->getRoles(),
					'#class'         => DRTS_BS_PREFIX . 'ms-4',
					'#states'        => array(
						'visible' => array(
							sprintf( '[name="%s[role][]"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( 'recipients' ) ) ) ) => array(
								'type'  => 'checked',
								'value' => true,
							),
						),
					),
				),
				'email'  => array(
					'#type'          => 'checkbox',
					'#title'         => __( 'Enter e-mail addresses', 'directories-pro' ),
					'#default_value' => ! empty( $settings['recipients']['email'] ),
					'#weight'        => 5,
					'#switch'        => false,
					'#class'         => DRTS_BS_PREFIX . 'mb-2',
				),
				'emails' => array(
					'#type'             => 'textfield',
					'#separator'        => ',',
					'#default_value'    => $settings['recipients']['emails'],
					'#weight'           => 6,
					'#class'            => DRTS_BS_PREFIX . 'ms-4',
					'#element_validate' => array(
						function ( Form $form, &$value, $element ) {
							foreach ( array_keys( $value ) as $i ) {
								$value[ $i ] = $this->_application->Form_Validate_email( $value[ $i ] );
							}
						},
					),
					'#states'           => array(
						'visible' => array(
							sprintf( '[name="%s[email][]"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( 'recipients' ) ) ) ) => array(
								'type'  => 'checked',
								'value' => true,
							),
						),
					),
					empty( $settings['recipients']['emails'] ) ? '#placeholder' : '#description' => __( 'Enter e-mail addresses separated with commas.', 'directories-pro' ),
				),
			),
			'subject'    => array(
				'#type'                  => 'textfield',
				'#title'                 => __( 'E-mail subject', 'directories-pro' ),
				'#placeholder'           => '',
				'#description'           => isset( $messageMeta['tags'] ) ? ( $desc = $this->_application->System_Util_availableTags( $messageMeta['tags'] ) ) : null,
				'#description_no_escape' => isset( $desc ),
				'#default_value'         => $settings['subject'],
				'#required'              => true,
			),
			'body'       => array(
				'#type'                  => 'textarea',
				'#title'                 => __( 'E-mail message', 'directories-pro' ),
				'#description'           => isset( $desc ) ? $desc : null,
				'#description_no_escape' => isset( $desc ),
				'#default_value'         => $settings['body'],
				'#required'              => true,
				'#rows'                  => 10,
			),
		);
	}

	public function notificationSenderRecipientList( array $settings ) {
		$ret = array();
		if ( ! empty( $settings['recipients'] ) ) {
			if ( ! empty( $settings['recipients']['site'] ) ) {
				$ret[] = __( 'Site E-mail', 'directories-pro' );
			}
			if ( ! empty( $settings['recipients']['role'] )
				&& ! empty( $settings['recipients']['roles'] )
			) {
				$roles = $this->_application->getPlatform()->getRoles();
				foreach ( $settings['recipients']['roles'] as $role ) {
					$ret[] = $roles[ $role ];
				}
			}
			if ( ! empty( $settings['recipients']['email'] )
				&& ! empty( $settings['recipients']['emails'] )
			) {
				foreach ( $settings['recipients']['emails'] as $email ) {
					$ret[] = $email;
				}
			}
			if ( ! empty( $settings['recipients']['event'] ) ) {
				$fields = array();
				foreach ( $settings['recipients']['event'] as $event_recipient ) {
					switch ( $event_recipient ) {
						case 'author':
						case 'post_author':
							$ret[] = __( 'Post author', 'directories-pro' );
							break;
						case 'parent_author':
							$ret[] = __( 'Parent post author', 'directories-pro' );
							break;
						case 'user':
							$ret[] = __( 'User', 'directories-pro' );
							break;
						case 'comment_author':
							$ret[] = __( 'Comment author', 'directories-pro' );
							break;
						default:
							if ( strpos( $event_recipient, 'field_' ) === 0
								|| strpos( $event_recipient, 'parent_field_' ) === 0
							) {
								$fields[] = $event_recipient;
							}
					}
				}
				if ( $field_count = count( $fields ) ) {
					$field_label = __( 'E-mail field', 'directories-pro' );
					$ret[]       = $field_count > 1 ? $field_label . '(' . $field_count . ')' : $field_label;
				}
			}
		}
		return $ret;
	}

	public function notificationSenderSend( array $settings, iterable $messages ) {
		$_subject = $settings['subject'];
		$_body    = $settings['body'];
		foreach ( $messages as $message ) {
			$subject          = $this->_replaceMessageTags( isset( $message['subject'] ) ? $message['subject'] : $_subject, $message );
			$body             = $this->_replaceMessageTags( isset( $message['body'] ) ? $message['body'] : $_body, $message );
			$emails_processed = array();
			if ( ! empty( $settings['recipients']['event'] ) ) {
				foreach ( $settings['recipients']['event'] as $event_recipient ) {
					if ( ! $_recipient = $this->_getEventRecipientByMessage( $event_recipient, $message ) ) {
						$this->_application->logDebug(
							sprintf(
								'Skipping e-mail recipient of type "%s" for notification because no valid recipient could be found',
								$event_recipient
							)
						);
						continue;
					}

					if ( $_recipient['type'] === 'user' ) {
						if ( ( ! $identity = $this->_application->UserIdentity( $_recipient['value'] ) )
							|| $identity->isAnonymous()
							|| ! $identity->email
						) {
							continue;
						}

						$email = $identity->email;
					} elseif ( $_recipient['type'] === 'email' ) {
						$email = $_recipient['value'];
					} else {
						continue;
					}
					if ( ! isset( $emails_processed[ $email ] ) ) {
						$this->_sendEmail( $email, $subject, $body );
						$emails_processed[ $email ] = 1;
					}
				}
			}
			if ( ! empty( $settings['recipients']['site'] ) ) {
				if ( ( $email = $this->_application->getPlatform()->getSiteEmail() )
					&& ! isset( $emails_processed[ $email ] )
				) {
					$this->_sendEmail( $email, $subject, $body );
					$emails_processed[ $email ] = 1;
				}
			}
			if ( ! empty( $settings['recipients']['role'] ) ) {
				foreach ( (array) $settings['recipients']['roles'] as $role ) {
					foreach ( $this->_application->getPlatform()->getUsersByRole( $role ) as $identity ) {
						if ( $identity->isAnonymous()
							|| ! $identity->email
							|| isset( $emails_processed[ $identity->email ] )
						) {
							continue;
						}

						$this->_sendEmail( $identity->email, $subject, $body );
						$emails_processed[ $identity->email ] = 1;
					}
				}
			}
			if ( ! empty( $settings['recipients']['email'] ) ) {
				foreach ( (array) $settings['recipients']['emails'] as $email ) {
					if ( ! isset( $emails_processed[ $email ] ) ) {
						$this->_sendEmail( $email, $subject, $body );
						$emails_processed[ $email ] = 1;
					}
				}
			}
		}
	}

	protected function _sendEmail( $email, $subject, $body ) {
		return $this->_application->getPlatform()->mail( $email, $subject, $body );
	}

	protected function _getRecipientByEntityField( $entity, $fieldName ) {
		if ( ( $field = $this->_application->Entity_Field( $entity, $fieldName ) )
			&& ( $field_type = $this->_application->Field_Type( $field->getFieldType(), true ) )
			&& $field_type instanceof IEmail
		) {
			$this->_application->Entity_Field_load( $entity );
			if ( $field_email = $field_type->fieldEmailAddress( $field, $entity, true ) ) {
				return array(
					'type'  => 'email',
					'value' => $field_email,
				);
			}
		}
	}
}
