<?php
/**
 * Module: JetEngine Dynamic Meta.
 */
namespace Jet_Engine_Divi_Views\Components\Jet_Engine\Modules;

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

use ET\Builder\Framework\DependencyManagement\Interfaces\DependencyInterface;
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
use Jet_Engine_Divi_Views\Module_Render;
use ET\Builder\FrontEnd\Module\Style;
use Jet_Engine_Divi_Views\Utils;
use Jet_Engine_Divi_Views\Components\Jet_Engine\Current_Object_Trait;

class Dynamic_Meta implements DependencyInterface {

	use Current_Object_Trait;

	/**
	 * Module's style components.
	 *
	 * This function is equivalent of JS function ModuleStyles located in
	 * module/styles.tsx.
	 *
	 * @param array $args {
	 *     An array of arguments.
	 *
	 *      @type string $id                Module ID. In VB, the ID of module is UUIDV4. In FE, the ID is order index.
	 *      @type string $name              Module name.
	 *      @type string $attrs             Module attributes.
	 *      @type string $parentAttrs       Parent attrs.
	 *      @type string $orderClass        Selector class name.
	 *      @type string $parentOrderClass  Parent selector class name.
	 *      @type string $wrapperOrderClass Wrapper selector class name.
	 *      @type string $settings          Custom settings.
	 *      @type string $state             Attributes state.
	 *      @type string $mode              Style mode.
	 *      @type ModuleElements $elements  ModuleElements instance.
	 * }
	 */
	public static function module_styles( $args ) {
		$elements                    = $args['elements'];
		$settings                    = $args['settings'] ?? [];
		$default_printed_style_attrs = $args['defaultPrintedStyleAttrs'] ?? [];
		$attrs                       = $args['attrs'] ?? [];
		$order_class                 = $args['orderClass'] ?? '';

		$selectors = [
			'wrapper'             => "{$order_class} .jet-listing-dynamic-meta",
			'item'                => "{$order_class} .jet-listing-dynamic-meta__item",
			'item_hover'          => "{$order_class} .jet-listing-dynamic-meta__item:hover",
			'item_val'            => "{$order_class} .jet-listing-dynamic-meta__item-val",
			'item_val_hover'      => "{$order_class} .jet-listing-dynamic-meta__item-val:hover",
			'item_and_val'        => "{$order_class} .jet-listing-dynamic-meta__item, {$order_class} .jet-listing-dynamic-meta__item-val",
			'item_and_val_hover'  => "{$order_class} .jet-listing-dynamic-meta__item:hover, {$order_class} .jet-listing-dynamic-meta__item-val:hover",
			'icon_path'           => "{$order_class} .jet-listing-dynamic-meta__icon svg path",
			'icon_svg'            => "{$order_class} .jet-listing-dynamic-meta__icon svg",
			'icon_img'            => "{$order_class} .jet-listing-dynamic-meta__icon img",
			'icon_svg_ltr'        => "body:not(.rtl) {$order_class} .jet-listing-dynamic-meta__icon svg",
			'icon_img_ltr'        => "body:not(.rtl) {$order_class} .jet-listing-dynamic-meta__icon img",
			'icon_svg_rtl'        => "body.rtl {$order_class} .jet-listing-dynamic-meta__icon svg",
			'icon_img_rtl'        => "body.rtl {$order_class} .jet-listing-dynamic-meta__icon img",
			'prefix'              => "{$order_class} .jet-listing-dynamic-meta__prefix",
			'suffix'              => "{$order_class} .jet-listing-dynamic-meta__suffix",
		];

		$item_typography = Utils\extract_typography_attrs( $attrs['module']['decoration']['itemTypography'] ?? null );
		$item_typography_styles = Utils\build_typography_styles(
			$selectors['item_and_val'],
			$item_typography
		);

		$item_border = Utils\extract_border_attrs( $attrs['module']['decoration']['itemBorder'] ?? null );
		$item_border_styles = Utils\build_border_styles(
			$selectors['item'],
			$item_border
		);

		$item_spacing = Utils\extract_spasing_attrs( $attrs['module']['decoration']['itemSpacing'] ?? null );
		$item_spacing_styles = Utils\build_spacing_styles(
			$selectors['item'],
			$item_spacing
		);

		$item_val_border = Utils\extract_border_attrs( $attrs['module']['decoration']['itemValBorder'] ?? null );
		$item_val_border_styles = Utils\build_border_styles(
			$selectors['item_val'],
			$item_val_border
		);

		$item_val_spacing = Utils\extract_spasing_attrs( $attrs['module']['decoration']['itemValSpacing'] ?? null );
		$item_val_spacing_styles = Utils\build_spacing_styles(
			$selectors['item_val'],
			$item_val_spacing
		);

		Style::add(
			[
				'id'            => $args['id'],
				'name'          => $args['name'],
				'orderIndex'    => $args['orderIndex'],
				'storeInstance' => $args['storeInstance'],
				'styles'        => [
					$elements->style(
						[
							'attrName'   => 'module',
							'styleProps' => [
								'defaultPrintedStyleAttrs' => $default_printed_style_attrs['module']['decoration'] ?? [],
								'disabledOn'               => [
									'disabledModuleVisibility' => $settings['disabledModuleVisibility'] ?? null,
								],
								'advancedStyles'           => array_merge(
									$item_typography_styles,
									$item_border_styles,
									$item_spacing_styles,
									$item_val_border_styles,
									$item_val_spacing_styles,
									[
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['wrapper'],
												'attr'     => $attrs['module']['decoration']['metaAlignment'] ?? [],
												'property' => 'text-align',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item'],
												'attr'     => $attrs['module']['decoration']['itemBgColor'] ?? [],
												'property' => 'background-color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_and_val'],
												'attr'     => $attrs['module']['decoration']['itemColor'] ?? [],
												'property' => 'color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_hover'],
												'attr'     => $attrs['module']['decoration']['itemBgColorHover'] ?? [],
												'property' => 'background-color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_and_val_hover'],
												'attr'     => $attrs['module']['decoration']['itemColorHover'] ?? [],
												'property' => 'color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_hover'],
												'attr'     => $attrs['module']['decoration']['itemHoverBorderColor'] ?? [],
												'property' => 'border-color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_path'],
												'attr'     => $attrs['module']['decoration']['iconColor'] ?? [],
												'property' => 'fill',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_svg'],
												'attr'     => $attrs['module']['decoration']['iconSize'] ?? [],
												'property' => 'width',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_img'],
												'attr'     => $attrs['module']['decoration']['iconSize'] ?? [],
												'property' => 'width',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_svg_ltr'],
												'attr'     => $attrs['module']['decoration']['iconGap'] ?? [],
												'property' => 'margin-right',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_img_ltr'],
												'attr'     => $attrs['module']['decoration']['iconGap'] ?? [],
												'property' => 'margin-right',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_svg_rtl'],
												'attr'     => $attrs['module']['decoration']['iconGap'] ?? [],
												'property' => 'margin-left',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['icon_img_rtl'],
												'attr'     => $attrs['module']['decoration']['iconGap'] ?? [],
												'property' => 'margin-left',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_val'],
												'attr'     => $attrs['module']['decoration']['itemValBgColor'] ?? [],
												'property' => 'background-color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_val'],
												'attr'     => $attrs['module']['decoration']['itemValColor'] ?? [],
												'property' => 'color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_val_hover'],
												'attr'     => $attrs['module']['decoration']['itemValBgColorHover'] ?? [],
												'property' => 'background-color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_val_hover'],
												'attr'     => $attrs['module']['decoration']['itemValColorHover'] ?? [],
												'property' => 'color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['item_val_hover'],
												'attr'     => $attrs['module']['decoration']['itemValHoverBorderColor'] ?? [],
												'property' => 'border-color',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['prefix'],
												'attr'     => $attrs['module']['decoration']['prefixLGap'] ?? [],
												'property' => 'margin-left',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['prefix'],
												'attr'     => $attrs['module']['decoration']['prefixRGap'] ?? [],
												'property' => 'margin-right',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['suffix'],
												'attr'     => $attrs['module']['decoration']['suffixLGap'] ?? [],
												'property' => 'margin-left',
											],
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['suffix'],
												'attr'     => $attrs['module']['decoration']['suffixRGap'] ?? [],
												'property' => 'margin-right',
											],
										],
									]
								),
							],
						]
					),
				],
			]
		);
	}

	/**
	 * Set script data of used module options.
	 *
	 * @since ??
	 *
	 * @param array $args {
	 *   Array of arguments.
	 *
	 *   @type string $id       Module id.
	 *   @type string $selector Module selector.
	 *   @type array  $attrs    Module attributes.
	 * }
	 */
	public static function module_script_data( $args ) {
	}

	/**
	 * Module classnames function for Dynamic module.
	 *
	 * This function is equivalent of JS function moduleClassnames located in
	 * src/components/dynamic-module/module-classnames.ts.
	 *
	 * @since ??
	 *
	 * @param array $args {
	 *     An array of arguments.
	 *
	 *     @type object $classnamesInstance Instance of ET\Builder\Packages\Module\Layout\Components\Classnames.
	 *     @type array  $attrs              Block attributes data that being rendered.
	 * }
	 */
	public static function module_classnames( $args ) {
	}

	/**
	 * Dynamic module render callback which outputs server side rendered HTML on the Front-End.
	 *
	 * @since ??
	 *
	 * @param array          $attrs    Block attributes that were saved by VB.
	 * @param string         $content  Block content.
	 * @param \WP_Block      $block    Parsed block object that being rendered.
	 * @param ModuleElements $elements ModuleElements instance.
	 *
	 * @return string HTML rendered of module.
	 */
	public static function render_callback( $attrs, $content, $block, $elements ) {
		$prepared_attrs = [];

		$object_was_set = self::set_current_object( $attrs );

		foreach ( $attrs as $key => $value ) {
			if ( isset( $value['innerContent']['desktop']['value'] ) ) {
				$prepared_attrs[ $key ] = $value['innerContent']['desktop']['value'];
			}
		}

		$normalize_icon_pair = function ( $icon_key, $icon_url_key ) use ( &$prepared_attrs ) {

			if ( ! empty( $prepared_attrs[ $icon_url_key ] ) && is_array( $prepared_attrs[ $icon_url_key ] ) ) {
				if ( isset( $prepared_attrs[ $icon_url_key ]['url'] ) ) {
					$prepared_attrs[ $icon_url_key ] = $prepared_attrs[ $icon_url_key ]['url'];
				}
			}

			if ( ! empty( $prepared_attrs[ $icon_key ] ) && is_array( $prepared_attrs[ $icon_key ] ) ) {
				if ( isset( $prepared_attrs[ $icon_key ]['id'] ) ) {
					$prepared_attrs[ $icon_key ] = absint( $prepared_attrs[ $icon_key ]['id'] );
				} elseif ( isset( $prepared_attrs[ $icon_key ]['url'] ) ) {
					$prepared_attrs[ $icon_url_key ] = $prepared_attrs[ $icon_key ]['url'];
					$prepared_attrs[ $icon_key ]     = 0;
				}
			}

			if ( ! empty( $prepared_attrs[ $icon_key ] ) && is_string( $prepared_attrs[ $icon_key ] ) ) {
				$icon_string = trim( $prepared_attrs[ $icon_key ] );
				if ( filter_var( $icon_string, FILTER_VALIDATE_URL ) ) {
					$prepared_attrs[ $icon_url_key ] = $icon_string;
					$prepared_attrs[ $icon_key ]     = 0;
				} else {
					$prepared_attrs[ $icon_key ] = absint( $icon_string );
				}
			}

			if ( ! empty( $prepared_attrs[ $icon_key ] ) && empty( $prepared_attrs[ $icon_url_key ] ) ) {
				$icon_url = wp_get_attachment_url( absint( $prepared_attrs[ $icon_key ] ) );
				if ( $icon_url ) {
					$prepared_attrs[ $icon_url_key ] = $icon_url;
				}
			}

			if ( empty( $prepared_attrs[ $icon_key ] ) && ! empty( $prepared_attrs[ $icon_url_key ] ) && is_string( $prepared_attrs[ $icon_url_key ] ) ) {
				$attachment_id = attachment_url_to_postid( $prepared_attrs[ $icon_url_key ] );
				if ( $attachment_id ) {
					$prepared_attrs[ $icon_key ] = absint( $attachment_id );
				}
			}
		};

		$normalize_icon_pair( 'date_selected_icon', 'date_selected_icon_url' );
		$normalize_icon_pair( 'author_selected_icon', 'author_selected_icon_url' );
		$normalize_icon_pair( 'comments_selected_icon', 'comments_selected_icon_url' );

		$normalize_toggle = function ( $value ) {
			if ( true === $value || 1 === $value || '1' === $value || 'true' === $value || 'yes' === $value || 'on' === $value ) {
				return true;
			}

			if ( false === $value || 0 === $value || '0' === $value || '' === $value || null === $value || 'false' === $value || 'no' === $value || 'off' === $value ) {
				return false;
			}

			return (bool) $value;
		};

		$prepared_attrs['date_enabled']     = isset( $prepared_attrs['date_enabled'] ) ? $normalize_toggle( $prepared_attrs['date_enabled'] ) : true;
		$prepared_attrs['author_enabled']   = isset( $prepared_attrs['author_enabled'] ) ? $normalize_toggle( $prepared_attrs['author_enabled'] ) : true;
		$prepared_attrs['comments_enabled'] = isset( $prepared_attrs['comments_enabled'] ) ? $normalize_toggle( $prepared_attrs['comments_enabled'] ) : true;

		if ( ! isset( $prepared_attrs['date_link'] ) ) {
			$prepared_attrs['date_link'] = 'archive';
		}

		if ( ! isset( $prepared_attrs['author_link'] ) ) {
			$prepared_attrs['author_link'] = 'archive';
		}

		if ( ! isset( $prepared_attrs['comments_link'] ) ) {
			$prepared_attrs['comments_link'] = 'single';
		}

		if ( ! isset( $prepared_attrs['zero_comments_format'] ) ) {
			$prepared_attrs['zero_comments_format'] = '0';
		}

		if ( ! isset( $prepared_attrs['one_comment_format'] ) ) {
			$prepared_attrs['one_comment_format'] = '1';
		}

		if ( ! isset( $prepared_attrs['more_comments_format'] ) ) {
			$prepared_attrs['more_comments_format'] = '%';
		}

		if ( ! isset( $prepared_attrs['layout'] ) ) {
			$prepared_attrs['layout'] = 'inline';
		}

		$render = self::get_jet_engine_render_instance( $prepared_attrs );
		$divi_module_render = new Module_Render();

		$content = $divi_module_render->render_content(
			$render,
			$attrs,
			$block,
			$elements,
			self::class
		);

		if ( $object_was_set ) {
			self::reset_current_object();
		}

		return $content;
	}

	/**
	 * Get JetEngine render class instance
	 */
	public static function get_jet_engine_render_instance( $attributes ) {
		return jet_engine()->listings->get_render_instance( self::get_jet_engine_render_name(), $attributes );
	}

	/**
	 * Return name of JetEngine renderer for current module
	 */
	public static function get_jet_engine_render_name() {
		return 'dynamic-meta';
	}

	/**
	 * Loads `DynamicImage` and registers Front-End render callback and REST API Endpoints.
	 *
	 * @since ??
	 *
	 * @return void
	 */
	public function load() {

		$module_json_folder_path = JET_ENGINE_DIVI_VIEWS_MODULES_JSON_PATH . 'dynamic-meta/';

		add_action(
			'init',
			function() use ( $module_json_folder_path ) {
				ModuleRegistration::register_module(
					$module_json_folder_path,
					[
						'render_callback' => [ Dynamic_Meta::class, 'render_callback' ],
					]
				);
			}
		);
	}
}
