<?php

namespace GP_Entry_Blocks\Blocks;

use GFAPI;
use GFCommon;
use GFFormsModel;

/**
 * The parent block to all other blocks in GP Entry Blocks.
 *
 * Uses <InnerBlocks />. Does not use dynamic rendering.
 *
 * @since 1.0
 */
class Entries extends Block {
	public function __construct( $path ) {
		parent::__construct( $path );

		add_action( 'template_redirect', array( $this, 'maybe_delete_entry' ) );
		add_action( 'template_redirect', array( $this, 'maybe_duplicate_entry' ) );
		add_filter( 'gform_notification_events', array( $this, 'add_deleted_notification_event' ) );
	}

	/**
	 * @param array $attributes Block attributes.
	 * @param string $content Block content.
	 * @param \WP_Block $block Block instance.
	 *
	 * @return string
	 */
	public function render( $attributes, $content, $block ) {
		$form = GFAPI::get_form( rgar( $attributes, 'formId' ) );

		if ( ! rgar( $form, 'is_active' ) || rgar( $form, 'is_trash' ) ) {
			return __( 'Oops! This form cannot be displayed.', 'gp-entry-blocks' );
		}

		$content = $this->render_notifications() . $content;

		return $content;
	}

	/**
	 * Renders a notification depending on the current global variables such as $GLOBALS['gpeb_duplicated_entry'].
	 *
	 * @return string
	 */
	public function render_notifications() {
		if ( ! empty( $GLOBALS['gpeb_duplicated_entry'] ) ) {
			return sprintf(
				'<div class="gpeb-notification gpeb-notification--success">%s</div>',
				/**
				 * Filter the notification content displayed when an entry is duplicated.
				 *
				 * @param string $notification_content The notification content.
				 * @param array $entry The entry that was duplicated.
				 *
				 * @since 1.0-alpha-2.10
				 */
				apply_filters( 'gpeb_notification_content_duplicated_entry', __( 'Entry duplicated.', 'gp-entry-blocks' ), $GLOBALS['gpeb_duplicated_entry'] )
			);
		}

		if ( ! empty( $GLOBALS['gpeb_deleted_entry'] ) ) {
			return sprintf(
				'<div class="gpeb-notification gpeb-notification--success">%s</div>',
				/**
				 * Filter the notification content displayed when an entry is deleted.
				 *
				 * @param string $notification_content The notification content.
				 * @param array $entry The entry that was deleted.
				 *
				 * @since 1.0-alpha-2.10
				 */
				apply_filters( 'gpeb_notification_content_deleted_entry', __( 'Entry deleted.', 'gp-entry-blocks' ), $GLOBALS['gpeb_deleted_entry'] )
			);
		}

		return '';
	}

	/**
	 * Add Entry Deleted as an available Notification event for Gravity Forms.
	 *
	 * @param array $events
	 *
	 * @return array Events with Deleted event added.
	 */
	public function add_deleted_notification_event( $events ) {
		$events['gpeb_deleted'] = __( 'Entry Deleted/Trashed via Entry Blocks', 'gp-entry-blocks' );

		return $events;
	}

	/**
	 * Handles processing deletion if the query params to delete are present.
	 */
	public function maybe_delete_entry() {
		$nonce           = rgget( '_wpnonce' );
		$delete_entry_id = rgget( 'delete_entry' );

		if ( ! $delete_entry_id || ! wp_verify_nonce( $nonce, "delete_entry_{$delete_entry_id}" ) ) {
			return;
		}

		$entry = GFAPI::get_entry( $delete_entry_id );

		if ( ! $entry || is_wp_error( $entry ) ) {
			return;
		}

		if ( ! gp_entry_blocks()->permissions->can_current_user_edit_entry( $entry ) ) {
			return;
		}

		$this->send_entry_deleted_notifications( $entry, GFAPI::get_form( $entry['form_id'] ) );

		/**
		 * Filter whether an entry deleted using the Delete Link in a block should skip the trash and immediately be
		 * deleted permanently.
		 *
		 * @param boolean $delete_permanently Whether the entry should skip the trash and be deleted permanently. Defaults to `false`.
		 * @param array $entry The entry being deleted.
		 *
		 * @since 1.0-alpha-1.2
		 */
		if ( apply_filters( 'gpeb_delete_entry_permanently', false, $entry ) ) {
			/**
			 * Fires before an entry will be permanently deleted by Entry Blocks.
			 *
			 * @param array $entry The entry that will be deleted.
			 *
			 * @since 1.0-alpha-1.13
			 */
			do_action( 'gpeb_delete_entry', $entry );

			GFAPI::delete_entry( $delete_entry_id );
		} else {
			/**
			 * Fires before an entry will be moved to the trash by Entry Blocks.
			 *
			 * @param array $entry The entry that will be trashed.
			 *
			 * @since 1.0-alpha-1.13
			 */
			do_action( 'gpeb_trash_entry', $entry );

			GFFormsModel::update_entry_property( $entry['id'], 'status', 'trash' );
		}

		$GLOBALS['gpeb_deleted_entry'] = $entry;
	}

	/**
	 * Send notifications that are attached to the Entry Deleted via Entry Blocks event.
	 *
	 * @param array $entry The current entry.
	 * @param array $form The current form.
	 */
	public function send_entry_deleted_notifications( $entry, $form ) {
		$notifications = GFCommon::get_notifications_to_send( 'gpeb_deleted', $form, $entry );

		GFCommon::send_notifications( wp_list_pluck( $notifications, 'id' ), $form, $entry, true, 'gpeb_deleted' );
	}

	/**
	 * Handles processing duplication if the query params to duplicate are present.
	 */
	public function maybe_duplicate_entry() {
		$nonce              = rgget( '_wpnonce' );
		$duplicate_entry_id = rgget( 'duplicate_entry' );

		if ( ! $duplicate_entry_id || ! wp_verify_nonce( $nonce, "duplicate_entry_{$duplicate_entry_id}" ) ) {
			return;
		}

		$entry = GFAPI::get_entry( $duplicate_entry_id );

		if ( ! $entry || is_wp_error( $entry ) ) {
			return;
		}

		if ( ! gp_entry_blocks()->permissions->can_current_user_edit_entry( $entry ) ) {
			return;
		}

		/**
		 * Filter an entry before it will be duplicated. Return `null` to prevent the entry from being duplicated.
		 *
		 * @param array|false|null $entry The entry being duplicated.
		 *
		 * @since 1.0-alpha-2.10
		 */
		$entry = apply_filters( 'gpeb_duplicate_entry', $entry );

		if ( ! $entry ) {
			return;
		}

		$GLOBALS['gpeb_duplicated_entry'] = GFAPI::add_entry( $entry );

		/**
		 * Action that fires after an entry has been duplicated.
		 *
		 * @param array $entry The entry that was duplicated.
		 *
		 * @since 1.0-alpha-2.10
		 */
		do_action( 'gpeb_entry_duplicated', $entry );
	}
}
