<?php
/**
 * "Conditional Email" ACFE Form Action Class.
 *
 * Handles the "Conditional Email" ACFE Form Action.
 *
 * @package Conditional_Form_Actions_For_ACFE
 * @since 0.1
 */

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * CiviCRM Profile Sync "Conditional Email" ACFE Form Action Class.
 *
 * A class that handles the "Conditional Email" ACFE Form Action.
 *
 * @since 0.1
 */
class CFAFA_Form_Action_Email extends CFAFA_Form_Action_Base {

	/**
	 * Plugin object.
	 *
	 * @since 0.1
	 * @access public
	 * @var object $plugin The plugin object.
	 */
	public $plugin;

	/**
	 * Parent (calling) object.
	 *
	 * @since 0.1
	 * @access public
	 * @var object $acf The parent object.
	 */
	public $acfe;

	/**
	 * Form Action Name.
	 *
	 * @since 0.1
	 * @access public
	 * @var string $action_name The unique name of the Form Action.
	 */
	public $action_name = 'email_cfafa';

	/**
	 * Field Key Prefix.
	 *
	 * @since 0.1
	 * @access public
	 * @var string $field_key The prefix for the Field Key.
	 */
	public $field_key = 'field_cfafa_email_';

	/**
	 * Field Name Prefix.
	 *
	 * @since 0.1
	 * @access public
	 * @var string $field_name The prefix for the Field Name.
	 */
	public $field_name = 'cfafa_email_';

	/**
	 * Constructor.
	 *
	 * @since 0.1
	 *
	 * @param object $parent The parent object reference.
	 */
	public function __construct( $parent ) {

		// Store references to objects.
		$this->plugin = $parent->plugin;
		$this->acfe = $parent;

		// Label this Form Action.
		$this->action_label = __( 'Conditional Email action', 'conditional-form-actions-for-acfe' );

		// Alias Placeholder for this Form Action.
		$this->alias_placeholder = __( 'Conditional Email', 'conditional-form-actions-for-acfe' );

		// Init parent.
		parent::__construct();

	}

	/**
	 * Configure this object.
	 *
	 * @since 0.1
	 */
	public function configure() {

		// Declare the mapped Email Fields with translatable titles.
		$this->mapped_email_fields = [
			'subject' => __( 'Subject', 'conditional-form-actions-for-acfe' ),
			'from_name' => __( 'From Name', 'conditional-form-actions-for-acfe' ),
			'from_email' => __( 'From Email', 'conditional-form-actions-for-acfe' ),
			'alternative_receiver_address' => __( 'Alternative Receiver Address', 'conditional-form-actions-for-acfe' ),
			'cc' => __( 'Carbon Copy', 'conditional-form-actions-for-acfe' ),
			'bcc' => __( 'Blind Carbon Copy', 'conditional-form-actions-for-acfe' ),
			//'extra_data' => __( 'Extra Data', 'conditional-form-actions-for-acfe' ),
			//'from_email_option' => __( 'From Email Option', 'conditional-form-actions-for-acfe' ),
		];

		// Populate mapping Fields.
		foreach ( $this->mapped_email_fields as $name => $title ) {
			$this->mapping_field_filters_add( $name );
		}

		// Declare the Email Contact Fields with translatable titles.
		$this->contact_fields = [
			'contact_id' => __( 'Recipient CiviCRM Contact', 'conditional-form-actions-for-acfe' ),
		];

		// Handle Contact Fields.
		foreach ( $this->contact_fields as $name => $title ) {

			// Populate mapping Fields.
			$this->mapping_field_filters_add( $name );

			// Add Contact Action Reference Field to ACF Model.
			$this->js_model_contact_reference_field_add( $this->field_name . 'ref_' . $name );

			// Pre-load with "Generic" values.
			//$filter = 'acf/prepare_field/name=' . $this->field_name . 'map_' . $name;
			//add_filter( $filter, [ $this, 'prepare_choices' ], 5 );

		}

		// Email Conditional Field.
		$this->mapping_field_filters_add( 'email_conditional' );

	}

