<?php

namespace ElementPack\Modules\ScrollFillEffect;

use Elementor\Controls_Manager;
use Elementor\Group_Control_Background;
use ElementPack\Base\Element_Pack_Module_Base;
use ElementPack\Traits\Global_Widget_Controls;
use ElementPack\Modules\ScrollFillEffect\Atomic\Support as Atomic_Support;
use ElementPack\Modules\ScrollFillEffect\Normalizers\Settings_Normalizer;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
} // Exit if accessed directly

class Module extends Element_Pack_Module_Base {

	use Global_Widget_Controls;

	private $atomic_support = null;
	private $settings_normalizer = null;

	public function __construct() {
		parent::__construct();
		$this->add_actions();
	}

	public function get_name() {
		return 'bdt-scroll-fill-effect';
	}

	public function register_section( $element ) {
		$pro_lock = bdt_get_widget_badge( str_replace( 'bdt-', '', $this->get_name() ) );
		$element->start_controls_section(
			'section_element_pack_sfe_controls',
			[ 
				'tab'   => Controls_Manager::TAB_CONTENT,
				'label' => BDTEP_CP . esc_html__( 'Scroll Fill Effect', 'bdthemes-element-pack' ) . $pro_lock,
			]
		);
		$element->end_controls_section();
	}

