<?php
namespace Jet_Engine_Divi_Views;

// Prevent direct access to the file.
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Modules controller class
 */
class Modules_Controller {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'divi_visual_builder_assets_before_enqueue_scripts', [ $this, 'assets' ] );
		add_action( 'divi_module_library_modules_dependency_tree', [ $this, 'register_modules' ] );
		add_filter( 'block_type_metadata_settings', [ $this, 'dynamic_modules_attributes' ], 0, 2 );
		add_filter( 'render_block_data', [ $this, 'set_editor_block_data' ] );

		add_filter( 'rest_pre_dispatch', [ $this, 'maybe_merge_request_data' ], 10, 3 );
	}

	/**
	 * Merge request data with JSON payload on Block Render Rest API request.
	 * Required to correctly process block preview.
	 */
	public function maybe_merge_request_data( $result, $server, $request ) {

		// Check if this is a block-renderer REST API request
		$route = $request->get_route();

		if ( false === strpos( $route, 'wp/v2/block-renderer' ) ) {
			return $result;
		}

		if ( ! current_user_can( 'edit_posts' ) ) {
			return $result;
		}

		$payload = file_get_contents( 'php://input' );
		$payload = json_decode( $payload, true );

		if ( ! is_array( $payload ) ) {
			return $result;
		}

		$_REQUEST = array_merge( $_REQUEST, $payload );
		$_GET     = array_merge( $_GET, $payload );
		$_POST    = array_merge( $_POST, $payload );

		$request->set_query_params( wp_unslash( $_GET ) );
		$request->set_body_params( wp_unslash( $_POST ) );

		return $result;
	}

	/**
	 * @return mixed|null
	 */
	public function get_registered_blocks() {
		return apply_filters(
			'jet-engine-divi-views/modules-controller/registered-blocks',
			[
				'jet-engine-divi/dynamic-field' => [
					'block' => 'jet-engine/dynamic-field',
				],
				'jet-engine-divi/dynamic-image' => [
					'block' => 'jet-engine/dynamic-image',
				],
				'jet-engine-divi/dynamic-repeater' => [
					'block' => 'jet-engine/dynamic-repeater',
				],
				'jet-engine-divi/dynamic-meta' => [
					'block' => 'jet-engine/dynamic-meta',
				],
				'jet-engine-divi/dynamic-link' => [
					'block' => 'jet-engine/dynamic-link',
				],
				'jet-engine-divi/dynamic-terms' => [
					'block' => 'jet-engine/dynamic-terms',
				],
				'jet-engine-divi/listing-grid' => [
					'block' => 'jet-engine/listing-grid',
				],
			]
		);
	}

	/**
	 * Add JetEngine module attibutes dynamically on registration
	 *
	 * @return array
	 */
	public function dynamic_modules_attributes( $settings, $metadata ) {
		$registered_blocks = $this->get_registered_blocks();

		if ( array_key_exists( $settings['name'], $registered_blocks ) ) {
			$block = \WP_Block_Type_Registry::get_instance()->get_registered( $registered_blocks[ $settings['name'] ]['block'] );

			if ( $block ) {
				$settings['attributes'] = array_merge(
					$settings['attributes'],
					array_fill_keys( array_keys( $block->attributes ), array( 'type' => 'object' ) )
				);
			}
		}

		return $settings;
	}

	/**
	 * Register and enqueue module related assets and data
	 */
	public function assets() {

		if ( ! et_builder_d5_enabled() || ! et_core_is_fb_enabled() ) {
			return;
		}

		/**
		 * Fill assets list from the components to enqueue
		 * required script only of certain component is active
		 */
		$assets = apply_filters(
			'jet-engine-divi-views/modules-controller/assets',
			[]
		);

		$base_deps = [
			'divi-module-library',
			'divi-vendor-wp-hooks',
		];

		foreach ( $assets as $asset ) {

			$deps = ! empty( $asset['deps'] ) ? array_merge( $base_deps, $asset['deps'] ) : $base_deps;

			wp_enqueue_script(
				$asset['handle'],
				$asset['src'],
				$deps,
				JET_ENGINE_DIVI_VIEWS_VERSION,
				true
			);

			if ( ! empty( $asset['localize'] ) ) {
				wp_localize_script(
					$asset['handle'],
					$asset['localize']['object'],
					$asset['localize']['data']
				);
			}
		}
	}

	/**
	 * Register JetEngine-related modules
	 */
	public function register_modules( $dependency_tree ) {
		do_action( 'jet-engine/divi-views/register-modules', $dependency_tree );
	}

	/**
	 * Set Divi-specific block data on JetEngone-specific Block Render Rest API request.
	 * Required to correctly process block preview.
	 */
	public function set_editor_block_data( $parsed_block ) {

		if ( empty( $_REQUEST['is_jet_block_editor_render'] ) ) {
			return $parsed_block;
		}

		\ET\Builder\FrontEnd\BlockParser\BlockParserStore::maybe_new_instance();

		if ( empty( $parsed_block['id'] ) ) {
			$parsed_block['id'] = $parsed_block['blockName'] . '-0';
		}

		if ( empty( $parsed_block['storeInstance'] ) ) {
			$parsed_block['storeInstance'] = 0;
		}

		if ( empty( $parsed_block['orderIndex'] ) ) {
			$parsed_block['orderIndex'] = 0;
		}

		return $parsed_block;
	}
}
