<?php
namespace PowerpackElements\Classes;

use Elementor\Plugin;
use Elementor\Utils;
use Elementor\Icons_Manager;
use PowerpackElements\Classes\PP_Config;

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

/**
 * Class PP_Helper.
 */
class PP_Helper {

	/**
	 * Script debug
	 *
	 * @var script_debug
	 */
	private static $script_debug = null;

	/**
	 * Widgets List
	 *
	 * @var widgets_list
	 */
	private static $widgets_list = null;

	/**
	 * Widget Options
	 *
	 * @var widget_options
	 */
	private static $widget_options = null;

	/**
	 * A list of safe tage for `validate_html_tag` method.
	 */
	const ALLOWED_HTML_WRAPPER_TAGS = [
		'a',
		'article',
		'aside',
		'button',
		'div',
		'footer',
		'h1',
		'h2',
		'h3',
		'h4',
		'h5',
		'h6',
		'header',
		'main',
		'nav',
		'p',
		'section',
		'span',
	];

	/**
	 * Convert Comma Separated List into Array
	 *
	 * @param string $list Comma separated list.
	 * @return array
	 * @since 1.4.13.2
	 */
	public static function comma_list_to_array( $list = '' ) {

		$list_array = explode( ',', $list );

		return $list_array;
	}

	/**
	 * Get widgets list.
	 *
	 * @since 2.3.0
	 * @return array()
	 */
	public static function get_widgets_list() {

		$widgets_info = PP_Config::get_widget_info();
		$widgets_list = [];

		foreach ($widgets_info as $key => $value) {
			$widgets_list = array_merge( $widgets_list, $value);
		}

		if ( ! isset( self::$widgets_list ) ) {
			self::$widgets_list = $widgets_list;
		}

		return apply_filters( 'ppe_widgets_list', self::$widgets_list );
	}

	/**
	 * Get Widget Name
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 1.4.13.1
	 */
	public static function get_widget_name( $slug = '' ) {

		self::$widgets_list = self::get_widgets_list();

		$widget_name = '';

		if ( isset( self::$widgets_list[ $slug ] ) ) {
			$widget_name = self::$widgets_list[ $slug ]['name'];
		}

		return apply_filters( 'pp_elements_widget_name', $widget_name );
	}

	/**
	 * Provide Widget Name
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 1.4.13.1
	 */
	public static function get_widget_title( $slug = '' ) {

		self::$widgets_list = self::get_widgets_list();

		$widget_name = '';

		if ( isset( self::$widgets_list[ $slug ] ) ) {
			$widget_name = self::$widgets_list[ $slug ]['title'];
		}

		return apply_filters( 'pp_elements_widget_title', $widget_name );
	}

	/**
	 * Provide Widget Name
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 1.4.13.1
	 */
	public static function get_widget_categories( $slug = '' ) {

		self::$widgets_list = self::get_widgets_list();

		$widget_categories = '';

		if ( isset( self::$widgets_list[ $slug ] ) ) {
			$widget_categories = self::$widgets_list[ $slug ]['categories'];
		}

		return apply_filters( 'pp_elements_widget_categories', $widget_categories );
	}

	/**
	 * Provide Widget Name
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 1.4.13.1
	 */
	public static function get_widget_icon( $slug = '' ) {

		self::$widgets_list = self::get_widgets_list();

		$widget_icon = '';

		if ( isset( self::$widgets_list[ $slug ] ) ) {
			$widget_icon = self::$widgets_list[ $slug ]['icon'];
		}

		return apply_filters( 'pp_elements_widget_icon', $widget_icon );
	}

	/**
	 * Provide Widget Name
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 1.4.13.1
	 */
	public static function get_widget_keywords( $slug = '' ) {

		self::$widgets_list = self::get_widgets_list();

		$widget_keywords = '';

		if ( isset( self::$widgets_list[ $slug ] ) ) {
			$widget_keywords = self::$widgets_list[ $slug ]['keywords'];
		}

		return apply_filters( 'pp_elements_widget_keywords', $widget_keywords );
	}

