<?php

/**
 * Stacking Card Child Module.
 *
 * @package DiviSupreme.
 */

declare(strict_types=1);

namespace DiviSupreme\Modules;

if (!defined('ABSPATH')) {
	die('Direct access forbidden.');
}

use ET\Builder\Framework\DependencyManagement\Interfaces\DependencyInterface;
use ET\Builder\Framework\Utility\HTMLUtility;
use ET\Builder\FrontEnd\Module\Style;
use ET\Builder\Packages\Module\Module;
use ET\Builder\Packages\Module\Options\Element\ElementClassnames;
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
use ET\Builder\Packages\Module\Layout\Components\StyleCommon\CommonStyle;
use ET\Builder\Packages\StyleLibrary\Utils\StyleDeclarations;
use ET\Builder\Packages\IconLibrary\IconFont\Utils;
use ET\Builder\Packages\Module\Options\Css\CssStyle;
use ET\Builder\FrontEnd\BlockParser\BlockParserStore;
use DiviSupreme\Extensions\IconLibraries\LegacyModuleIconStyles;


/**
 * Class that handles "StackingCardChild Module" module.
 */
class StackingCardChild implements DependencyInterface
{


	/**
	 * Register module.
	 * `DependencyInterface` interface ensures class method name `load()` is executed for initialization.
	 */
	public function load()
	{
		add_action('init', array(self::class, 'register_module'));
	}

	/**
	 * Initilises the module.
	 *
	 * @return void
	 */
	public static function dsm_initialise()
	{
		add_action(
			'divi_module_library_modules_dependency_tree',
			function ($dependency_tree) {
				$dependency_tree->add_dependency(new self());
			}
		);
	}

	/**
	 * Register module.
	 */
	public static function register_module()
	{

		$module_json_path = DSM_DIR_PATH . 'divi-5/public/packages/module-library/stacking-card-child';

		ModuleRegistration::register_module(
			$module_json_path,
			array(
				'render_callback' => array(self::class, 'render_callback'),
			)
		);
	}

	public static function dsm_icon_style_declaration($params)
	{
		return LegacyModuleIconStyles::build_pseudo_icon_declaration( $params );
	}

