<?php

if (! defined('ABSPATH')) {
	exit;
}

/**
 * Elementor Widgets Init — storzen
 *
 * Widget registration is gated by the Storzen toggle settings saved in the
 * admin panel.  A widget file is only included (and the widget registered with
 * Elementor) when its corresponding toggle is enabled in the Settings panel.
 *
 * Toggle → widget-file map
 * ─────────────────────────────────────────────────────────────────
 *  Toggle key (panel slug: storzen / menu: widgets / tab: shop)
 *   product_card, archive_grid, product_grid_w → general (General Style)
 *   product_carousel     → slider
 *   elementor_shop_tab   → tab (Elementor Tab widget)
 *   elementor_shop_list  → list (Elementor List widget)
 *   elementor_shop_sidebar → shop-sidebar (shop grid + filter sidebar)
 *   archive_grid           → archive-grid (Archive Products Grid)
 *   sidebar_ajax_*         → sidebar-filter + separate filter-type widgets
 *   sidebar_search         → sidebar-filter-search
 *   (always on)            → grid (shop card grid widget)
 *
 *  Shop Details tab (pk_storzen_widgets_shop_details):
 *   product_title, product_price, product_rating, product_atc, product_gallery,
 *   product_desc, related_products, product_tabs, sticky_atc, product_share,
 *   product_meta, product_service_info, buy_now, product_utility_links, realtime_visitor
 *   → class-storzen-style-product-single-parts.php (multiple widgets)
 *
 *  Cart tab (pk_storzen_widgets_cart):
 *   cart_table, cart_totals, cart_coupon, mini_cart
 *   → class-storzen-style-cart-widgets.php (multiple widgets)
 *
 *  Checkout tab (pk_storzen_widgets_checkout):
 *   checkout_form, order_review, payment_methods
 *   → class-storzen-style-checkout-widgets.php (multiple widgets)
 *
 *  Thank You tab (pk_storzen_widgets_thankyou):
 *   order_details, order_summary, upsell_after
 *   → class-storzen-style-thankyou-widgets.php (multiple widgets)
 *
 *  My Account tab (pk_storzen_widgets_my_account):
 *   acc_dashboard, acc_orders, acc_addresses, acc_details, acc_login, acc_wishlist, acc_full
 *   → class-storzen-style-my-account-widgets.php (multiple widgets)
 *
 *  Carousel, grid, tab, and list Elementor toggles are on the Shop tab.
 *
 * Because some widgets serve multiple purposes they are enabled when ANY of
 * their associated toggles is ON.
 * ─────────────────────────────────────────────────────────────────
 *
 * @package storzen
 * @since   1.0.3
 */

