<?php
/**
 * Progress Bar module (Divi 5).
 *
 * @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\Module\Options\Text\TextStyle;
use ET\Builder\Packages\StyleLibrary\Utils\StyleDeclarations;
use ET\Builder\Packages\Module\Options\Css\CssStyle;

/**
 * Handles the Supreme Progress Bar module.
 */
class ProgressBar implements DependencyInterface {

	/**
	 * Initialize module registration on init.
	 *
	 * @return void
	 */
	public function load(): void {
		add_action( 'init', array( self::class, 'register_module' ) );
	}

	/**
	 * Legacy bootstrap (unused in Divi 5 dependency tree).
	 *
	 * @return void
	 */
	public static function dsm_initialise(): void {
		add_action(
			'divi_module_library_modules_dependency_tree',
			function ( $dependency_tree ) {
				$dependency_tree->add_dependency( new self() );
			}
		);
	}

	/**
	 * Register with Divi module library.
	 *
	 * @return void
	 */
	public static function register_module(): void {
		$module_json_path = DSM_DIR_PATH . 'divi-5/public/packages/module-library/progress-bar';

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

	/**
	 * Direction for horizontal tracker fill (RTL vs LTR).
	 *
	 * @param array<string, mixed> $params Hook args.
	 * @return string
	 */
	public static function dir_progress_direction_declaration( array $params ): string {
		$attr = $params['attrValue'] ?? array();

		$style_declarations = new StyleDeclarations(
			array(
				'returnType' => 'string',
				'important'  => array(
					'direction' => true,
				),
			)
		);

		$is_progress_direction = 'right' === $attr ? 'rtl' : 'ltr';

		$style_declarations->add( 'direction', $is_progress_direction );

		return $style_declarations->value();
	}

	/**
	 * Direction for percentage label text.
	 *
	 * @param array<string, mixed> $params Hook args.
	 * @return string
	 */
	public static function dir_percentage_direction_declaration( array $params ): string {
		$attr = $params['attrValue'] ?? array();

		$style_declarations = new StyleDeclarations(
			array(
				'returnType' => 'string',
				'important'  => array(
					'direction' => true,
				),
			)
		);

		$is_progress_direction = 'right' === $attr ? 'ltr' : 'rtl';

		$style_declarations->add( 'direction', $is_progress_direction );

		return $style_declarations->value();
	}

	/**
	 * Margin alignment for circular tracker.
	 *
	 * @param array<string, mixed> $params Hook args.
	 * @return string
	 */
	public static function dir_circle_alignment_declaration( array $params ): string {
		$attr = $params['attrValue'] ?? array();

		$style_declarations = new StyleDeclarations(
			array(
				'returnType' => 'string',
				'important'  => array(
					'margin' => true,
				),
			)
		);

		$align_value = '';

		switch ( $attr ) {
			case 'left':
				$align_value = 'auto 0 0 0';
				break;
			case 'center':
				$align_value = '0 auto';
				break;
			case 'right':
				$align_value = '0 0 0 auto';
				break;
		}

		$style_declarations->add( 'margin', $align_value );

		return $style_declarations->value();
	}

	/**
	 * Render module style.
	 *
	 * @param array<string, mixed> $args Hook args.
	 * @return void
	 */
	public static function module_styles( array $args ): void {
		$attrs    = $args['attrs'] ?? array();
		$elements = $args['elements'];

		Style::add(
			array(
				'id'              => $args['id'],
				'name'            => $args['name'],
				'orderIndex'      => $args['orderIndex'],
				'storeInstance'   => $args['storeInstance'],
				'styles'          => array(
					$elements->style(
						array(
							'attrName'   => 'module',
							'styleProps' => array(
								'disabledOn' => array(
									'disabledModuleVisibility' => $args['settings']['disabledModuleVisibility'] ?? null,
								),
							),
						)
					),
					TextStyle::style(
						array(
							'selector' => $args['orderClass'],
							'attr'     => $attrs['module']['advanced']['text'] ?? array(),
						)
					),
					CssStyle::style(
						array(
							'selector' => $args['orderClass'],
							'attr'     => $attrs['css'] ?? array(),
						)
					),
					$elements->style(
						array(
							'attrName' => 'progress_indicator_bg_color',
						)
					),
					$elements->style(
						array(
							'attrName' => 'percentage',
						)
					),
					$elements->style(
						array(
							'attrName' => 'indicatorStyle',
						)
					),
					$elements->style(
						array(
							'attrName' => 'trackerStyle',
						)
					),
					CommonStyle::style(
						array(
							'selector' => "{$args['orderClass']} .dsm-progress-bar-container.dsm-progress-bar-tracker-horizontal",
							'attr'     => $attrs['dsm_progress_height']['innerContent'] ?? array(),
							'property' => 'height',
						)
					),
					CommonStyle::style(
						array(
							'selector' => "{$args['orderClass']} .dsm-progress-bar-tracker-horizontal",
							'attr'     => $attrs['dsm_tracker_bg_color']['innerContent'] ?? array(),
							'property' => 'background',
						)
					),
					CommonStyle::style(
						array(
							'selector'            => "{$args['orderClass']} .dsm-progress-bar-container.dsm-progress-bar-tracker-horizontal",
							'attr'                => $attrs['dsm_progress_direction']['innerContent'] ?? array(),
							'declarationFunction' => array( static::class, 'dir_progress_direction_declaration' ),
						)
					),
					CommonStyle::style(
						array(
							'selector'            => "{$args['orderClass']} .dsm-progress-bar-container.dsm-progress-bar-tracker-horizontal .dsm-current-progress-percentage",
							'attr'                => $attrs['dsm_percentage_direction']['innerContent'] ?? array(),
							'declarationFunction' => array( static::class, 'dir_percentage_direction_declaration' ),
						)
					),
					CommonStyle::style(
						array(
							'selector'            => "{$args['orderClass']} .dsm-progressbar-circular",
							'attr'                => $attrs['dsm_progress_alignment']['innerContent'] ?? array(),
							'declarationFunction' => array( static::class, 'dir_circle_alignment_declaration' ),
						)
					),
					CommonStyle::style(
						array(
							'selector' => "{$args['orderClass']} .dsm-progressbar-circular",
							'attr'     => $attrs['dsm_progress_circle_size']['innerContent'] ?? array(),
							'property' => 'width',
						)
					),
					CommonStyle::style(
						array(
							'selector' => "{$args['orderClass']} .dsm-progressbar-circular",
							'attr'     => $attrs['dsm_progress_circle_size']['innerContent'] ?? array(),
							'property' => 'height',
						)
					),
				),
			)
		);
	}

	/**
	 * Render module script data.
	 *
	 * @param array<string, mixed> $args Hook args.
	 * @return void
	 */
	public static function module_script_data( array $args ): void {
		$elements = $args['elements'];

		$elements->script_data(
			array(
				'attrName' => 'module',
			)
		);
	}

	/**
	 * Render module classnames.
	 *
	 * @param array<string, mixed> $args Hook args.
	 * @return void
	 */
	public static function module_classnames( array $args ): void {
		$classnames_instance = $args['classnamesInstance'];
		$attrs               = $args['attrs'];

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

	/**
	 * Render module HTML output.
	 *
	 * @param array<string, mixed> $attrs    Block attributes.
	 * @param string               $content  Inner content.
	 * @param \WP_Block            $block    Block instance.
	 * @param mixed                $elements Module elements registry.
	 * @return string
	 */
	public static function render_callback( $attrs, $content, $block, $elements ): string {
		if ( ! is_array( $attrs ) ) {
			$attrs = array();
		}

		wp_enqueue_script( 'dsm-progress-bar' );

		$dsm_tracker_type         = $attrs['dsm_tracker_type']['innerContent']['desktop']['value'] ?? '';
		$dsm_progress_relative    = $attrs['dsm_progress_relative']['innerContent']['desktop']['value'] ?? '';
		$dsm_show_percentage      = $attrs['dsm_show_percentage']['innerContent']['desktop']['value'] ?? '';
		$dsm_progress_direction   = $attrs['dsm_progress_direction']['innerContent']['desktop']['value'] ?? '';
		$raw_progress_selector      = $attrs['dsm_progress_selector']['innerContent']['desktop']['value'] ?? '';
		$dsm_progress_selector    = is_array( $raw_progress_selector )
			? (string) ( $raw_progress_selector['text'] ?? '' )
			: (string) $raw_progress_selector;
		$dsm_indicator_color      = $attrs['dsm_indicator_color']['innerContent']['desktop']['value'] ?? '';
		$dsm_tracker_color        = $attrs['dsm_tracker_color']['innerContent']['desktop']['value'] ?? '';
		$dsm_progress_indicator_width = $attrs['dsm_progress_indicator_width']['innerContent']['desktop']['value'] ?? '';
		$dsm_progress_tracker_width   = $attrs['dsm_progress_tracker_width']['innerContent']['desktop']['value'] ?? '';

		if ( 'circular' === $dsm_tracker_type ) {
			$styles = array();

			if ( ! empty( $dsm_indicator_color ) ) {
				$styles[] = '--circle-indicator-color: ' . $dsm_indicator_color;
			}
			if ( ! empty( $dsm_tracker_color ) ) {
				$styles[] = '--circle-tracker-color: ' . $dsm_tracker_color;
			}
			if ( ! empty( $dsm_progress_indicator_width ) ) {
				$styles[] = '--circle-indicator-width: ' . $dsm_progress_indicator_width;
			}
			if ( ! empty( $dsm_progress_tracker_width ) ) {
				$styles[] = '--circle-tracker-width: ' . $dsm_progress_tracker_width;
			}

			$style_attr = ! empty( $styles ) ? ' style="' . esc_attr( implode( '; ', $styles ) ) . '"' : '';
		} else {
			$style_attr = '';
		}

		$horizontal_inner = 'horizontal' === $dsm_tracker_type
			? sprintf(
				'<div class="dsm-current-progress">%1$s</div>',
				'on' === $dsm_show_percentage ? '<div class="dsm-current-progress-percentage"></div>' : ''
			)
			: '';

		$circular_inner = 'circular' === $dsm_tracker_type
			? '<div class="dsm-progressbar-circular">
						<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
							<circle class="circle" r="40%" cx="50%" cy="50%"></circle>
							<circle class="current-progress" r="40%" cx="50%" cy="50%"></circle>
						</svg>
						<div class="dsm-current-progress-percentage"></div>
					</div>'
			: '';

		$container = sprintf(
			'<div class="dsm-progress-bar-container dsm-progress-bar-tracker-%1$s"%7$s data-relative="%2$s" data-show_percentage="%3$s" data-tracker_type="%1$s" data-direction="%4$s" data-selector="%5$s">%6$s</div>',
			esc_attr( $dsm_tracker_type ),
			esc_attr( $dsm_progress_relative ),
			esc_attr( $dsm_show_percentage ),
			esc_attr( $dsm_progress_direction ),
			esc_attr( (string) $dsm_progress_selector ),
			$horizontal_inner . $circular_inner,
			$style_attr
		);

		$module_inner = HTMLUtility::render(
			array(
				'tag'               => 'div',
				'attributes'        => array(
					'class' => 'et_pb_module_inner',
				),
				'childrenSanitizer' => 'et_core_esc_previously',
				'children'          => $container,
			)
		);

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

		return Module::render(
			array(
				'orderIndex'           => $block->parsed_block['orderIndex'],
				'storeInstance'        => $block->parsed_block['storeInstance'],
				'attrs'                => $attrs,
				'elements'             => $elements,
				'id'                   => $block->parsed_block['id'],
				'moduleClassName'      => 'dsm_progress_bar',
				'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,
			)
		);
	}
}
