<?php
/**
 * Module: JetSmartFilters Active Tags Filters.
 */
namespace Jet_Engine_Divi_Views\Components\Jet_Smart_Filters\Modules;

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

use ET\Builder\Framework\DependencyManagement\Interfaces\DependencyInterface;
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
use ET\Builder\Packages\Module\Module;
use ET\Builder\FrontEnd\BlockParser\BlockParserStore;
use ET\Builder\FrontEnd\Module\Style;
use ET\Builder\Packages\Module\Options\Text\TextStyle;
use Jet_Engine_Divi_Views\Utils;

class Active_Tags implements DependencyInterface {

	private static function get_default_settings() {
		return [
			'content_provider'             => 'not-selected',
			'apply_type'                   => 'ajax',
			'tags_label'                   => __( 'Active tags:', 'jet-smart-filters' ),
			'query_id'                     => '',
			'clear_item'                   => false,
			'clear_item_label'             => __( 'Clear', 'jet-smart-filters' ),
			'additional_providers_enabled' => false,
			'additional_providers_list'    => [
				[
					'additional_provider'       => '',
					'additional_providers_list' => '',
				],
			],
		];
	}

	private static function normalize_toggle_value( $value ) {
		if ( is_array( $value ) ) {
			return self::map_responsive_value(
				$value,
				static function ( $current ) {
					if ( is_bool( $current ) ) {
						return $current;
					}

					return in_array( $current, [ 'on', 'yes', 'true', '1', 1 ], true );
				}
			);
		}

		if ( is_bool( $value ) ) {
			return $value;
		}

		return in_array( $value, [ 'on', 'yes', 'true', '1', 1 ], true );
	}

	private static function get_prepared_attrs( $attrs ) {
		$defaults = self::get_default_settings();
		$prepared = $defaults;

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

		if ( array_key_exists( 'clear_item', $prepared ) ) {
			$prepared['clear_item'] = self::normalize_toggle_value( $prepared['clear_item'] );
		}

		if ( array_key_exists( 'additional_providers_enabled', $prepared ) ) {
			$prepared['additional_providers_enabled'] = self::normalize_toggle_value( $prepared['additional_providers_enabled'] );
		}

		return $prepared;
	}

