<?php

class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step {

	/**
	 * Code for Wiaas Delivery Process Step type
	 * @var string
	 */
	public $_step_type = 'wiaas_delivery_step';
	/**
	 * Returns label for Wiass Delivery Process Step
	 * @return string
	 */
	public function get_label() {
		return esc_html__( 'Delivery Step', 'wiaas' );
	}

	/**
	 * Returns settings for wiaas delivery process step
	 * @return array
	 */
	public function get_settings() {

		$settings_api = $this->get_common_settings_api();

		$forms = Wiaas_Delivery_Process_Action::get_action_forms();
		$form_choices[] = array( 'label' => esc_html__( 'Select a Form', 'wiaas' ), 'value' => '' );
		foreach ( $forms  as $form ) {

		    $form_choices[] = array( 'label' => $form['title'], 'value' => $form['id'] );
		}

		$settings = array(
			'title'  => esc_html__( 'Wiaas Delivery Step', 'wiaas' ),
			'fields' => array(
				$settings_api->get_setting_instructions(),
				array (
					'name' => 'is_visible_to_customer',
					'label' => __( 'Visible to customer', 'wiaas' ),
					'type' => 'checkbox',
					'choices' => array(
						array(
							'label'         => __( 'Show to customer', 'wiaas' ),
							'name'          => 'is_visible_to_customer',
							'default_value' => true,
						),
					),
					'tooltip'       => __( 'Determines if this step will be shown to customer.', 'wiaas' ),
				),
				array(
					'name' => 'target_form_id',
					'label' => esc_html__( 'Action', 'wiaas' ),
					'type' => 'select',
					'onchange'    => "jQuery(this).closest('form').submit();",
					'choices' => $form_choices,
				)
			),
		);

		return $settings;
	}

	public function start() {

	    parent::start();

        $this->update_step_status('pending');

        return false;
	}

	public function evaluate_status() {

	   return $this->get_status();
    }

    public function get_status_label($status) {

	    $label = parent::get_status_label($status);

	    if (empty($label)) {

	        $label = __('Not started', 'wiaas');
        }

        return $label;
    }

	/**
     * Update status
     *
	 * @param bool $status
	 */
	public function update_step_status($status = false) {

		/**
		 * If status is being updated after manual step completion ('Next Step' or 'Previous Step') change default
         * behavior of settings status to cancelled if manual action is sending flow to next step.
         * Instead of default cancelled status set complete status for this step.
		 */
	    if ($status === 'cancelled' && $admin_action = rgpost( 'wiaas_delivery_process_navigation_action' )) {

		    list( $base_admin_action, $step_id ) = rgexplode( '|', $admin_action, 2 );

		    $next_step = gravity_flow()->get_next_step($this, $this->get_entry(), $this->get_form());
		    // going to next step
		    if ($base_admin_action === 'send_to_step' && $next_step && $next_step->get_id() == $step_id) {

			    $status = 'complete';
            }
        }

        parent::update_step_status($status);
    }

	/**
     *
	 * Process Wiaas Delivery Process Step
	 *
	 * @return bool We will always return false because step will be completed only by manual user action
	 */
	function process() {

		$form = $this->get_form();
		$entry = $this->get_entry();
		$target_form = GFAPI::get_form( $this->target_form_id );

		# if target form is not set we are done
		if (!$target_form) {
			// return false since we wait for admin to process the step
			return false;
		}

		$delivery_settings = rgar($target_form, 'wiaas_delivery_process');

		if (! $delivery_settings['automatic_action_entries_enabled']) {

		    return false;
        }

		$action_entries_ids = gform_get_meta($this->get_entry_id(), 'wiaas_delivery_step_' . $this->get_id() . '_action_entry_ids');

		// if action entries present this step is reprocessing and we should not be creating new action entries
		if (! empty($action_entries_ids)) {
			// return false since we wait for admin to process the step
			return false;
		}

		// create new entries for step action forms
		$order_field = GFCommon::get_fields_by_type($form, 'wiaas_order')[0];
		$order_id = empty($order_field) ? null : absint($entry[$order_field->id]);

		// if process has not order we cannot create actions
		if (empty($order_id)) {
			// return false since we wait for admin to process the step
			return false;
		}

		$delivery_settings = rgar($target_form, 'wiaas_delivery_process');

		switch ($delivery_settings['automatic_action_entries_type']) {

			case 'single':
				$action_entries_ids = $this->_create_single_action_entry($target_form, $order_id);
				break;
			case 'bundle':
				$action_entries_ids = $this->_create_per_bundle_action_entries($target_form, $order_id);
		}

		gform_update_meta($this->get_entry_id(), 'wiaas_delivery_step_' . $this->get_id() . '_action_entry_ids', $action_entries_ids);

		$note = $this->get_name() . ': ' . esc_html__( 'started.', 'wiaas' );
		$this->add_note( $note );

		// return false since we wait for admin to process the step
		return false;
	}