	/**
	 * Render module style.
	 *
	 * @param array $args - Arguments.
	 */
	public static function module_styles($args)
	{
		$attrs = $args['attrs'] ?? array();
		$elements = $args['elements'];
		$tooltip_placement = $attrs['tooltip_placement']['innerContent']['desktop']['value'] ?? '';

		Style::add(
			array(
				'id' => $args['id'],
				'name' => $args['name'],
				'orderIndex' => $args['orderIndex'],
				'storeInstance' => $args['storeInstance'],
				'styles' => array(
					// Module.
					$elements->style(
						array(
							'attrName' => 'module',
							'styleProps' => array(
								'disabledOn' => array(
									'disabledModuleVisibility' => $args['settings']['disabledModuleVisibility'] ?? null,
								),
							),
						)
					),

					CssStyle::style(
						array(
							'selector' => $args['orderClass'],
							'attr' => $attrs['css'] ?? array(),
						)
					),

					$elements->style(
						array(
							'attrName' => 'dsm_title',
						)
					),

					$elements->style(
						array(
							'attrName' => 'dsm_content',
						)
					),

					$elements->style(
						array(
							'attrName' => 'button',
						)
					),

					$elements->style(
						array(
							'attrName' => 'card_style',
						)
					),

					$elements->style(
						array(
							'attrName' => 'icon_style',
						)
					),

					$elements->style(
						array(
							'attrName' => 'image_style',
						)
					),

					$elements->style(
						array(
							'attrName' => 'image_spacing',
						)
					),

					$elements->style(
						array(
							'attrName' => 'icon_padding',
						)
					),

					$elements->style(
						array(
							'attrName' => 'icon_margin',
						)
					),

					$elements->style(
						array(
							'attrName' => 'dsm_card_spacing',
						)
					),

					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child .dsm_image_wrapper img",
							'attr' => $attrs['image_width']['innerContent'] ?? array(),
							'property' => 'width',
						)
					),

					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child",
							'attr' => $attrs['dsm_bg_color']['innerContent'] ?? array(),
							'property' => 'background-color',
						)
					),


					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child .dsm_icon::before",
							'attr' => $attrs['dsm_icon_color']['innerContent'] ?? array(),
							'property' => 'color',
						)
					),

					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child .dsm_icon::before",
							'attr' => $attrs['dsm_icon_bg_color']['innerContent'] ?? array(),
							'property' => 'background-color',
						)
					),

					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child .dsm_icon::before",
							'attr' => $attrs['dsm_icon_font_size']['innerContent'] ?? array(),
							'property' => 'font-size',
						)
					),

					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child .dsm_icon",
							'attr' => $attrs['dsm_icon_align']['innerContent'] ?? array(),
							'property' => 'text-align',
						)
					),


					CommonStyle::style(
						array(
							'selector' => "{$args['orderClass']} .dsm_icon::before",
							'attr' => $attrs['font_icon']['innerContent'] ?? array(),
							'declarationFunction' => array(static::class, 'dsm_icon_style_declaration'),
						)
					),

					CommonStyle::style(
						array(
							'selector' => ".dsm_stacking_card_container {$args['orderClass']}.dsm_stacking_card_child .dsm-button-wrapper",
							'attr' => $attrs['button_alignment']['innerContent'] ?? array(),
							'property' => 'text-align',
						)
					),
				),
			)
		);
	}

	/**
	 * Render module script data.
	 *
	 * @param array $args - Arguments.
	 */
	public static function module_script_data($args)
	{
		$elements = $args['elements'];

		// Element Script Data Options.
		$elements->script_data(
			array(
				'attrName' => 'module',
			)
		);
	}

	/**
	 * Render module classnames.
	 *
	 * @param array $args - Arguments.
	 */
	public static function module_classnames($args)
	{
		$classnames_instance = $args['classnamesInstance'];
		$attrs = $args['attrs'];

		// Module.
		$classnames_instance->add(
			ElementClassnames::classnames(
				array(
					'attrs' => $attrs['module']['decoration'] ?? array(),
				)
			)
		);
	}

	/**
	 * Divi 5 upload `innerContent` value to a single URL string (object `{ src, id }` or legacy string).
	 *
	 * @param mixed $value Raw `innerContent.{bp}.value` for UploadContainer fields.
	 * @return string
	 */
	private static function inner_upload_src_string($value): string
	{
		if (is_string($value)) {
			return $value;
		}

		if (is_array($value)) {
			if (! empty($value['src']) && is_string($value['src'])) {
				return $value['src'];
			}
			if (! empty($value['url']) && is_string($value['url'])) {
				return $value['url'];
			}
		}

		return '';
	}

	/**
	 * Escape `src` for an `<img>` tag (allow data-URI placeholders).
	 *
	 * @param string $src Raw image URL or data URI.
	 * @return string
	 */
	private static function escape_image_src_for_attribute(string $src): string
	{
		if (preg_match('#^data:image/[a-zA-Z0-9.+-]+;base64,[a-zA-Z0-9+/=]+$#', $src)) {
			return esc_attr($src);
		}

		return esc_url($src);
	}

	/**
	 * Render module HTML output.
	 *
	 * @param array     $attrs - Modules Attributes.
	 * @param string    $content - Content.
	 * @param \WP_Block $block - Block.
	 * @param mixed     $elements - Elements.
	 */
	public static function render_callback($attrs, $content, $block, $elements)
	{

		$parent = BlockParserStore::get_parent($block->parsed_block['id'], $block->parsed_block['storeInstance']);
		$parent_attrs = $parent->attrs ?? array();

		$title = $attrs['dsm_title']['innerContent']['desktop']['value']['text'] ?? '';
		$title_tag = $attrs['dsm_title']['decoration']['font']['font']['desktop']['value']['headingLevel'] ?? '';
		$content = $attrs['dsm_content']['innerContent']['desktop']['value']['text'] ?? '';
		$button_text = $attrs['button_text']['innerContent']['desktop']['value'] ?? '';
		$button_url = $attrs['button_url']['innerContent']['desktop']['value'] ?? '';
		$url_new_window = $attrs['button_url_new_window']['innerContent']['desktop']['value'] ?? '';
		$image_raw = $attrs['image']['innerContent']['desktop']['value'] ?? '';
		$image = self::inner_upload_src_string($image_raw);
		$parent_tag = $parent_attrs['header']['decoration']['font']['font']['desktop']['value']['headingLevel'] ?? '';
		$use_icon = $attrs['use_content_icon']['innerContent']['desktop']['value'] ?? '';

		// Icon.
		$icon_settings = is_array( $attrs['font_icon']['innerContent']['desktop']['value'] ?? null )
			? $attrs['font_icon']['innerContent']['desktop']['value']
			: array();
		$icon_value    = Utils::process_font_icon( $icon_settings );
		$icon          = HTMLUtility::render(
			array(
				'tag'               => 'span',
				'attributes'        => array(
					'class' => 'dsm_icon et-pb-icon',
				),
				'childrenSanitizer' => 'et_core_esc_previously',
				'children'          => is_string( $icon_value ) ? $icon_value : '',
			)
		);

		$button_markup = sprintf(
			'<div class="dsm-button-wrapper">
			  <a %2$s %3$s class="et_pb_button">%1$s</a>
			</div>',
			$button_text,
			'' !== $button_url ? sprintf('href="%1$s" ', $button_url) : '',
			'on' === $url_new_window ? 'target="_blank" ' : ''
		);

		$container = sprintf(
			'<div class="dsm_stacking_card_wrapper">
				<div class="dsm_image_wrapper">
					%3$s
				</div>
				<div class="dsm_content_wrapper">
				  %5$s
				  %1$s
				  %2$s
				  %4$s
				</div>
			</div>',
			'' !== $title ? sprintf('<%2$s class="dsm_title">%1$s</%2$s>', $title, empty($title_tag) ? $parent_tag : $title_tag) : '',
			'' !== $content ? sprintf('<p class="dsm_content">%1$s</p>', $content) : '',
			'' !== $image ? sprintf('<img src="%1$s" alt="" />', self::escape_image_src_for_attribute($image)) : '',
			'' !== $button_text ? $button_markup : '',
			'on' === $use_icon && '' !== $icon ? sprintf('<span class="dsm_icon"></span>') : ''
		);

		// Module Inner.
		// Essentially, this is the module content.
		// Were wrapping the title and content in a div with class `et_pb_module_inner`.
		$module_inner = HTMLUtility::render(
			array(
				'tag' => 'div',
				'attributes' => array(
					'class' => 'et_pb_module_inner',
				),
				'childrenSanitizer' => 'et_core_esc_previously',
				'children' => $container,
			)
		);

		// This are the module elements that will be rendered in the frontend.

		$module_elements = $elements->style_components(
			array(
				'attrName' => 'module',
			)
		);

		// This are the children of the module container, which are the module elements and the module inner.
		$module_container_children = $module_elements . $container;

		return Module::render(
			array(
				'orderIndex' => $block->parsed_block['orderIndex'],
				'storeInstance' => $block->parsed_block['storeInstance'],
				'tag' => 'div',
				'attrs' => $attrs,
				'elements' => $elements,
				'id' => $block->parsed_block['id'],
				'name' => $block->block_type->name,
				'classnamesFunction' => array(self::class, 'module_classnames'),
				'moduleCategory' => $block->block_type->category,
				'stylesComponent' => array(self::class, 'module_styles'),
				'scriptDataComponent' => array(self::class, 'module_script_data'),
				'children' => $module_container_children,
			)
		);
	}
}