	/**
	 * 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 = [
			'tags'       => "{$args['orderClass']} .jet-smart-filters-active-tags",
			'tags_list'  => "{$args['orderClass']} .jet-active-tags__list",
			'tags_title' => "{$args['orderClass']} .jet-active-tags__title",
			'tag'        => "{$args['orderClass']} .jet-active-tag",
			'tag_label'  => "{$args['orderClass']} .jet-active-tag__label",
			'tag_value'  => "{$args['orderClass']} .jet-active-tag__val",
			'tag_remove' => "{$args['orderClass']} .jet-active-tag__remove",
			'tag_clear'  => "{$args['orderClass']} .jet-active-tag--clear",
		];

		$title_typography = Utils\extract_typography_attrs( $attrs['module']['decoration']['titleTypography'] ?? null );
		$title_typography_styles = Utils\build_typography_styles(
			$selectors['tags_title'],
			$title_typography
		);

		$title_margin = Utils\extract_spasing_attrs( $attrs['module']['decoration']['titleMargin'] ?? null );
		$title_margin_styles = Utils\build_spacing_styles(
			$selectors['tags_title'],
			$title_margin
		);

		$filters_border = Utils\extract_border_attrs( $attrs['module']['decoration']['filtersBorder'] ?? null );
		$filters_border_styles = Utils\build_border_styles(
			$selectors['tags_list'],
			$filters_border
		);

		$filters_padding = Utils\extract_spasing_attrs( $attrs['module']['decoration']['filtersPadding'] ?? null );
		$filters_padding_styles = Utils\build_spacing_styles(
			$selectors['tags_list'],
			$filters_padding
		);

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

		$item_padding = Utils\extract_spasing_attrs( $attrs['module']['decoration']['itemPadding'] ?? null );
		$item_padding_styles = Utils\build_spacing_styles(
			$selectors['tag'],
			$item_padding
		);

		$label_typography = Utils\extract_typography_attrs( $attrs['module']['decoration']['labelTypography'] ?? null );
		$label_typography_styles = Utils\build_typography_styles(
			$selectors['tag_label'],
			$label_typography
		);

		$value_typography = Utils\extract_typography_attrs( $attrs['module']['decoration']['valueTypography'] ?? null );
		$value_typography_styles = Utils\build_typography_styles(
			$selectors['tag_value'],
			$value_typography
		);

		$remove_border = Utils\extract_border_attrs( $attrs['module']['decoration']['removeBorder'] ?? null );
		$remove_border_styles = Utils\build_border_styles(
			$selectors['tag_remove'],
			$remove_border
		);

		$remove_padding = Utils\extract_spasing_attrs( $attrs['module']['decoration']['removePadding'] ?? null );
		$remove_padding_styles = Utils\build_spacing_styles(
			$selectors['tag_remove'],
			$remove_padding
		);

		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(
									$title_typography_styles,
									$title_margin_styles,
									$filters_border_styles,
									$filters_padding_styles,
									$item_border_styles,
									$item_padding_styles,
									$label_typography_styles,
									$value_typography_styles,
									$remove_border_styles,
									$remove_padding_styles,
									[
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tags_title'],
												'attr'     => $attrs['module']['decoration']['titleColor'] ?? [],
												'property' => 'color',
											]
										],
									],
									[
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tags']}, {$selectors['tags_list']}",
												'attr'     => $attrs['module']['decoration']['filtersPosition'] ?? [],
												'property' => 'flex-direction',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag'],
												'attr'     => $attrs['module']['decoration']['filtersGapHorizontal'] ?? [],
												'property' => 'margin-right',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag'],
												'attr'     => $attrs['module']['decoration']['filtersGapVertical'] ?? [],
												'property' => 'margin-bottom',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tags_list'],
												'attr'     => $attrs['module']['decoration']['filtersBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tags_list'],
												'attr'     => $attrs['module']['decoration']['filtersAlignItems'] ?? [],
												'property' => 'align-items',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tags_list'],
												'attr'     => $attrs['module']['decoration']['filtersJustifyContent'] ?? [],
												'property' => 'justify-content',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag'],
												'attr'     => $attrs['module']['decoration']['itemMinWidth'] ?? [],
												'property' => 'min-width',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag'],
												'attr'     => $attrs['module']['decoration']['itemPosition'] ?? [],
												'property' => 'flex-direction',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag'],
												'attr'     => $attrs['module']['decoration']['itemBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover",
												'attr'     => $attrs['module']['decoration']['itemHoverBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover",
												'attr'     => $attrs['module']['decoration']['itemHoverBorderColor'] ?? [],
												'property' => 'border-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag_clear']} {$selectors['tag_value']}",
												'attr'     => $attrs['module']['decoration']['clearItemColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_clear'],
												'attr'     => $attrs['module']['decoration']['clearItemBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag_clear']}:hover {$selectors['tag_value']}",
												'attr'     => $attrs['module']['decoration']['clearItemHoverColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag_clear']}:hover",
												'attr'     => $attrs['module']['decoration']['clearItemHoverBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_label'],
												'attr'     => $attrs['module']['decoration']['labelColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover {$selectors['tag_label']}",
												'attr'     => $attrs['module']['decoration']['labelHoverColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_value'],
												'attr'     => $attrs['module']['decoration']['valueColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover {$selectors['tag_value']}",
												'attr'     => $attrs['module']['decoration']['valueHoverColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_remove'],
												'attr'     => $attrs['module']['decoration']['removeSize'] ?? [],
												'property' => 'font-size',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_remove'],
												'attr'     => $attrs['module']['decoration']['removeOffsetTop'] ?? [],
												'property' => 'top',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_remove'],
												'attr'     => $attrs['module']['decoration']['removeOffsetRight'] ?? [],
												'property' => 'right',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_remove'],
												'attr'     => $attrs['module']['decoration']['removeColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => $selectors['tag_remove'],
												'attr'     => $attrs['module']['decoration']['removeBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover {$selectors['tag_remove']}",
												'attr'     => $attrs['module']['decoration']['removeHoverColor'] ?? [],
												'property' => 'color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover {$selectors['tag_remove']}",
												'attr'     => $attrs['module']['decoration']['removeHoverBgColor'] ?? [],
												'property' => 'background-color',
											]
										],
										[
											'componentName' => 'divi/common',
											'props'         => [
												'selector' => "{$selectors['tag']}:hover {$selectors['tag_remove']}",
												'attr'     => $attrs['module']['decoration']['removeHoverBorderColor'] ?? [],
												'property' => 'border-color',
											]
										],
									],
                                )
							],
						]
					),
				],
			]
		);
	}

	/**
	 * 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 = self::get_prepared_attrs( $attrs );

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

		$filters_block_type = jet_smart_filters()->blocks->get_block_type( 'active-tags' );

		$content = $filters_block_type->render_callback( $prepared_attrs );

		return Module::render(
			[
				// FE only.
				'orderIndex'          => $block->parsed_block['orderIndex'],
				'storeInstance'       => $block->parsed_block['storeInstance'],

				// VB equivalent.
				'id'                  => $block->parsed_block['id'],
				'name'                => $block->block_type->name,
				'moduleCategory'      => $block->block_type->category,
				'attrs'               => $attrs,
				'elements'            => $elements,
				'classnamesFunction'  => [ Active_Tags::class, 'module_classnames' ],
				'stylesComponent'     => [ Active_Tags::class, 'module_styles' ],
				'scriptDataComponent' => [ Active_Tags::class, 'module_script_data' ],
				'parentAttrs'         => $parent_attrs,
				'parentId'            => $parent->id ?? '',
				'parentName'          => $parent->blockName ?? '',
				'children'            => [ $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-field';
	}

	/**
	 * Loads `DynamicField` 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 . 'active-tags/';

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