<?php
namespace Elementor\Testing;

use Elementor\Utils;
use ElementorEditorTesting\Elementor_Test_Base;

class Elementor_Test_Widgets extends Elementor_Test_Base {

	public function test_getInstance() {
		$this->assertInstanceOf( '\Elementor\Widgets_Manager', $this->elementor()->widgets_manager );
	}

	public function test_getWidgets() {
		$this->assertNotEmpty( $this->elementor()->widgets_manager->get_widget_types() );
	}

	public function test_elementMethods() {
		$common_widgets = [ 'common', 'common-optimized', 'common-base' ];

		foreach ( $this->elementor()->widgets_manager->get_widget_types() as $widget_type ) {
			$name = $widget_type->get_name();

			if ( in_array( $name, $common_widgets, true ) ) {
				continue;
			}

			$this->assertNotEmpty( $widget_type->get_title() );
			$this->assertNotEmpty( $widget_type->get_type() );
			$this->assertNotEmpty( $name );
		}
	}

	public function test_registerNUnregisterWidget() {
		$widget_class = '\Elementor\Widget_Text_editor';
		$widget_id = 'text-editor';

		$this->assertTrue( $this->elementor()->widgets_manager->register( new $widget_class() ) );

		$widget = $this->elementor()->widgets_manager->get_widget_types( $widget_id );
		$this->assertInstanceOf( $widget_class, $widget );

		$this->assertTrue( $this->elementor()->widgets_manager->unregister( $widget_id ) );
		$this->assertFalse( $this->elementor()->widgets_manager->unregister( $widget_id ) );

		$this->assertNull( $this->elementor()->widgets_manager->get_widget_types( $widget_id ) );
	}

	public function test_controlsSelectorsData() {
		foreach ( $this->elementor()->widgets_manager->get_widget_types() as $widget ) {
			foreach ( $widget->get_controls() as $control ) {
				if ( empty( $control['selectors'] ) ) {
					continue;
				}

				foreach ( $control['selectors'] as $selector => $css_property ) {
					$comma_replacement_string = '--#-#--';

					preg_match('/:is\(.*\)/',  $selector, $matches);
					foreach ( $matches as $match ) {
						$replacement=str_replace (',', $comma_replacement_string, $match);
						$selector= str_replace($match, $replacement, $selector);
					}

					foreach ( explode( ',', $selector ) as $item ) {
						$item= str_replace ($comma_replacement_string, ',', $item);
						preg_match( '/\{\{(WRAPPER)|(ID)\}\}/', $item, $matches );

						$this->assertTrue( ! ! $matches );
					}
				}
			}
		}
	}

	public function test_controlsDefaultData() {
		$all_possible_devices_except_desktop = [ 'mobile', 'mobile_extra', 'tablet', 'tablet_extra', 'laptop', 'widescreen' ];

		foreach ( $this->elementor()->widgets_manager->get_widget_types() as $widget ) {
			foreach ( $widget->get_controls() as $control ) {
				if ( \Elementor\Controls_Manager::SELECT !== $control['type'] ) {
					continue;
				}

				$error_msg = sprintf( 'Widget: %1$s, Control: %2$s', $widget->get_name(), $control['name'] );

				// is_empty makes an exception of the value '0' (string zero)
				if ( Utils::is_empty( $control['default'] ) ) {
					// Don't perform this check for non-desktop responsive controls generated by add_responsive_control(),
					// because their default value is always an empty string, even if there is no '' option.
					$has_device_responsive_max_value = false;

					if ( isset( $control['responsive']['max'] ) ) {
						foreach ( $all_possible_devices_except_desktop as $device ) {
							if ( $device === $control['responsive']['max'] ) {
								$has_device_responsive_max_value = true;

								// if at least one device has $control['responsive']['max'] set to it, no need to keep going.
								break;
							}
						}
					}

					if ( ! $has_device_responsive_max_value ) {
						$this->assertTrue( isset( $control['options'][''] ), $error_msg );
					}
				} else {
					$flat_options = [];

					if ( isset( $control['groups'] ) ) {
						foreach ( $control['groups'] as $index_or_key => $args_or_label ) {
							if ( is_numeric( $index_or_key ) ) {
								$args = $args_or_label;

								$this->assertTrue( is_array( $args['options'] ), $error_msg );

								foreach ( $args['options'] as $key => $label ) {
									$flat_options[ $key ] = $label;
								}
							} else {
								$key = $index_or_key;
								$label = $args_or_label;
								$flat_options[ $key ] = $label;
							}
						}
					} else {
						$flat_options = $control['options'];
					}

					$this->assertArrayHasKey( $control['default'], $flat_options, $error_msg );
				}
			}
		}
	}
}