	/**
	 * Pre-load mapping Fields with "Generic" choices.
	 *
	 * Not used but leaving this here for future use.
	 *
	 * @since 0.1
	 *
	 * @param array $field The existing array of Field data.
	 * @param array $field The modified array of Field data.
	 */
	public function prepare_choices( $field ) {

		// --<
		return $field;

	}

	/**
	 * Performs validation when the Form the Action is attached to is submitted.
	 *
	 * @since 0.1
	 *
	 * @param array $form The array of Form data.
	 * @param integer $current_post_id The ID of the Post from which the Form has been submitted.
	 * @param string $action The customised name of the action.
	 */
	public function validation( $form, $current_post_id, $action ) {

		/*
		// Get some Form details.
		$form_name = acf_maybe_get( $form, 'name' );
		$form_id = acf_maybe_get( $form, 'ID' );
		//acfe_add_validation_error( $selector, $message );
		*/

	}

	/**
	 * Performs the action when the Form the Action is attached to is submitted.
	 *
	 * @since 0.1
	 *
	 * @param array $form The array of Form data.
	 * @param integer $current_post_id The ID of the Post from which the Form has been submitted.
	 * @param string $action The customised name of the action.
	 */
	public function make( $form, $current_post_id, $action ) {

		// Bail if a filter has overridden the action.
		if ( false === $this->make_skip( $form, $current_post_id, $action ) ) {
			return;
		}

		// Get some Form details.
		$form_name = acf_maybe_get( $form, 'name' );
		$form_id = acf_maybe_get( $form, 'ID' );

		// Populate Email data array.
		$email = $this->form_email_data( $form, $current_post_id, $action );

		// Send the Email with the data from the Form.
		$email = $this->form_email_save( $email );

		// Save the results of this Action for later use.
		$this->make_action_save( $action, $email );

	}

	/**
	 * Defines additional Fields for the "Action" Tab.
	 *
	 * @since 0.1
	 *
	 * @return array $fields The array of Fields for this section.
	 */
	public function tab_action_append() {

		// Define Template Field.
		$template_field = [
			'key' => $this->field_key . 'template',
			'label' => __( 'Message Template', 'conditional-form-actions-for-acfe' ),
			'name' => $this->field_name . 'template',
			'type' => 'select',
			'instructions' => '',
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
				'data-instruction-placement' => 'field',
			],
			'acfe_permissions' => '',
			'default_value' => '',
			'placeholder' => '',
			'allow_null' => 0,
			'multiple' => 0,
			'ui' => 0,
			'return_format' => 'value',
			'choices' => $this->civicrm->email->template_options_get(),
		];