	public function register_controls( $widget, $args ) {

		$widget->add_control(
			'ep_widget_sf_fx_enable',
			[ 
				'label'              => esc_html__( 'Use Scroll Fill Effect?', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::SWITCHER,
				'render_type'        => 'template',
				'default'            => '',
				'return_value'       => 'yes',
				'frontend_available' => true,
				'prefix_class'       => 'bdt-scroll-effect-',
			]
		);

		// select field contorls
		$widget->add_control(
			'ep_widget_sf_fx_animation_type',
			[ 
				'label'              => __( 'Animation Type', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::SELECT,
				'options'            => [ 
					'scroll_fill'           => __( 'Scroll Fill', 'bdthemes-element-pack' ),
					'scaling_gradient_text' => __( 'Scaling Gradient Text', 'bdthemes-element-pack' ),
					'reveal_gradient_mask'  => __( 'Gradient Text Reveal', 'bdthemes-element-pack' ),
				],
				'default'            => 'scroll_fill',
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable' => 'yes',
				],
				'prefix_class'       => 'bdt-scroll-effect-',
				'render_type'        => 'template',
			]
		);

		// notice control
		$widget->add_control(
			'ep_widget_sf_fx_notice',
			[ 
				'label' => __( 'Notice', 'bdthemes-element-pack' ),
				'type' => Controls_Manager::NOTICE,
				'notice_type' => 'info',
				'content' => __( 'Scaling Gradient Text Effect will not work in Editor Mode. You can see the effect in Preview Mode.', 'bdthemes-element-pack' ),
				'condition'          => [ 
					'ep_widget_sf_fx_enable' => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);
		// notice control
		$widget->add_control(
			'ep_widget_sf_fx_rgm_notice',
			[ 
				'label' => __( 'Notice', 'bdthemes-element-pack' ),
				'type' => Controls_Manager::NOTICE,
				'notice_type' => 'info',
				'content' => __( 'Gradient Text Reveal Effect will not work in Editor Mode. You can see the effect in Preview Mode.', 'bdthemes-element-pack' ),
				'condition' => [ 
					'ep_widget_sf_fx_enable' => 'yes',
					'ep_widget_sf_fx_animation_type' => 'reveal_gradient_mask',
				]
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_base_color',
			[ 
				'label'       => __( 'Base Color', 'bdthemes-element-pack' ),
				'type'        => Controls_Manager::COLOR,
				'default'     => 'rgba(156, 156, 156, 0.5)',
				'description' => __( 'Set the base color for the text. Must Select Transparent Color.', 'bdthemes-element-pack' ),
				'alpha'       => true,
				'condition'   => [ 
					'ep_widget_sf_fx_enable' => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scroll_fill',
				],
				'selectors'   => [ 
					'{{WRAPPER}} .elementor-heading-title'                  => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}} .bdt-heading-tag span'                     => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}} .bdt-ep-advanced-heading-main-title-inner' => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > h1'         => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > h2'         => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > h3'         => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > h4'         => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > h5'         => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > h6'         => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > p'          => '-webkit-text-fill-color: {{VALUE}};',
					'{{WRAPPER}}.elementor-widget-text-editor > div'        => '-webkit-text-fill-color: {{VALUE}};',
				],
			]
		);

		$widget->add_group_control(
			Group_Control_Background::get_type(),
			[ 
				'name'           => 'ep_widget_sf_fx_fill_bg',
				'types'          => [ 'gradient' ],
				'fields_options' => [ 
					'background' => [ 
						'label' => 'Fill Color'
					],
				],
				'condition'      => [ 
					'ep_widget_sf_fx_enable' => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scroll_fill',
				],
				'selector'       => '{{WRAPPER}} .elementor-heading-title, {{WRAPPER}} .bdt-heading-tag span, {{WRAPPER}} .bdt-ep-advanced-heading-main-title-inner, {{WRAPPER}}.elementor-widget-text-editor > h1, {{WRAPPER}}.elementor-widget-text-editor > h2, {{WRAPPER}}.elementor-widget-text-editor > h3, {{WRAPPER}}.elementor-widget-text-editor > h4, {{WRAPPER}}.elementor-widget-text-editor > h5, {{WRAPPER}}.elementor-widget-text-editor > h6, {{WRAPPER}}.elementor-widget-text-editor > p, {{WRAPPER}}.elementor-widget-text-editor > div',
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_start_scale',
			[ 
				'label'   => esc_html__( 'Start Scale', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::SLIDER,
				'range'   => [ 
					'px' => [ 
						'min'  => 0.5,
						'max'  => 5,
						'step' => 0.1,
					],
				],
				'default' => [ 
					'size' => 2,
				],
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_end_scale',
			[ 
				'label'   => esc_html__( 'End Scale', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::SLIDER,
				'range'   => [ 
					'px' => [ 
						'min'  => 0.5,
						'max'  => 3,
						'step' => 0.1,
					],
				],
				'default' => [ 
					'size' => 1,
				],
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_start_opacity',
			[ 
				'label'   => esc_html__( 'Start Opacity', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::SLIDER,
				'range'   => [ 
					'px' => [ 
						'min'  => 0,
						'max'  => 1,
						'step' => 0.1,
					],
				],
				'default' => [ 
					'size' => 0,
				],
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_end_opacity',
			[ 
				'label'   => esc_html__( 'End Opacity', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::SLIDER,
				'range'   => [ 
					'px' => [ 
						'min'  => 0,
						'max'  => 1,
						'step' => 0.1,
					],
				],
				'default' => [ 
					'size' => 1,
				],
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_start_color',
			[ 
				'label'              => __( 'Start Color', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::COLOR,
				'default'            => '#00e239',
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_end_color',
			[ 
				'label'              => __( 'End Color', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::COLOR,
				'default'            => '#ffffff',
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_stagger',
			[ 
				'label'   => esc_html__( 'Stagger Delay', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::SLIDER,
				'range'   => [ 
					'px' => [ 
						'min'  => 0,
						'max'  => 1,
						'step' => 0.01,
					],
				],
				'default' => [ 
					'size' => 0.1,
				],
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_duration',
			[ 
				'label'   => esc_html__( 'Animation Duration', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::SLIDER,
				'range'   => [ 
					'px' => [ 
						'min'  => 0.5,
						'max'  => 5,
						'step' => 0.1,
					],
				],
				'default' => [ 
					'size' => 1.5,
				],
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_start_trigger',
			[ 
				'label'   => esc_html__( 'Start Trigger', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::TEXT,
				'default' => 'top 80%',
				'description' => esc_html__( 'e.g., "top bottom" (start immediately), "top 80%", "center center"', 'bdthemes-element-pack' ),
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_sg_end_trigger',
			[ 
				'label'   => esc_html__( 'End Trigger', 'bdthemes-element-pack' ),
				'type'    => Controls_Manager::TEXT,
				'default' => 'top 30%',
				'description' => esc_html__( 'e.g., "bottom top" (end when bottom reaches top), "top 30%", "center top"', 'bdthemes-element-pack' ),
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'          => 'yes',
					'ep_widget_sf_fx_animation_type' => 'scaling_gradient_text',
				],
			]
		);

		// ── Reveal Gradient Mask — Scroll-driven controls ───────────────────

		$widget->add_control(
			'ep_widget_sf_fx_rgm_mask_color',
			[ 
				'label'              => __( 'Mask Color', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::COLOR,
				'default'            => '#000000',
				'description'        => __( 'The solid color for the gradient mask. Should match the section/page background.', 'bdthemes-element-pack' ),
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'         => 'yes',
					'ep_widget_sf_fx_animation_type' => 'reveal_gradient_mask',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_rgm_x_percent',
			[ 
				'label'       => esc_html__( 'Reveal Distance (%)', 'bdthemes-element-pack' ),
				'type'        => Controls_Manager::SLIDER,
				'range'       => [ 
					'px' => [ 
						'min'  => -200,
						'max'  => 0,
						'step' => 10,
					],
				],
				'default'     => [ 
					'size' => -100,
				],
				'description'        => esc_html__( 'How far the mask travels (as % of its own width). -100 = fully revealed.', 'bdthemes-element-pack' ),
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'         => 'yes',
					'ep_widget_sf_fx_animation_type' => 'reveal_gradient_mask',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_rgm_start_trigger',
			[ 
				'label'              => esc_html__( 'Start Trigger', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => 'top 80%',
				'description'        => esc_html__( 'When the reveal begins as the element scrolls into view. e.g. "top 80%", "top center", "top bottom".', 'bdthemes-element-pack' ),
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'         => 'yes',
					'ep_widget_sf_fx_animation_type' => 'reveal_gradient_mask',
				],
			]
		);

		$widget->add_control(
			'ep_widget_sf_fx_rgm_end_trigger',
			[ 
				'label'              => esc_html__( 'End Trigger', 'bdthemes-element-pack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => 'top 20%',
				'description'        => esc_html__( 'When the reveal is fully complete. e.g. "top 20%", "center center", "bottom top".', 'bdthemes-element-pack' ),
				'frontend_available' => true,
				'condition'          => [ 
					'ep_widget_sf_fx_enable'         => 'yes',
					'ep_widget_sf_fx_animation_type' => 'reveal_gradient_mask',
				],
			]
		);
	}

	public function enqueue_scripts() {
		wp_register_script( 'gsap', BDTEP_ASSETS_URL . 'vendor/js/gsap.min.js', [], '3.12.5', true );
		wp_register_script( 'scroll-trigger', BDTEP_ASSETS_URL . 'vendor/js/ScrollTrigger.min.js', [], '3.12.5', true );
		wp_register_script( 'ep-scroll-fill-effect', BDTEP_ASSETS_URL . 'js/modules/ep-scroll-fill-effect.min.js', [ 'jquery', 'gsap', 'scroll-trigger' ], BDTEP_VER, true );

		if ( \ElementPack\Element_Pack_Loader::elementor()->preview->is_preview_mode() || \ElementPack\Element_Pack_Loader::elementor()->editor->is_edit_mode() ) {
			wp_enqueue_script( 'gsap' );
			wp_enqueue_script( 'scroll-trigger' );
		}
	}

	public function enqueue_editor_scripts() {
		wp_register_script( 'gsap', BDTEP_ASSETS_URL . 'vendor/js/gsap.min.js', [], '3.12.5', true );
		wp_register_script( 'scroll-trigger', BDTEP_ASSETS_URL . 'vendor/js/ScrollTrigger.min.js', [ 'gsap' ], '3.12.5', true );

		wp_enqueue_script(
			'ep-scroll-fill-effect-editor',
			BDTEP_ASSETS_URL . 'js/modules/ep-scroll-fill-effect-editor.min.js',
			[ 'elementor-editor', 'gsap', 'scroll-trigger' ],
			BDTEP_VER,
			true
		);
	}

	public function should_script_enqueue( $widget ) {
		if ( $this->get_settings_normalizer()->normalize( $widget ) ) {
			$this->enqueue_scripts();
			wp_enqueue_script( 'gsap' );
			wp_enqueue_script( 'scroll-trigger' );
			wp_enqueue_script( 'ep-scroll-fill-effect' );
		}
	}

	public function register_atomic_schema( $schema ) {
		return $this->get_atomic_support()->register_schema( $schema );
	}

	public function register_atomic_controls( $controls, $element ) {
		$element_type = method_exists( $element, 'get_element_type' ) ? $element::get_element_type() : '';

		if ( 'e-heading' !== $element_type ) {
			return $controls;
		}

		return $this->get_atomic_support()->register_controls( $controls );
	}

	public function inject_atomic_scroll_fill_effect_data( $widget_content, $widget ) {
		if ( ! $this->is_atomic_heading( $widget ) ) {
			return $widget_content;
		}

		if ( ! is_string( $widget_content ) || '' === $widget_content ) {
			return $widget_content;
		}

		$settings = $this->get_settings_normalizer()->normalize( $widget );

		if ( ! $settings ) {
			return $widget_content;
		}

		if ( ! method_exists( $widget, 'get_atomic_settings' ) || false !== strpos( $widget_content, 'data-ep-scroll-fill-effect=' ) ) {
			return $widget_content;
		}

		$encoded_settings = wp_json_encode( $settings );
		$atomic_classes   = $this->get_atomic_scroll_fill_effect_classes( $settings );

		if ( class_exists( '\WP_HTML_Tag_Processor' ) ) {
			$processor = new \WP_HTML_Tag_Processor( $widget_content );

			if ( $processor->next_tag() ) {
				$processor->set_attribute( 'data-ep-scroll-fill-effect', $encoded_settings );
				$existing_classes = $processor->get_attribute( 'class' );

				if ( is_string( $existing_classes ) ) {
					$processor->set_attribute( 'class', $this->merge_atomic_classes( $existing_classes, $atomic_classes ) );
				} else {
					$processor->set_attribute( 'class', implode( ' ', $atomic_classes ) );
				}

				return $processor->get_updated_html();
			}
		}

		return preg_replace_callback(
			'/<([a-zA-Z][^\\s>]*)([^>]*)>/',
			function ( $matches ) use ( $encoded_settings, $atomic_classes ) {
				$tag_name   = $matches[1];
				$attributes = $matches[2];

				if ( preg_match( '/\sclass=(["\'])(.*?)\1/', $attributes, $class_matches ) ) {
					$merged_classes = $this->merge_atomic_classes( $class_matches[2], $atomic_classes );
					$attributes     = preg_replace(
						'/\sclass=(["\'])(.*?)\1/',
						' class="' . esc_attr( $merged_classes ) . '"',
						$attributes,
						1
					);
				} else {
					$attributes .= ' class="' . esc_attr( implode( ' ', $atomic_classes ) ) . '"';
				}

				return '<' . $tag_name . $attributes . ' data-ep-scroll-fill-effect="' . esc_attr( $encoded_settings ) . '">';
			},
			$widget_content,
			1
		) ?: $widget_content;
	}

	private function get_atomic_scroll_fill_effect_classes( array $settings ) {
		$classes = [ 'bdt-scroll-effect-yes' ];

		if ( ! empty( $settings['animation_type'] ) && is_string( $settings['animation_type'] ) ) {
			$classes[] = 'bdt-scroll-effect-' . sanitize_html_class( $settings['animation_type'] );
		}

		return array_values( array_unique( array_filter( $classes ) ) );
	}

	private function merge_atomic_classes( string $existing_classes, array $atomic_classes ) {
		$classes = preg_split( '/\s+/', trim( $existing_classes ) );

		if ( ! is_array( $classes ) ) {
			$classes = [];
		}

		return implode( ' ', array_unique( array_merge( array_filter( $classes ), $atomic_classes ) ) );
	}

	private function is_atomic_heading( $widget ): bool {
		if ( ! method_exists( $widget, 'get_atomic_settings' ) ) {
			return false;
		}

		$element_type = method_exists( $widget, 'get_element_type' ) ? $widget::get_element_type() : '';

		return 'e-heading' === $element_type;
	}

	public function maybe_register_atomic_hooks() {
		if ( ! class_exists( '\Elementor\Plugin' ) ) {
			return;
		}

		if ( has_filter( 'elementor/atomic-widgets/props-schema', [ $this, 'register_atomic_schema' ] ) ) {
			return;
		}

		add_filter( 'elementor/atomic-widgets/props-schema', [ $this, 'register_atomic_schema' ], 20 );
		add_filter( 'elementor/atomic-widgets/controls', [ $this, 'register_atomic_controls' ], 30, 2 );
		// add_filter( 'elementor/widget/print_template', [ $this, 'inject_atomic_scroll_fill_effect_print_template_data' ], 10, 2 );
	}

	private function get_atomic_support() {
		if ( null === $this->atomic_support ) {
			$this->atomic_support = new Atomic_Support();
		}

		return $this->atomic_support;
	}

	private function get_settings_normalizer() {
		if ( null === $this->settings_normalizer ) {
			$this->settings_normalizer = new Settings_Normalizer();
		}

		return $this->settings_normalizer;
	}

	protected function add_actions() {

		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );

		add_action( 'elementor/element/heading/section_title/after_section_end', [ $this, 'register_section' ] );
		add_action( 'elementor/element/heading/section_element_pack_sfe_controls/before_section_end', [ $this, 'register_controls' ], 10, 2 );

		add_action( 'elementor/element/text-editor/section_editor/after_section_end', [ $this, 'register_section' ] );
		add_action( 'elementor/element/text-editor/section_element_pack_sfe_controls/before_section_end', [ $this, 'register_controls' ], 10, 2 );

		add_action( 'elementor/element/bdt-advanced-heading/section_content_advanced_heading/after_section_end', [ $this, 'register_section' ] );
		add_action( 'elementor/element/bdt-advanced-heading/section_element_pack_sfe_controls/before_section_end', [ $this, 'register_controls' ], 10, 2 );

		// render scripts
		add_action( 'elementor/frontend/widget/before_render', [ $this, 'should_script_enqueue' ], 10, 1 );
		add_action( 'elementor/preview/enqueue_scripts', [ $this, 'enqueue_scripts' ] );
		add_action( 'elementor/editor/after_enqueue_scripts', [ $this, 'enqueue_editor_scripts' ] );
		
		add_filter( 'elementor/widget/render_content', [ $this, 'inject_atomic_scroll_fill_effect_data' ], 10, 2 );

		if ( did_action( 'elementor/init' ) ) {
			$this->maybe_register_atomic_hooks();
		} else {
			add_action( 'elementor/init', [ $this, 'maybe_register_atomic_hooks' ] );
		}
	}
}