if (! class_exists('Storzen_Elementor_Widgets_Init')) {

	final class Storzen_Elementor_Widgets_Init
	{

		const VERSION                   = '1.2.0';
		const MINIMUM_ELEMENTOR_VERSION = '2.0.0';
		const MINIMUM_PHP_VERSION       = '5.4';

		private static $_instance = null;

		public static function instance()
		{
			if (is_null(self::$_instance)) {
				self::$_instance = new self();
			}
			return self::$_instance;
		}

		public function __construct()
		{
			add_action('plugins_loaded', array($this, 'init'));
		}

		public function init()
		{

			// ── Requirement checks ───────────────────────────────────────────
			if (! did_action('elementor/loaded')) {
				add_action('admin_notices', array($this, 'admin_notice_missing_main_plugin'));
				return;
			}

			if (! version_compare(ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=')) {
				add_action('admin_notices', array($this, 'admin_notice_minimum_elementor_version'));
				return;
			}

			if (version_compare(PHP_VERSION, self::MINIMUM_PHP_VERSION, '<')) {
				add_action('admin_notices', array($this, 'admin_notice_minimum_php_version'));
				return;
			}

			add_action('elementor/elements/categories_registered', array($this, '_widget_categories'));

			// Elementor 3.5+ uses elementor/widgets/register; older versions use widgets_registered.
			// Priority 20: run after other extensions so our widgets do not race core registration.
			if (defined('ELEMENTOR_VERSION') && version_compare(ELEMENTOR_VERSION, '3.5.0', '>=')) {
				add_action('elementor/widgets/register', array($this, '_widget_registered'), 20, 1);
			} else {
				add_action('elementor/widgets/widgets_registered', array($this, '_widget_registered_legacy'), 20);
			}
		}

		// ── Admin notices ────────────────────────────────────────────────────

		public function admin_notice_missing_main_plugin()
		{
			if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Standard WP admin notice dismiss pattern.
				unset( $_GET['activate'] );
			}
			$message = sprintf(
				/* translators: 1: Plugin name 2: Elementor */
				esc_html__('"%1$s" requires "%2$s" to be installed and activated.', 'storzen'),
				'<strong>' . esc_html__('Woo Shop Addon', 'storzen') . '</strong>',
				'<strong>' . esc_html__('Elementor', 'storzen') . '</strong>'
			);
			printf('<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', wp_kses_post($message));
		}

		public function admin_notice_minimum_elementor_version()
		{
			if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Standard WP admin notice dismiss pattern.
				unset( $_GET['activate'] );
			}
			$message = sprintf(
				/* translators: 1: Plugin name 2: Elementor 3: Required version */
				esc_html__('"%1$s" requires "%2$s" version %3$s or greater.', 'storzen'),
				'<strong>' . esc_html__('Woo Shop Addon', 'storzen') . '</strong>',
				'<strong>' . esc_html__('Elementor', 'storzen') . '</strong>',
				self::MINIMUM_ELEMENTOR_VERSION
			);
			printf('<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', wp_kses_post($message));
		}

		public function admin_notice_minimum_php_version()
		{
			if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Standard WP admin notice dismiss pattern.
				unset( $_GET['activate'] );
			}
			$message = sprintf(
				/* translators: 1: Plugin name 2: PHP 3: Required version */
				esc_html__('"%1$s" requires "%2$s" version %3$s or greater.', 'storzen'),
				'<strong>' . esc_html__('Woo Shop Addon', 'storzen') . '</strong>',
				'<strong>' . esc_html__('PHP', 'storzen') . '</strong>',
				self::MINIMUM_PHP_VERSION
			);
			printf('<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', wp_kses_post($message));
		}

		// ── Category registration ────────────────────────────────────────────

		public function _widget_categories($elements_manager)
		{
			$elements_manager->add_category(
				'storzen',
				array(
					'title' => esc_html__('Woo Shop Addon', 'storzen'),
					'icon'  => 'fa fa-plug',
				)
			);
			// Single-product widgets (Shop Details tab toggles) — separate panel group.
			$elements_manager->add_category(
				'storzen-product-details',
				array(
					'title' => esc_html__('Product Details', 'storzen'),
					'icon'  => 'eicon-product',
				)
			);
			$elements_manager->add_category(
				'storzen-cart',
				array(
					'title' => esc_html__('Cart', 'storzen'),
					'icon'  => 'eicon-cart',
				)
			);
			$elements_manager->add_category(
				'storzen-checkout',
				array(
					'title' => esc_html__('Checkout', 'storzen'),
					'icon'  => 'eicon-checkout',
				)
			);
			$elements_manager->add_category(
				'storzen-thankyou',
				array(
					'title' => esc_html__('Thank You', 'storzen'),
					'icon'  => 'eicon-check-circle',
				)
			);
			$elements_manager->add_category(
				'storzen-my-account',
				array(
					'title' => esc_html__('My Account', 'storzen'),
					'icon'  => 'eicon-person',
				)
			);
			$elements_manager->add_category(
				'storzen-archive',
				array(
					'title' => esc_html__('Archive / Shop', 'storzen'),
					'icon'  => 'eicon-archive',
				)
			);
		}

		// ── Widget registration (toggle-gated) ───────────────────────────────

		/**
		 * Map: widget-file-slug → array of toggle keys (ANY being ON enables it).
		 *
		 * Toggle keys are the field slugs saved under:
		 *   option key  pk_storzen_widgets_shop
		 *   option key  pk_storzen_widgets_shop_details
		 *   option key  pk_storzen_widgets_cart
		 *   option key  pk_storzen_widgets_checkout
		 *   option key  pk_storzen_widgets_thankyou
		 *   option key  pk_storzen_widgets_my_account
		 *   option key  pk_storzen_widgets_landing
		 *
		 * Pass '*' as the only toggle to always load the widget regardless of settings.
		 */
		private function widget_toggle_map()
		{
			$sidebar_ajax_toggles = array(
				'sidebar_ajax_cats',
				'sidebar_ajax_attrs',
				'sidebar_ajax_stock',
				'sidebar_ajax_ratings',
			);

			return array(
				// file slug              => toggle key(s) that enable it (ANY match enables).
				'general'       => array('product_card', 'archive_grid', 'product_grid_w'),
				'slider'        => array('product_carousel'),
				'tab'           => array('elementor_shop_tab'),
				'list'          => array('elementor_shop_list'),
				'shop-sidebar'  => array('elementor_shop_sidebar'),
				'archive-grid'  => array('archive_grid'),
				'sidebar-filter' => $sidebar_ajax_toggles,
				'sidebar-filter-search' => array('sidebar_search'),
				'sidebar-filter-categories' => array('sidebar_ajax_cats'),
				'sidebar-filter-attributes' => array('sidebar_ajax_attrs'),
				'sidebar-filter-stock' => array('sidebar_ajax_stock'),
				'sidebar-filter-ratings' => array('sidebar_ajax_ratings'),
				'grid'          => array('*'),
				// v1.2.2 — Archive toolbar widgets
				'archive-toolbar' => array('archive_ordering', 'archive_result_count', 'archive_title'),
			);
		}

		/**
		 * Whether Storzen is active (licensed).
		 *
		 * @return bool
		 */
		private function is_pro_active()
		{
			return defined('STORZEN_IS_PRO') && STORZEN_IS_PRO === 'yes';
		}

		/**
		 * Toggle keys that require Storzen (must match admin-panel.php set_pro() fields).
		 *
		 * @return string[]
		 */
		private function pro_widget_toggle_keys()
		{
			return apply_filters(
				'storzen_widget_toggle_keys',
				array(
					'sidebar_search',
					'sidebar_ajax_cats',
					'sidebar_ajax_attrs',
					'sidebar_ajax_stock',
					'sidebar_ajax_ratings',
					'product_rating',
					'product_tabs',
					'product_share',
					'order_review',
					'payment_methods',
					'order_details',
					'order_summary',
					'upsell_after',
					'acc_dashboard',
					'acc_orders',
					'acc_addresses',
					'acc_details',
					'acc_login',
					'acc_wishlist',
					'acc_full',
					'mini_cart_drw',
				)
			);
		}

		/**
		 * Default toggle value when the option has never been saved.
		 *
		 * IMPORTANT: This list MUST stay in sync with the `set_default()` calls
		 * declared in `inc/admin-panel.php`. The admin UI shows toggles as ON
		 * by default, but `is_widget_enabled()` calls this function when the
		 * option has never been saved — so any mismatch silently disables the
		 * widget at runtime even though the admin UI says it's on.
		 *
		 * If you add a new toggle to admin-panel.php, mirror its default here.
		 *
		 * @param string $key Toggle field slug.
		 * @return bool
		 */
		private function get_widget_toggle_default($key)
		{
			$defaults = apply_filters(
				'storzen_widget_toggle_defaults',
				array(
					// ── Shop tab ─────────────────────────────────────────────
					'product_card'           => true,
					'archive_grid'           => true,
					'sidebar_search'         => true,
					'sidebar_ajax_cats'      => false,
					'sidebar_ajax_attrs'     => false,
					'sidebar_ajax_stock'     => false,
					'sidebar_ajax_ratings'   => false,
					'product_carousel'       => true,
					'product_grid_w'         => true,
					'elementor_shop_tab'     => true,
					'elementor_shop_list'    => true,
					'elementor_shop_sidebar' => true,

					// ── Archive toolbar widgets (v1.2.2) ─────────────────
					'archive_ordering'     => true,
					'archive_result_count' => true,
					'archive_title'        => true,

					// ── Shop Details tab ─────────────────────────────────────
					'product_title'          => true,
					'product_price'          => true,
					'product_rating'         => true,
					'product_atc'            => true,
					'product_gallery'        => true,
					'product_desc'           => true,
					'related_products'       => true,
					'product_tabs'           => true,
					'sticky_atc'             => false,
					'product_share'          => false,
					'product_meta'           => true,
					'product_service_info'   => true,
					'buy_now'                => true,
					'product_utility_links'  => true,
					'realtime_visitor'       => false,

					// ── v1.2 — New single-product widgets ───────────────────
					'product_reviews'        => true,
					'product_stock_widget'   => true,
					'product_upsells'        => true,

					// ── Cart tab ─────────────────────────────────────────────
					'cart_table'             => true,
					'cart_totals'            => true,
					'cart_coupon'            => true,

					// ── Checkout tab ─────────────────────────────────────────
					'checkout_form'          => true,
					'order_review'           => true,
					'payment_methods'        => true,

					// ── Thank You tab ────────────────────────────────────────
					'order_details'          => true,
					'order_summary'          => true,
					'upsell_after'           => false,

					// ── My Account tab ───────────────────────────────────────
					'acc_dashboard'          => true,
					'acc_orders'             => true,
					'acc_addresses'          => true,
					'acc_details'            => true,
					'acc_login'              => true,
					'acc_wishlist'           => false,
					'acc_full'               => true,

					// ── Cart Menu tab ────────────────────────────────────────
					'ajax_cart'              => true,
					'cart_redirect'          => false,
					'mini_cart_drw'          => false,

					// ── v1.2.1 — New cart widgets ───────────────────────────
					'cart_empty_message'     => true,
					'cart_cross_sell_widget'   => true,
					// v1.1.3 — new widgets
					'checkout_trust_badges'    => true,
					'product_breadcrumbs'      => true,
				)
			);

			if (isset($defaults[$key])) {
				return (bool) $defaults[$key];
			}

			if (in_array($key, $this->pro_widget_toggle_keys(), true)) {
				return false;
			}

			return true;
		}

		/**
		 * Check whether a widget should be registered based on the saved toggles.
		 *
		 * Reads from Storzen option keys (Shop, Shop Details, Cart, Landing, etc.)
		 * — all places where relevant toggles live.
		 *
		 * @param  array $toggle_keys  One or more toggle field slugs.
		 * @return bool
		 */
		private function is_widget_enabled(array $toggle_keys)
		{
			// '*' means unconditionally enabled
			if (in_array('*', $toggle_keys, true)) {
				return true;
			}

			$is_pro   = $this->is_pro_active();
			$pro_keys = $this->pro_widget_toggle_keys();

			// Gather saved values from all relevant tabs. Shop must win over Landing when the same
			// toggle slug exists in both (e.g. product_carousel) so the Shop tab controls Elementor widgets.
			$options = array_merge(
				(array) get_option('pk_storzen_widgets_landing',       array()),
				(array) get_option('pk_storzen_widgets_shop_details',  array()),
				(array) get_option('pk_storzen_widgets_shop',         array()),
				(array) get_option('pk_storzen_widgets_cart',           array()),
				(array) get_option('pk_storzen_widgets_checkout',       array()),
				(array) get_option('pk_storzen_widgets_thankyou',     array()),
				(array) get_option('pk_storzen_widgets_my_account',   array())
			);

			foreach ($toggle_keys as $key) {
				if (! $is_pro && in_array($key, $pro_keys, true)) {
					continue;
				}

				$val = isset($options[$key]) ? $options[$key] : null;

				if ($val === null) {
					$val = $this->get_widget_toggle_default($key);
				}

				if ($val === true || $val === '1' || $val === 1) {
					return true;
				}
			}

			return false;
		}

		public function _widget_registered($widgets_manager)
		{

			if (! class_exists('Elementor\Widget_Base')) {
				return;
			}

			// Note: the separate Sidebar Filter widgets are now standalone widgets,
			// so we don't need to include the old base file to register them.

			$map = $this->widget_toggle_map();

			/**
			 * Allow developers to add/remove widgets or change their toggle keys.
			 *
			 * @param array $map  widget-file-slug => [ toggle_key, ... ]
			 */
			$map = apply_filters('storzen_elementor_widget_map', $map);

			foreach ($map as $widget_file => $toggle_keys) {

				// ── Toggle gate ──────────────────────────────────────────────
				if (! $this->is_widget_enabled((array) $toggle_keys)) {
					continue; // toggle is OFF — skip registration entirely
				}

				$file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-' . $widget_file . '.php';

				if ($file && is_readable($file)) {
					include_once $file;
				}

				// For filter widgets we register here (files only define classes).
				switch ($widget_file) {
					case 'sidebar-filter-search':
						if (class_exists('Elementor\Storzen_Sidebar_Filter_Search')) {
							$this->register_widget_instance($widgets_manager, new \Elementor\Storzen_Sidebar_Filter_Search());
						}
						break;
					case 'sidebar-filter-categories':
						if (class_exists('Elementor\Storzen_Sidebar_Filter_Categories')) {
							$this->register_widget_instance($widgets_manager, new \Elementor\Storzen_Sidebar_Filter_Categories());
						}
						break;
					case 'sidebar-filter-attributes':
						if (class_exists('Elementor\Storzen_Sidebar_Filter_Attributes')) {
							$this->register_widget_instance($widgets_manager, new \Elementor\Storzen_Sidebar_Filter_Attributes());
						}
						break;
					case 'sidebar-filter-stock':
						if (class_exists('Elementor\Storzen_Sidebar_Filter_Stock')) {
							$this->register_widget_instance($widgets_manager, new \Elementor\Storzen_Sidebar_Filter_Stock());
						}
						break;
					case 'sidebar-filter-ratings':
						if (class_exists('Elementor\Storzen_Sidebar_Filter_Ratings')) {
							$this->register_widget_instance($widgets_manager, new \Elementor\Storzen_Sidebar_Filter_Ratings());
						}
						break;
				}
			}

			$this->register_product_detail_widgets( $widgets_manager );
			$this->register_cart_widgets( $widgets_manager );
			$this->register_checkout_widgets( $widgets_manager );
			$this->register_thankyou_widgets( $widgets_manager );
			$this->register_my_account_widgets( $widgets_manager );
		}

		/**
		 * Cart page widgets (Cart tab toggles).
		 *
		 * @param \Elementor\Widgets_Manager $widgets_manager Widgets manager.
		 */
		private function register_cart_widgets( $widgets_manager ) {
			$file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-cart-widgets.php';
			if ( ! is_readable( $file ) ) {
				return;
			}
			require_once $file;

			// v1.2.1 — load new cart widget classes.
			$cart_new = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-cart-widgets-new.php';
			if ( is_readable( $cart_new ) ) {
				require_once $cart_new;
			}

			$map = array(
				array( 'cart_table', 'Elementor\Storzen_Cart_Table_Widget' ),
				array( 'cart_totals', 'Elementor\Storzen_Cart_Totals_Widget' ),
				array( 'cart_coupon', 'Elementor\Storzen_Cart_Coupon_Widget' ),
				array( 'mini_cart_drw', 'Elementor\Storzen_Mini_Cart_Drawer_Widget' ),
			// v1.2.1 — new cart widgets
			array( 'cart_empty_message',     'Elementor\Storzen_Empty_Cart_Widget' ),
			array( 'cart_cross_sell_widget', 'Elementor\Storzen_Cart_Cross_Sell_Widget' ),
			);
			foreach ( $map as $row ) {
				if ( ! $this->is_widget_enabled( array( $row[0] ) ) ) {
					continue;
				}
				$class_name = $row[1];
				if ( class_exists( $class_name ) ) {
					$this->register_widget_instance( $widgets_manager, new $class_name() );
				}
			}
		}

		/**
		 * Checkout page widgets (Checkout tab toggles).
		 *
		 * @param \Elementor\Widgets_Manager $widgets_manager Widgets manager.
		 */
		private function register_checkout_widgets( $widgets_manager ) {
			$file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-checkout-widgets.php';
			if ( ! is_readable( $file ) ) {
				return;
			}
			require_once $file;

			// v1.1.3 — load Trust Badges + Breadcrumbs widget file.
			$v113_file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-v113-widgets.php';
			if ( is_readable( $v113_file ) ) {
				require_once $v113_file;
			}

			$map = array(
				array( 'checkout_form',         'Elementor\Storzen_Checkout_Form_Widget' ),
				array( 'order_review',          'Elementor\Storzen_Checkout_Order_Review_Widget' ),
				array( 'payment_methods',       'Elementor\Storzen_Checkout_Payment_Widget' ),
				// v1.1.3
				array( 'checkout_trust_badges', 'Elementor\Storzen_Checkout_Trust_Badges_Widget' ),
			);
			foreach ( $map as $row ) {
				if ( ! $this->is_widget_enabled( array( $row[0] ) ) ) {
					continue;
				}
				$class_name = $row[1];
				if ( class_exists( $class_name ) ) {
					$this->register_widget_instance( $widgets_manager, new $class_name() );
				}
			}
		}

		/**
		 * Thank You / order received widgets (Thank You tab toggles).
		 *
		 * @param \Elementor\Widgets_Manager $widgets_manager Widgets manager.
		 */
		private function register_thankyou_widgets( $widgets_manager ) {
			$file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-thankyou-widgets.php';
			if ( ! is_readable( $file ) ) {
				return;
			}
			require_once $file;
			$map = array(
				array( 'order_details', 'Elementor\Storzen_Thankyou_Order_Details_Widget' ),
				array( 'order_summary', 'Elementor\Storzen_Thankyou_Order_Summary_Widget' ),
				array( 'upsell_after', 'Elementor\Storzen_Thankyou_Upsell_After_Widget' ),
			);
			foreach ( $map as $row ) {
				if ( ! $this->is_widget_enabled( array( $row[0] ) ) ) {
					continue;
				}
				$class_name = $row[1];
				if ( class_exists( $class_name ) ) {
					$this->register_widget_instance( $widgets_manager, new $class_name() );
				}
			}
		}

	/**
	 * My Account page widgets (My Account tab toggles).
	 *
	 * @param \Elementor\Widgets_Manager $widgets_manager Widgets manager.
	 */
	private function register_my_account_widgets( $widgets_manager ) {
		$file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-my-account-widgets.php';
		if ( ! is_readable( $file ) ) {
			return;
		}
		require_once $file;
		$map = array(
			array( 'acc_dashboard', 'Elementor\Storzen_My_Account_Dashboard_Widget' ),
			array( 'acc_orders', 'Elementor\Storzen_My_Account_Orders_Widget' ),
			array( 'acc_addresses', 'Elementor\Storzen_My_Account_Addresses_Widget' ),
			array( 'acc_details', 'Elementor\Storzen_My_Account_Details_Widget' ),
			array( 'acc_login', 'Elementor\Storzen_My_Account_Login_Widget' ),
			array( 'acc_wishlist', 'Elementor\Storzen_My_Account_Wishlist_Widget' ),
			array( 'acc_full', 'Elementor\Storzen_My_Account_Full_Widget' ),
		);
		foreach ( $map as $row ) {
			if ( ! $this->is_widget_enabled( array( $row[0] ) ) ) {
				continue;
			}
			$class_name = $row[1];
			if ( class_exists( $class_name ) ) {
				$this->register_widget_instance( $widgets_manager, new $class_name() );
			}
		}
	}

		/**
		 * Single product widgets (Shop Details toggles).
		 *
		 * @param \Elementor\Widgets_Manager $widgets_manager Widgets manager.
		 */
		private function register_product_detail_widgets( $widgets_manager ) {
			$file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-product-single-parts.php';
			if ( ! is_readable( $file ) ) {
				return;
			}
			require_once $file;

			// v1.2 — load new single-product widget classes.
			$new_file = STORZEN_ELEMENTOR . '/widgets/class-storzen-style-product-single-parts-new.php';
			if ( is_readable( $new_file ) ) {
				require_once $new_file;
			}

			$map = array(
				array( 'product_title', 'Elementor\Storzen_Product_Title_Widget' ),
				array( 'product_price', 'Elementor\Storzen_Product_Price_Widget' ),
				array( 'product_rating', 'Elementor\Storzen_Product_Rating_Widget' ),
				array( 'product_atc', 'Elementor\Storzen_Product_Add_To_Cart_Widget' ),
				array( 'product_gallery', 'Elementor\Storzen_Product_Gallery_Widget' ),
				array( 'product_desc', 'Elementor\Storzen_Product_Description_Widget' ),
				array( 'related_products', 'Elementor\Storzen_Product_Related_Widget' ),
				array( 'product_tabs', 'Elementor\Storzen_Product_Tabs_Widget' ),
				array( 'sticky_atc', 'Elementor\Storzen_Product_Sticky_Atc_Widget' ),
				array( 'product_share', 'Elementor\Storzen_Product_Share_Widget' ),
				array( 'product_meta', 'Elementor\Storzen_Product_Meta_Widget' ),
				array( 'product_service_info', 'Elementor\Storzen_Product_Service_Info_Widget' ),
				array( 'buy_now', 'Elementor\Storzen_Product_Buy_Now_Widget' ),
				array( 'product_utility_links', 'Elementor\Storzen_Product_Utility_Links_Widget' ),
				array( 'realtime_visitor', 'Elementor\Storzen_Product_Realtime_Visitor_Widget' ),
				// v1.2 — new widgets
				array( 'product_reviews',      'Elementor\Storzen_Product_Reviews_Widget' ),
				array( 'product_stock_widget', 'Elementor\Storzen_Product_Stock_Widget' ),
				array( 'product_upsells',      'Elementor\Storzen_Product_Upsells_Widget' ),
				// v1.1.3
				array( 'product_breadcrumbs',  'Elementor\Storzen_Product_Breadcrumbs_Widget' ),
			);
			foreach ( $map as $row ) {
				if ( ! $this->is_widget_enabled( array( $row[0] ) ) ) {
					continue;
				}
				$class_name = $row[1];
				if ( class_exists( $class_name ) ) {
					$this->register_widget_instance( $widgets_manager, new $class_name() );
				}
			}
		}

		/**
		 * Elementor changed API around 3.5.0 (`register()` vs `register_widget_type()`).
		 * Use whichever exists to avoid fatals that break the editor panel.
		 */
		private function register_widget_instance($widgets_manager, $widget_instance)
		{
			if (is_object($widgets_manager) && method_exists($widgets_manager, 'register')) {
				$widgets_manager->register($widget_instance);
				return;
			}
			if (is_object($widgets_manager) && method_exists($widgets_manager, 'register_widget_type')) {
				$widgets_manager->register_widget_type($widget_instance);
			}
		}

		public function _widget_registered_legacy()
		{
			if (! class_exists('Elementor\Plugin')) {
				return;
			}
			$this->_widget_registered(\Elementor\Plugin::instance()->widgets_manager);
		}
	} // end class

	Storzen_Elementor_Widgets_Init::instance();
}