		// Define "Disable Smarty" Field.
		$smarty_field = [
			'key' => $this->field_key . 'disable_smarty',
			'label' => __( 'Disable Smarty', 'conditional-form-actions-for-acfe' ),
			'name' => $this->field_name . 'disable_smarty',
			'type' => 'true_false',
			'instructions' => __( 'Disable Smarty. Normal CiviMail tokens are still supported. By default Smarty is enabled if configured by CIVICRM_MAIL_SMARTY.', 'conditional-form-actions-for-acfe' ),
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
				'data-instruction-placement' => 'field',
			],
			'acfe_permissions' => '',
			'message' => '',
			'default_value' => 0,
			'ui' => 1,
			'ui_on_text' => '',
			'ui_off_text' => '',
		];

		// Define "Create Activity" Field.
		$create_activity_field = [
			'key' => $this->field_key . 'create_activity',
			'label' => __( 'Create Activity', 'conditional-form-actions-for-acfe' ),
			'name' => $this->field_name . 'create_activity',
			'type' => 'true_false',
			'instructions' => __( 'Usually an Email Activity is created when an Email is sent.', 'conditional-form-actions-for-acfe' ),
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
				'data-instruction-placement' => 'field',
			],
			'acfe_permissions' => '',
			'message' => '',
			'default_value' => 1,
			'ui' => 1,
			'ui_on_text' => '',
			'ui_off_text' => '',
		];

		// Define "Activity Details" Field.
		$activity_details_field = [
			'key' => $this->field_key . 'activity_details',
			'label' => __( 'Activity Details', 'conditional-form-actions-for-acfe' ),
			'name' => $this->field_name . 'activity_details',
			'type' => 'select',
			'instructions' => '',
			'required' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
				'data-instruction-placement' => 'field',
			],
			'acfe_permissions' => '',
			'default_value' => 'html,text',
			'placeholder' => '',
			'allow_null' => 0,
			'multiple' => 0,
			'ui' => 0,
			'return_format' => 'value',
			'choices' => [
				'html,text' => __( 'HTML and Text versions of the body', 'conditional-form-actions-for-acfe' ),
				'tplName' => __( 'Just the name of the message template', 'conditional-form-actions-for-acfe' ),
				'html' => __( 'Just the HTML version of the body', 'conditional-form-actions-for-acfe' ),
				'text' => __( 'Just the text version of the body', 'conditional-form-actions-for-acfe' ),
			],
			'conditional_logic' => [
				[
					[
						'field' => $this->field_key . 'create_activity',
						'operator' => '==',
						'value' => 1,
					],
				],
			],
		];

		// Init Fields.
		$fields = [
			$template_field,
			$smarty_field,
			$create_activity_field,
			$activity_details_field,
		];

		// Add Case Field if the CiviCase component is active.
		$case_active = $this->civicrm->is_component_enabled( 'CiviCase' );
		if ( $case_active ) {

			$fields[] = [
				'key' => $this->field_key . 'email_case_id',
				'label' => __( 'Case', 'conditional-form-actions-for-acfe' ),
				'name' => $this->field_name . 'email_case_id',
				'type' => 'cfafa_acfe_case_action_ref',
				'instructions' => __( 'Select a Case Action in this Form.', 'conditional-form-actions-for-acfe' ),
				'required' => 0,
				'wrapper' => [
					'width' => '',
					'class' => '',
					'id' => '',
					'data-instruction-placement' => 'field',
				],
				'acfe_permissions' => '',
				'default_value' => '',
				'placeholder' => __( 'None', 'conditional-form-actions-for-acfe' ),
				'allow_null' => 1,
				'multiple' => 0,
				'ui' => 0,
				'return_format' => 'value',
				'choices' => [],
			];

		}

		// Add Conditional Field.
		$code = 'email_conditional';
		$label = __( 'Conditional On', 'conditional-form-actions-for-acfe' );
		$conditional = $this->mapping_field_get( $code, $label );
		$conditional['placeholder'] = __( 'Always send', 'conditional-form-actions-for-acfe' );
		$conditional['wrapper']['data-instruction-placement'] = 'field';
		$conditional['instructions'] = __( 'To send the Email only when a Form Field is populated (e.g. "First Name") link this to the Form Field. To send the Email only when more complex conditions are met, link this to a Hidden Field with value "1" where the conditional logic of that Field shows it when the conditions are met.', 'conditional-form-actions-for-acfe' );
		$fields[] = $conditional;

		// --<
		return $fields;

	}

	/**
	 * Defines the "Mapping" Tab.
	 *
	 * @since 0.1
	 *
	 * @return array $fields The array of Fields for this section.
	 */
	public function tab_mapping_add() {

		// Get Tab Header.
		$mapping_tab_header = $this->tab_mapping_header();

		// Build Contacts Accordion.
		$mapping_contacts_accordion = $this->tab_mapping_accordion_contacts_add();

		// Build Email Details Accordion.
		$mapping_email_accordion = $this->tab_mapping_accordion_email_add();

		// Combine Sub-Fields.
		$fields = array_merge(
			$mapping_tab_header,
			$mapping_contacts_accordion,
			$mapping_email_accordion
		);

		// --<
		return $fields;

	}

	/**
	 * Defines the Fields in the "Contacts" Accordion.
	 *
	 * @since 0.1
	 *
	 * @return array $fields The array of Fields for this section.
	 */
	public function tab_mapping_accordion_contacts_add() {

		// Init return.
		$fields = [];

		// "Recipient Contact Reference" Accordion wrapper open.
		$fields[] = [
			'key' => $this->field_key . 'mapping_accordion_contacts_open',
			'label' => __( 'Recipient Contact Reference', 'conditional-form-actions-for-acfe' ),
			'name' => '',
			'type' => 'accordion',
			'instructions' => '',
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
			],
			'acfe_permissions' => '',
			'open' => 0,
			'multi_expand' => 1,
			'endpoint' => 0,
		];

		// Add Contact Reference Fields.
		foreach ( $this->contact_fields as $name => $title ) {

			// Bundle them into a container group.
			$contact_group_field = [
				'key' => $this->field_key . 'contact_group_' . $name,
				'label' => $title,
				'name' => $this->field_name . 'contact_group_' . $name,
				'type' => 'group',
				'instructions' => sprintf( __( 'Use one Field to identify the %s.', 'conditional-form-actions-for-acfe' ), $title ),
				'wrapper' => [
					'width' => '',
					'class' => '',
					'id' => '',
				],
				'required' => 0,
				'layout' => 'block',
			];

			// Define Contact Action Reference Field.
			$contact_group_field['sub_fields'][] = [
				'key' => $this->field_key . 'ref_' . $name,
				'label' => __( 'CiviCRM Contact Action', 'conditional-form-actions-for-acfe' ),
				'name' => $this->field_name . 'ref_' . $name,
				'type' => 'cfafa_acfe_contact_action_ref',
				'instructions' => __( 'Select a Contact Action in this Form.', 'conditional-form-actions-for-acfe' ),
				'required' => 0,
				'wrapper' => [
					'width' => '',
					'class' => '',
					'id' => '',
				],
				'acfe_permissions' => '',
				'default_value' => '',
				'placeholder' => __( 'None', 'conditional-form-actions-for-acfe' ),
				'allow_null' => 0,
				'multiple' => 0,
				'ui' => 0,
				'return_format' => 'value',
				'choices' => [],
				'conditional_logic' => [
					[
						[
							'field' => $this->field_key . 'map_' . $name,
							'operator' => '==empty',
						],
						[
							'field' => $this->field_key . 'cid_' . $name,
							'operator' => '==empty',
						],
					],
				],
			];

			// Define Contact ID Field.
			$cid_field = [
				'key' => $this->field_key . 'cid_' . $name,
				'label' => __( 'CiviCRM Contact ID', 'conditional-form-actions-for-acfe' ),
				'name' => $this->field_name . 'cid_' . $name,
				'type' => 'civicrm_contact',
				'instructions' => __( 'Select a CiviCRM Contact ID from the database.', 'conditional-form-actions-for-acfe' ),
				'required' => 0,
				'wrapper' => [
					'width' => '',
					'class' => '',
					'id' => '',
				],
				'acfe_permissions' => '',
				'default_value' => '',
				'placeholder' => __( 'None', 'conditional-form-actions-for-acfe' ),
				'allow_null' => 0,
				'multiple' => 0,
				'ui' => 0,
				'return_format' => 'value',
				'choices' => [],
				'conditional_logic' => [
					[
						[
							'field' => $this->field_key . 'ref_' . $name,
							'operator' => '==empty',
						],
						[
							'field' => $this->field_key . 'map_' . $name,
							'operator' => '==empty',
						],
					],
				],
			];

			// Add Contact ID Field.
			$contact_group_field['sub_fields'][] = $cid_field;

			// Define Custom Contact Reference Field.
			$title = sprintf( __( 'Custom Contact Reference', 'conditional-form-actions-for-acfe' ), $title );
			$mapping_field = $this->mapping_field_get( $name, $title );
			$mapping_field['instructions'] = __( 'Define a custom Contact Reference.', 'conditional-form-actions-for-acfe' );
			$mapping_field['conditional_logic'] = [
				[
					[
						'field' => $this->field_key . 'ref_' . $name,
						'operator' => '==empty',
					],
					[
						'field' => $this->field_key . 'cid_' . $name,
						'operator' => '==empty',
					],
				],
			];

			// Add Custom Contact Reference Field.
			$contact_group_field['sub_fields'][] = $mapping_field;

			// Add Contact Reference Group.
			$fields[] = $contact_group_field;

		}

		// "Recipient Contact Reference" Accordion wrapper close.
		$fields[] = [
			'key' => $this->field_key . 'mapping_accordion_contacts_close',
			'label' => __( 'Recipient Contact Reference', 'conditional-form-actions-for-acfe' ),
			'name' => '',
			'type' => 'accordion',
			'instructions' => '',
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
			],
			'acfe_permissions' => '',
			'open' => 0,
			'multi_expand' => 1,
			'endpoint' => 1,
		];

		// --<
		return $fields;

	}

	/**
	 * Defines the Fields in the "Email Fields" Accordion.
	 *
	 * @since 0.1
	 *
	 * @return array $fields The array of Fields for this section.
	 */
	public function tab_mapping_accordion_email_add() {

		// Init return.
		$fields = [];

		// "Email Fields" Accordion wrapper open.
		$fields[] = [
			'key' => $this->field_key . 'mapping_accordion_email_open',
			'label' => __( 'Email Fields', 'conditional-form-actions-for-acfe' ),
			'name' => '',
			'type' => 'accordion',
			'instructions' => '',
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
			],
			'acfe_permissions' => '',
			'open' => 0,
			'multi_expand' => 1,
			'endpoint' => 0,
		];

		// Add "Mapping" Fields.
		foreach ( $this->mapped_email_fields as $name => $title ) {
			$fields[] = $this->mapping_field_get( $name, $title );
		}

		// "Email Fields" Accordion wrapper close.
		$fields[] = [
			'key' => $this->field_key . 'mapping_accordion_email_close',
			'label' => __( 'Email Fields', 'conditional-form-actions-for-acfe' ),
			'name' => '',
			'type' => 'accordion',
			'instructions' => '',
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => [
				'width' => '',
				'class' => '',
				'id' => '',
			],
			'acfe_permissions' => '',
			'open' => 0,
			'multi_expand' => 1,
			'endpoint' => 1,
		];

		// --<
		return $fields;

	}

	/**
	 * Builds Email data array from mapped Fields.
	 *
	 * @since 0.1
	 *
	 * @param array $form The array of Form data.
	 * @param integer $current_post_id The ID of the Post from which the Form has been submitted.
	 * @param string $action The customised name of the action.
	 * @return array $data The array of Email data.
	 */
	public function form_email_data( $form, $current_post_id, $action ) {

		// Init data array.
		$data = [];

		// Get Field data.
		$data['from'] = get_sub_field( $this->field_key . 'from' );
		$data['from'] = acfe_form_map_field_value( $from, $current_post_id, $form );

		$data['reply_to'] = get_sub_field( $this->field_key . 'reply_to' );
		$data['reply_to'] = acfe_form_map_field_value( $reply_to, $current_post_id, $form );

		$data['to'] = get_sub_field($this->field_key . 'to' );
		$data['to'] = acfe_form_map_field_value( $to, $current_post_id, $form );

		$data['cc'] = get_sub_field( $this->field_key . 'cc' );
		$data['cc'] = acfe_form_map_field_value( $cc, $current_post_id, $form );

		$data['bcc'] = get_sub_field( $this->field_key . 'bcc' );
		$data['bcc'] = acfe_form_map_field_value( $bcc, $current_post_id, $form );

		$data['subject'] = get_sub_field( $this->field_key . 'subject' );
		$data['subject'] = acfe_form_map_field_value( $subject, $current_post_id, $form );

		$data['content'] = get_sub_field( $this->field_key . 'content' );
		$data['content'] = acfe_form_map_field_value( $content, $current_post_id, $form );

		// Get Email Conditional Reference.
		$data['email_conditional_ref'] = get_sub_field( $this->field_key . 'map_email_conditional' );
		$conditionals = [ $data['email_conditional_ref'] ];

		// Populate array with mapped Conditional Field values.
		$conditionals = acfe_form_map_vs_fields( $conditionals, $conditionals, $current_post_id, $form );

		// Save Email Conditional.
		$data['email_conditional'] = array_pop( $conditionals );

		// --<
		return $data;

	}

	/**
	 * Sends the Conditional Email given data from mapped Fields.
	 *
	 * @since 0.1
	 *
	 * @param array $email_data The array of Email data.
	 * @return array|bool $email The Email data array, or false on failure.
	 */
	public function form_email_save( $email_data ) {

		// Init return.
		$email = false;

		// Skip if the Email Conditional Reference Field has a value.
		if ( ! empty( $email_data['email_conditional_ref'] ) ) {
			// And the Email Conditional Field has no value.
			if ( empty( $email_data['email_conditional'] ) ) {
				return $email;
			}
		}

		// Add Custom Field data if present.
		if ( ! empty ( $custom_data ) ) {
			$email_data += $custom_data;
		}

		// Unset Email Conditionals.
		if ( isset( $email_data['email_conditional'] ) ) {
			unset( $email_data['email_conditional'] );
		}
		if ( isset( $email_data['email_conditional_ref'] ) ) {
			unset( $email_data['email_conditional_ref'] );
		}

		// Strip out empty Fields.
		$email_data = $this->form_data_prepare( $email_data );

		// Sanity checks.
		if ( empty( $email_data['contact_id'] ) || empty( $email_data['template_id'] ) ) {
			return $email;
		}

		// Send the Email.
		$result = $this->civicrm->email->email_send( $email_data );

		// Bail on failure.
		if ( $result === false ) {
			return $email;
		}

		// --<
		return $result;

	}

	/**
	 * Finds the linked Contact ID when it has been mapped.
	 *
	 * @since 0.1
	 *
	 * @param string $action_name The name of the referenced Form Action.
	 * @return integer|bool $contact_id The numeric ID of the Contact, or false if not found.
	 */
	public function form_contact_id_get_mapped( $action_name ) {

		// Init return.
		$contact_id = false;

		// We need an Action Name.
		if ( empty( $action_name ) ) {
			return $contact_id;
		}

		// Get the Contact data for that Action.
		$related_contact = acfe_form_get_action( $action_name, 'contact' );
		if ( empty( $related_contact['id'] ) ) {
			return $contact_id;
		}

		// Assign return.
		$contact_id = (int) $related_contact['id'];

		// --<
		return $contact_id;

	}

	/**
	 * Finds the linked Case ID when it has been mapped.
	 *
	 * @since 0.1
	 *
	 * @param string $action_name The name of the referenced Form Action.
	 * @return integer|bool $case_id The numeric ID of the Case, or false if not found.
	 */
	public function form_case_id_get_mapped( $action_name ) {

		// Init return.
		$case_id = false;

		// We need an Action Name.
		if ( empty( $action_name ) ) {
			return $case_id;
		}

		// Get the Case ID for that Action.
		$related_case_id = acfe_form_get_action( $action_name, 'id' );
		if ( empty( $related_case_id ) ) {
			return $case_id;
		}

		// Assign return.
		$case_id = (int) $related_case_id;

		// --<
		return $case_id;

	}

} // Class ends.