	/**
	 * Provide Widget Docs URL
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 3.0.0
	 */
	public static function get_widget_docs( $slug = '' ) {

		self::$widgets_list = self::get_widgets_list();

		$widget_docs = '';

		if ( isset( self::$widgets_list[ $slug ]['docs'] ) ) {
			$widget_docs = self::$widgets_list[ $slug ]['docs'];
		}

		return apply_filters( 'pp_elements_widget_docs', $widget_docs );
	}

	/**
	 * Get widget styles.
	 *
	 * @since 1.5.0
	 * @return array
	 */
	public static function get_widget_style() {

		return PP_Config::get_widget_style();
	}

	/**
	 * Get Widget Options.
	 *
	 * @since 2.3.0
	 * @return array()
	 */
	public static function get_widget_options() {
		if ( null === self::$widget_options ) {
			if ( ! isset( self::$widgets_list ) ) {
				$widgets = self::get_widgets_list();
			} else {
				$widgets = self::$widgets_list;
			}

			$saved_widgets = pp_get_enabled_modules();

			if ( is_array( $widgets ) ) {

				foreach ( $widgets as $slug => $data ) {

					if ( is_array( $saved_widgets ) && in_array( $data['name'], $saved_widgets, true ) ) {
						$widgets[ $slug ]['is_activate'] = true;
					} else {
						$widgets[ $slug ]['is_activate'] = false;
					}
				}
			}

			self::$widget_options = $widgets;
		}

		return apply_filters( 'ppe_enabled_widgets', self::$widget_options );
	}

	/**
	 * Check if widget is active.
	 *
	 * @param string $slug Module slug.
	 * @return boolean
	 * @since 2.3.0
	 */
	public static function is_widget_active( $slug = '' ) {
		$widgets     = self::get_widget_options();
		$is_activate = false;

		if ( isset( $widgets[ $slug ] ) ) {
			$is_activate = $widgets[ $slug ]['is_activate'];
		}

		return $is_activate;
	}

	/**
	 * Elementor
	 *
	 * Retrieves the elementor plugin instance
	 *
	 * @since  1.4.13.2
	 * @return \Elementor\Plugin|$instace
	 */
	public static function elementor() {
		return \Elementor\Plugin::$instance;
	}

	/**
	 * Check if Elementor experimental feature is active.
	 *
	 * @param string $feature Feature slug.
	 * @return boolean
	 * @since 2.10.22
	 */
	public static function is_feature_active( $feature = '' ) {
		$is_active = false;

		if ( '' !== $feature && self::elementor()->experiments->is_feature_active( $feature ) ) {
			$is_active = true;
		}

		return $is_active;
	}