	public function workflow_detail_box($form, $args) {
		parent::workflow_detail_box($form, $args);

		$target_form = GFAPI::get_form( $this->target_form_id );

		if (empty( $target_form)) {

			return;
		}

		?>
			<h4>Step: <?php echo $this->get_name() ?></h4>
			<h4>Action: <?php echo $target_form['title'] ?></h4>
		<?php

	}

	/**
	 * Expands step entry with additional metadata to track created target actions entries id
	 *
	 * @param array $entry_meta
	 * @param int $form_id
	 *
	 * @return array
	 */
	public function get_entry_meta($entry_meta, $form_id) {
		if ($form_id === $this->get_form_id()) {
			$entry_meta['wiaas_delivery_step_' . $this->get_id() . '_action_entry_ids'] = array();
		}
		return $entry_meta;
	}



	/**
     *
	 * PRIVATE
     *
	 */


	/**
     * Create action entry to trigger subworkflow
	 * @param $target_form
	 * @param $order_id
	 *
	 * @return array
	 */
	private function _create_single_action_entry($target_form, $order_id) {

		$action_entries_ids = array();

		$new_entry = Wiaas_Order_Fields::map_order_to_entry($order_id, $target_form);

		if (empty($new_entry)) {
		    // entry cannot be created
		    return $action_entries_ids;
        }

		$new_entry['form_id'] = $target_form['id'];
		$new_entry['wiaas_delivery_process_id'] = $this->get_entry_id();
		$new_entry['wiaas_delivery_order_id'] = $order_id;

		$entry_id = GFAPI::add_entry( $new_entry );

		if ( is_wp_error( $entry_id ) ) {
			$this->log_debug( __METHOD__ .'(): failed to add entry' );
		} else {
			// store entry id
			$action_entries_ids[] = $entry_id;
		}

		return $action_entries_ids;
	}


	/**
     * Create action form entries for every bundle in order to trigger subworkflows
     *
	 * @param $target_form
	 * @param $order_id
	 *
	 * @return array
	 */
	private function _create_per_bundle_action_entries($target_form, $order_id) {

		$action_entries_ids = array();

		$bundle_items = wiaas_get_order_standard_bundle_items($order_id);

		foreach ($bundle_items as $item) {

			$new_entry = Wiaas_Order_Fields::map_order_to_entry($order_id, $target_form, $item->get_id());

			if (empty($new_entry)) {
				// entry cannot be created
				continue;
			}

			$new_entry['form_id'] = $target_form['id'];
			$new_entry['wiaas_delivery_process_id'] = $this->get_entry_id();
			$new_entry['wiaas_delivery_order_id'] = $order_id;

			$entry_id = GFAPI::add_entry( $new_entry );

			if ( is_wp_error( $entry_id ) ) {

				$this->log_debug( __METHOD__ .'(): failed to add entry' );
			} else {
				// store entry id

				$action_entries_ids[] = $entry_id;
			}
		}

		return $action_entries_ids;
	}
}