	/**
	 * Check if Elementor edit mode is active.
	 *
	 * Used to determine whether we are in the edit mode.
	 *
	 * @since 2.10.22
	 * @access public
	 *
	 * @param int $post_id Optional. Post ID. Default is `null`, the current post ID.
	 *
	 * @return bool Whether the edit mode is active.
	 */
	public static function is_edit_mode( $post_id = null ) {
		if ( self::elementor()->editor->is_edit_mode( $post_id ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if Elementor preview mode is active.
	 *
	 * Used to determine whether we are in the preview mode (iframe).
	 *
	 * @since 2.10.22
	 * @access public
	 *
	 * @param int $post_id Optional. Post ID. Default is `null`, the current post ID.
	 *
	 * @return bool Whether the edit mode is active.
	 */
	public static function is_preview_mode( $post_id = 0 ) {
		if ( self::elementor()->preview->is_preview_mode( $post_id ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if script debug is enabled.
	 *
	 * @since 1.5.0
	 *
	 * @return string The CSS suffix.
	 */
	public static function is_script_debug() {
		if ( null === self::$script_debug ) {

			self::$script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
		}

		return self::$script_debug;
	}

	/**
	 * Get Google Map Languages
	 *
	 * @since 1.4.11.2
	 * @access public
	 */
	public static function get_google_map_languages() {

		$languages = [
			'af'     => __( 'Afrikaan', 'powerpack' ),
			'sq'     => __( 'Albanian', 'powerpack' ),
			'am'     => __( 'Amharic', 'powerpack' ),
			'ar'     => __( 'Arabic', 'powerpack' ),
			'hy'     => __( 'Armenian', 'powerpack' ),
			'az'     => __( 'Azerbaijani', 'powerpack' ),
			'eu'     => __( 'Basque', 'powerpack' ),
			'be'     => __( 'Belarusian', 'powerpack' ),
			'bn'     => __( 'Bengali', 'powerpack' ),
			'bs'     => __( 'Bosnian', 'powerpack' ),
			'bg'     => __( 'Bulgarian', 'powerpack' ),
			'my'     => __( 'Burmese', 'powerpack' ),
			'ca'     => __( 'Catalan', 'powerpack' ),
			'zh'     => __( 'Chinese', 'powerpack' ),
			'zh-CN'  => __( 'Chinese (Simplified)', 'powerpack' ),
			'zh-HK'  => __( 'Chinese (Hong Kong)', 'powerpack' ),
			'zh-TW'  => __( 'Chinese (Traditional)', 'powerpack' ),
			'hr'     => __( 'Croatian', 'powerpack' ),
			'cs'     => __( 'Czech', 'powerpack' ),
			'da'     => __( 'Danish', 'powerpack' ),
			'nl'     => __( 'Dutch', 'powerpack' ),
			'en'     => __( 'English', 'powerpack' ),
			'en-AU'  => __( 'English (Australian)', 'powerpack' ),
			'en-GB'  => __( 'English (Great Britain)', 'powerpack' ),
			'et'     => __( 'Estonian', 'powerpack' ),
			'fa'     => __( 'Farsi', 'powerpack' ),
			'fi'     => __( 'Finnish', 'powerpack' ),
			'fil'    => __( 'Filipino', 'powerpack' ),
			'fr'     => __( 'French', 'powerpack' ),
			'fr-CA'  => __( 'French (Canada)', 'powerpack' ),
			'gl'     => __( 'Galician', 'powerpack' ),
			'ka'     => __( 'Georgian', 'powerpack' ),
			'de'     => __( 'German', 'powerpack' ),
			'el'     => __( 'Greek', 'powerpack' ),
			'gu'     => __( 'Gujarati', 'powerpack' ),
			'iw'     => __( 'Hebrew', 'powerpack' ),
			'hi'     => __( 'Hindi', 'powerpack' ),
			'hu'     => __( 'Hungarian', 'powerpack' ),
			'is'     => __( 'Icelandic', 'powerpack' ),
			'id'     => __( 'Indonesian', 'powerpack' ),
			'it'     => __( 'Italian', 'powerpack' ),
			'ja'     => __( 'Japanese', 'powerpack' ),
			'kn'     => __( 'Kannada', 'powerpack' ),
			'kk'     => __( 'Kazakh', 'powerpack' ),
			'km'     => __( 'Khmer', 'powerpack' ),
			'ko'     => __( 'Korean', 'powerpack' ),
			'ky'     => __( 'Kyrgyz', 'powerpack' ),
			'lo'     => __( 'Lao', 'powerpack' ),
			'lv'     => __( 'Latvian', 'powerpack' ),
			'lt'     => __( 'Lithuanian', 'powerpack' ),
			'mk'     => __( 'Macedonian', 'powerpack' ),
			'ms'     => __( 'Malay', 'powerpack' ),
			'ml'     => __( 'Malayalam', 'powerpack' ),
			'mr'     => __( 'Marathi', 'powerpack' ),
			'mn'     => __( 'Mongolian', 'powerpack' ),
			'ne'     => __( 'Nepali', 'powerpack' ),
			'no'     => __( 'Norwegian', 'powerpack' ),
			'pl'     => __( 'Polish', 'powerpack' ),
			'pt'     => __( 'Portuguese', 'powerpack' ),
			'pt-BR'  => __( 'Portuguese (Brazil)', 'powerpack' ),
			'pt-PT'  => __( 'Portuguese (Portugal)', 'powerpack' ),
			'pa'     => __( 'Punjabi', 'powerpack' ),
			'ro'     => __( 'Romanian', 'powerpack' ),
			'ru'     => __( 'Russian', 'powerpack' ),
			'sr'     => __( 'Serbian', 'powerpack' ),
			'si'     => __( 'Sinhalese', 'powerpack' ),
			'sk'     => __( 'Slovak', 'powerpack' ),
			'sl'     => __( 'Slovenian', 'powerpack' ),
			'es'     => __( 'Spanish', 'powerpack' ),
			'es-419' => __( 'Spanish (Latin America)', 'powerpack' ),
			'sw'     => __( 'Swahili', 'powerpack' ),
			'sv'     => __( 'Swedish', 'powerpack' ),
			'ta'     => __( 'Tamil', 'powerpack' ),
			'te'     => __( 'Telugu', 'powerpack' ),
			'th'     => __( 'Thai', 'powerpack' ),
			'tr'     => __( 'Turkish', 'powerpack' ),
			'uk'     => __( 'Ukrainian', 'powerpack' ),
			'ur'     => __( 'Urdu', 'powerpack' ),
			'uz'     => __( 'Uzbek', 'powerpack' ),
			'vi'     => __( 'Vietnamese', 'powerpack' ),
			'zu'     => __( 'Zulu', 'powerpack' ),
		];

		return $languages;
	}

	public static function get_recaptcha_desc() {
		// translators: %s: Integration Setting Page link
		return sprintf( __( 'To use reCAPTCHA, you need to add the API keys in the <a href="%s" target="_blank">Integrations Settings</a> and complete the setup process.', 'powerpack' ), \PowerpackElements\Classes\PP_Admin_Settings::get_form_action( '&tab=integration' ) );
	}

	/**
	 * Get contact forms of supported forms plugins
	 *
	 * @since 1.4.14.1
	 * @access public
	 */
	public static function get_contact_forms( $plugin = '' ) {
		$options       = [];
		$contact_forms = [];

		// Contact Form 7
		if ( 'Contact_Form_7' == $plugin && function_exists( 'wpcf7' ) ) {
			$args = [
				'post_type'      => 'wpcf7_contact_form',
				'posts_per_page' => -1,
			];

			$cf7_forms = get_posts( $args );

			if ( ! empty( $cf7_forms ) && ! is_wp_error( $cf7_forms ) ) {
				foreach ( $cf7_forms as $form ) {
					$contact_forms[ $form->ID ] = $form->post_title;
				}
			}
		}

		// Fluent Forms
		if ( 'Fluent_Forms' == $plugin && function_exists( 'wpFluentForm' ) ) {
			global $wpdb;

			$fluent_forms = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}fluentform_forms" );

			if ( $fluent_forms ) {
				foreach ( $fluent_forms as $form ) {
					$contact_forms[ $form->id ] = $form->title;
				}
			}
		}

		// Formidable Forms
		if ( 'Formidable_Forms' == $plugin && class_exists( 'FrmForm' ) ) {
			$formidable_forms = \FrmForm::get_published_forms( [], 999, 'exclude' );
			if ( count( $formidable_forms ) ) {
				foreach ( $formidable_forms as $form ) {
					$contact_forms[ $form->id ] = $form->name;
				}
			}
		}

		// Gravity Forms
		if ( 'Gravity_Forms' == $plugin && class_exists( 'GFForms' ) ) {
			$gravity_forms = \RGFormsModel::get_forms( null, 'title' );

			if ( ! empty( $gravity_forms ) && ! is_wp_error( $gravity_forms ) ) {
				foreach ( $gravity_forms as $form ) {
					$contact_forms[ $form->id ] = $form->title;
				}
			}
		}

		// Ninja Forms
		if ( 'Ninja_Forms' == $plugin && class_exists( 'Ninja_Forms' ) ) {
			$ninja_forms = Ninja_Forms()->form()->get_forms();

			if ( ! empty( $ninja_forms ) && ! is_wp_error( $ninja_forms ) ) {
				foreach ( $ninja_forms as $form ) {
					$contact_forms[ $form->get_id() ] = $form->get_setting( 'title' );
				}
			}
		}

		// WPforms
		if ( 'WP_Forms' == $plugin && function_exists( 'wpforms' ) ) {
			$args = [
				'post_type'      => 'wpforms',
				'posts_per_page' => -1,
			];

			$wpf_forms = get_posts( $args );

			if ( ! empty( $wpf_forms ) && ! is_wp_error( $wpf_forms ) ) {
				foreach ( $wpf_forms as $form ) {
					$contact_forms[ $form->ID ] = $form->post_title;
				}
			}
		}

		// Contact Forms List
		if ( ! empty( $contact_forms ) ) {
			$options[0] = esc_html__( 'Select a Contact Form', 'powerpack' );
			foreach ( $contact_forms as $form_id => $form_title ) {
				$options[ $form_id ] = $form_title;
			}
		}

		if ( empty( $options ) ) {
			$options[0] = esc_html__( 'No contact forms found!', 'powerpack' );
		}

		return $options;
	}

	/**
	 * Build the URL of Facebook SDK.
	 *
	 * @since 1.5.0
	 * @return string
	 */
	public static function get_fb_sdk_url( $app_id = '' ) {
		$fb_app_id = \PowerpackElements\Classes\PP_Admin_Settings::get_option( 'pp_fb_app_id' );

		$app_id = empty( $app_id ) ? $fb_app_id : $app_id;

		if ( $app_id && ! empty( $app_id ) ) {
			return sprintf( 'https://connect.facebook.net/%s/sdk.js#xfbml=1&version=v2.12&appId=%s', get_locale(), $app_id );
		}

		return sprintf( 'https://connect.facebook.net/%s/sdk.js#xfbml=1&version=v2.12', get_locale() );
	}

	/**
	 * Get Facebook app settings url
	 *
	 * @since 1.5.0
	 * @return string
	 */
	public static function get_fb_app_settings_url() {
		$app_id = \PowerpackElements\Classes\PP_Admin_Settings::get_option( 'pp_fb_app_id' );

		if ( $app_id ) {
			return sprintf( 'https://developers.facebook.com/apps/%d/settings/', $app_id );
		} else {
			return 'https://developers.facebook.com/apps/';
		}
	}

	/**
	 * Returns user agent.
	 *
	 * @since 1.5.0
	 * @return string
	 */
	public static function get_user_agent() {
		$user_agent = $_SERVER['HTTP_USER_AGENT'];

		if ( false !== stripos( $user_agent, 'Chrome' ) ) {
			return 'chrome';
		} elseif ( false !== stripos( $user_agent, 'Safari' ) ) {
			return 'safari';
		} elseif ( false !== stripos( $user_agent, 'Firefox' ) ) {
			return 'firefox';
		} elseif ( false !== stripos( $user_agent, 'MSIE' ) ) {
			return 'ie';
		} elseif ( false !== stripos( $user_agent, 'Trident/7.0; rv:11.0' ) ) {
			return 'ie';
		}

		return;
	}

	/**
	 * Get Client IP address
	 *
	 * @since 1.5.0
	 * @return string
	 */
	public static function get_client_ip() {
		$keys = [
			'HTTP_CLIENT_IP',
			'HTTP_X_FORWARDED_FOR',
			'HTTP_X_FORWARDED',
			'HTTP_X_CLUSTER_CLIENT_IP',
			'HTTP_FORWARDED_FOR',
			'HTTP_FORWARDED',
			'REMOTE_ADDR',
		];

		foreach ( $keys as $key ) {
			if ( isset( $_SERVER[ $key ] ) && filter_var( $_SERVER[ $key ], FILTER_VALIDATE_IP ) ) {
				return $_SERVER[ $key ];
			}
		}

		// fallback IP address.
		return '127.0.0.1';
	}

	/**
	 * Compare conditions.
	 *
	 * Whether the two values comply the comparison operator.
	 *
	 * @since 2.10.0
	 * @access public
	 * @static
	 *
	 * @param mixed  $left_value  First value to compare.
	 * @param mixed  $right_value Second value to compare.
	 * @param string $operator    Comparison operator.
	 *
	 * @return bool Whether the two values complies the comparison operator.
	 */
	public static function compare( $left_value, $right_value, $operator ) {
		switch ( $operator ) {
			case '==':
				return $left_value == $right_value;
			case '!=':
				return $left_value != $right_value;
			case '!==':
				return $left_value !== $right_value;
			case 'in':
				return in_array( $left_value, $right_value, true );
			case '!in':
				return ! in_array( $left_value, $right_value, true );
			case 'contains':
				return in_array( $right_value, $left_value, true );
			case '!contains':
				return ! in_array( $right_value, $left_value, true );
			case '<':
				return $left_value < $right_value;
			case '<=':
				return $left_value <= $right_value;
			case '>':
				return $left_value > $right_value;
			case '>=':
				return $left_value >= $right_value;
			default:
				return $left_value === $right_value;
		}
	}

	/**
	 * Validate an HTML tag against a safe allowed list.
	 *
	 * @since 2.3.2
	 * @param string $tag specifies the HTML Tag.
	 * @access public
	 * @return string
	 */
	public static function validate_html_tag( $tag ) {
		// Check if Elementor method exists, else we will run custom validation code.
		if ( method_exists( 'Elementor\Utils', 'validate_html_tag' ) ) {
			return Utils::validate_html_tag( $tag );
		} else {
			return in_array( strtolower( $tag ), self::ALLOWED_HTML_WRAPPER_TAGS, true ) ? $tag : 'div';
		}
	}

	/**
	 * Safe print a validated HTML tag.
	 *
	 * @since 2.9.19
	 * @param string $tag
	 */
	public static function print_validated_html_tag( $tag ) {
		// PHPCS - the method validate_html_tag is safe.
		echo self::validate_html_tag( $tag ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	public static function is_tribe_events_post( $post_id ) {
		return ( class_exists( 'Tribe__Events__Main' ) && 'tribe_events' === get_post_type( $post_id ) );
	}

	public static function render_arrows( $widget ) {
		$settings = $widget->get_settings_for_display();

		$migration_allowed = Icons_Manager::is_migration_allowed();

		if ( ! isset( $settings['arrow'] ) && ! Icons_Manager::is_migration_allowed() ) {
			// add old default.
			$settings['arrow'] = 'fa fa-angle-right';
		}

		$has_icon = ! empty( $settings['arrow'] );

		if ( ! $has_icon && ! empty( $settings['select_arrow']['value'] ) ) {
			$has_icon = true;
		}

		if ( ! empty( $settings['arrow'] ) ) {
			$widget->add_render_attribute( 'arrow-icon', 'class', $settings['arrow'] );
			$widget->add_render_attribute( 'arrow-icon', 'aria-hidden', 'true' );
		}

		$migrated = isset( $settings['__fa4_migrated']['select_arrow'] );
		$is_new = ! isset( $settings['arrow'] ) && $migration_allowed;

		if ( 'yes' === $settings['arrows'] ) {
			if ( $has_icon ) {
				if ( $is_new || $migrated ) {
					$next_arrow = $settings['select_arrow'];
					$prev_arrow = str_replace( 'right', 'left', $settings['select_arrow'] );
				} else {
					$next_arrow = $settings['arrow'];
					$prev_arrow = str_replace( 'right', 'left', $settings['arrow'] );
				}
			} else {
				$next_arrow = 'fa fa-angle-right';
				$prev_arrow = 'fa fa-angle-left';
			}

			if ( ! empty( $settings['arrow'] ) || ( ! empty( $settings['select_arrow']['value'] ) && $is_new ) ) { ?>
				<div class="pp-slider-arrow elementor-swiper-button-prev swiper-button-prev-<?php echo esc_attr( $widget->get_id() ); ?>" role="button" tabindex="0">
					<?php if ( $is_new || $migrated ) :
						Icons_Manager::render_icon( $prev_arrow, [ 'aria-hidden' => 'true' ] );
					else : ?>
						<i <?php $widget->print_render_attribute_string( 'arrow-icon' ); ?>></i>
					<?php endif; ?>
				</div>
				<div class="pp-slider-arrow elementor-swiper-button-next swiper-button-next-<?php echo esc_attr( $widget->get_id() ); ?>" role="button" tabindex="0">
					<?php if ( $is_new || $migrated ) :
						Icons_Manager::render_icon( $next_arrow, [ 'aria-hidden' => 'true' ] );
					else : ?>
						<i <?php $widget->print_render_attribute_string( 'arrow-icon' ); ?>></i>
					<?php endif; ?>
				</div>
			<?php }
		}
	}

	/**
	 * Provide Widget Name
	 *
	 * @param string $slug Module slug.
	 * @return string
	 * @since 2.9.0
	 */
	public static function get_widget_presets( $slug = '' ) {
		self::$widgets_list = self::get_widgets_list();

		$widget_preset = '';

		if ( isset( self::$widgets_list[ $slug ] ) ) {
			$widget_preset = self::$widgets_list[ $slug ]['preset'];
		}

		return apply_filters( 'pp_widget_preset', $widget_preset );
	}

	/**
	 * Outputs the JSON schema markup.
	 *
	 * @since 2.12.4
	 * @param array $schema_data The schema data to be encoded and printed.
	 */
	public static function print_json_schema( $schema_data ) {
		if ( empty( $schema_data ) ) {
			return;
		}

		$encoded_data  = wp_json_encode( $schema_data, self::is_script_debug() ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES : JSON_UNESCAPED_SLASHES );

		echo '<script type="application/ld+json">' . $encoded_data . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	/**
	 * Retrieves the type of the widget.
	 *
	 * This function determines the type of the widget by checking if the widget type is explicitly defined.
	 * If not defined, it defaults to the element type. Additionally, if the widget is a global widget,
	 * it retrieves the global widget type based on the template ID.
	 *
	 * @since 2.12.4
	 * @param array $element The element array containing widget details.
	 * @return string The type of the widget.
	 */
	public static function get_widget_type( $element ) {
		// Check if 'widgetType' is defined in the element array, otherwise use 'elType'.
		if ( empty( $element['widgetType'] ) ) {
			$type = $element['elType'];
		} else {
			$type = $element['widgetType'];
		}

		// If the widget type is 'global' and a template ID is provided, fetch the global widget type.
		if ( 'global' === $type && ! empty( $element['templateID'] ) ) {
			$type = self::get_global_widget_type( $element['templateID'] );
		}

		return $type;
	}

	/**
	* Retrieves the type of a global widget.
	*
	* This function fetches template data from a local source using the template ID.
	* It returns either the original widget type or an empty string if no type could be retrieved
	* or if the template data contains an error or lacks content.
	*
	* @since 2.12.4
	* @param int $template_id The ID of the template.
	* @param bool $return_type Whether to return the widget type object or just the type name.
	* @return mixed The original widget type or an empty string if not found.
	*/
	public static function get_global_widget_type( $template_id, $return_type = false ) {
		// Fetch template data using the template ID.
		$template_data = self::elementor()->templates_manager->get_template_data( [
			'source'      => 'local',
			'template_id' => $template_id,
		] );

		// If retrieving the template data results in an error, return an empty string.
		if ( is_wp_error( $template_data ) ) {
			return '';
		}

		// If the template data is empty, return an empty string.
		if ( empty( $template_data['content'] ) ) {
			return '';
		}

		// Retrieve the original widget type using the widget type of the first element in the template content.
		$original_widget_type = self::elementor()->widgets_manager->get_widget_types( $template_data['content'][0]['widgetType'] );

		// Return either the widget type object or just the widget type name, depending on $return_type.
		if ( $return_type ) {
			return $original_widget_type;
		}

		return $original_widget_type ? $template_data['content'][0]['widgetType'] : '';
	}

	/**
	 * Get Instagram-style image filter options.
	 *
	 * Single source of truth for the image filter list shared by all widgets that
	 * expose CSS image filters (Random Image, Image Gallery, Image Slider, Album,
	 * Tabbed Gallery, Showcase).
	 *
	 * @since 2.13.0
	 * @access public
	 *
	 * @param bool $inherit Whether to prepend an "Inherit" option (empty value).
	 *
	 * @return array Filter slug => label.
	 */
	public static function get_image_filters( $inherit = false ) {
		$filters = [
			'normal'           => esc_html__( 'Normal', 'powerpack' ),
			'filter-1977'      => esc_html__( '1977', 'powerpack' ),
			'filter-aden'      => esc_html__( 'Aden', 'powerpack' ),
			'filter-amaro'     => esc_html__( 'Amaro', 'powerpack' ),
			'filter-ashby'     => esc_html__( 'Ashby', 'powerpack' ),
			'filter-brannan'   => esc_html__( 'Brannan', 'powerpack' ),
			'filter-brooklyn'  => esc_html__( 'Brooklyn', 'powerpack' ),
			'filter-charmes'   => esc_html__( 'Charmes', 'powerpack' ),
			'filter-clarendon' => esc_html__( 'Clarendon', 'powerpack' ),
			'filter-crema'     => esc_html__( 'Crema', 'powerpack' ),
			'filter-dogpatch'  => esc_html__( 'Dogpatch', 'powerpack' ),
			'filter-earlybird' => esc_html__( 'Earlybird', 'powerpack' ),
			'filter-gingham'   => esc_html__( 'Gingham', 'powerpack' ),
			'filter-ginza'     => esc_html__( 'Ginza', 'powerpack' ),
			'filter-hefe'      => esc_html__( 'Hefe', 'powerpack' ),
			'filter-helena'    => esc_html__( 'Helena', 'powerpack' ),
			'filter-hudson'    => esc_html__( 'Hudson', 'powerpack' ),
			'filter-inkwell'   => esc_html__( 'Inkwell', 'powerpack' ),
			'filter-juno'      => esc_html__( 'Juno', 'powerpack' ),
			'filter-kelvin'    => esc_html__( 'Kelvin', 'powerpack' ),
			'filter-lark'      => esc_html__( 'Lark', 'powerpack' ),
			'filter-lofi'      => esc_html__( 'Lofi', 'powerpack' ),
			'filter-ludwig'    => esc_html__( 'Ludwig', 'powerpack' ),
			'filter-maven'     => esc_html__( 'Maven', 'powerpack' ),
			'filter-mayfair'   => esc_html__( 'Mayfair', 'powerpack' ),
			'filter-moon'      => esc_html__( 'Moon', 'powerpack' ),
		];

		if ( $inherit ) {
			$filters = [ '' => esc_html__( 'Inherit', 'powerpack' ) ] + $filters;
		}

		return $filters;
	}

	/**
	 * Get the list of PHP timezone identifiers, keyed by identifier.
	 *
	 * @since 3.0.0
	 * @access public
	 *
	 * @return array Timezone identifier => identifier.
	 */
	public static function get_timezones() {
		$timezone_list = [];
		foreach ( timezone_identifiers_list() as $timezone ) {
			$timezone_list[ $timezone ] = $timezone;
		}
		return $timezone_list;
	}

	/**
	 * Convert a date string from the site timezone to another timezone.
	 *
	 * @since 3.0.0
	 * @access public
	 *
	 * @param string $date         The source date string.
	 * @param string $formate      The output date format.
	 * @param string $new_timezone Target timezone identifier.
	 *
	 * @return string The formatted date, or the original value on failure.
	 */
	public static function get_timezones_converted_date( $date, $formate, $new_timezone ) {
		if ( empty( $date ) ) {
			return '';
		}

		$timezone_string = ( '' !== get_option( 'timezone_string' ) ) ? get_option( 'timezone_string' ) : 'UTC';

		try {
			$datetime = new \DateTime( $date, new \DateTimeZone( $timezone_string ) );
			$datetime->setTimezone( new \DateTimeZone( $new_timezone ) );
			return $datetime->format( $formate );
		} catch ( \Exception $e ) {
			return $date;
		}
	}
}
