<?php
namespace CSSIgniter\Ignition\Elementor\Widget;

class Post_Types extends \Elementor\Widget_Base {

	use \CSSIgniter\Ignition\Elementor\Common_Functions;

	public function get_style_depends() {

		wp_register_style( 'ignition-elementor-post-types', plugin_dir_url( __DIR__ ) . 'assets/css/post-types.min.css', array(), IGNITION_ELEMENTOR_WIDGETS_VERSION );

		return [
			'ignition-elementor-post-types',
		];

	}

	public function get_name() {
		return 'ci_post_types';
	}

	public function get_title() {
		return __( 'Post Types Widget', 'ignition-elementor-widgets' );
	}

	public function get_icon() {
		return 'eicon-wordpress';
	}

	public function get_script_depends() {
		return array( 'ignition-elementor-widgets-scripts' );
	}

	public function get_categories() {
		return array( 'ignition-elementor-widgets' );
	}

	protected function register_controls() {

		$this->start_controls_section( 'section_title', array(
			'label' => __( 'Post Types Widget', 'ignition-elementor-widgets' ),
		) );

		$this->query_controls();

		$this->add_control( 'columns', array(
			'label'   => __( 'Columns', 'ignition-elementor-widgets' ),
			'type'    => \Elementor\Controls_Manager::SELECT,
			'default' => '2',
			'options' => array(
				'1' => 1,
				'2' => 2,
				'3' => 3,
				'4' => 4,
			),
		) );

		$this->add_control( 'grid_spacing', array(
			'label'   => __( 'Grid Spacing', 'ignition-elementor-widgets' ),
			'type'    => \Elementor\Controls_Manager::SELECT,
			'default' => 'with-gutters',
			'options' => array(
				'with-gutters' => __( 'With Gutters', 'ignition-elementor-widgets' ),
				'no-gutters'   => __( 'No Gutters', 'ignition-elementor-widgets' ),
			),
		) );

		$this->add_control( 'read_more_button_label', array(
			'label'       => __( 'Button Label', 'ignition-elementor-widgets' ),
			'type'        => \Elementor\Controls_Manager::TEXT,
			'placeholder' => __( 'Read More', 'ignition-elementor-widgets' ),
		) );

		$element_style = \WP_Block_Styles_Registry::get_instance()->get_registered_styles_for_block( 'gutenbee/post-types' );

		if ( $element_style ) {
			$options = array_merge( wp_list_pluck( $element_style, 'label', 'name' ), array( 'default' => __( 'Default', 'ignition-elementor-widgets' ) ) );
			$this->add_control( 'element_style', array(
				'label'   => __( 'Element Style', 'ignition-elementor-widgets' ),
				'type'    => \Elementor\Controls_Manager::SELECT,
				'default' => 'default',
				'options' => $options,
			) );
		}

		$post_types_supports = get_theme_support( 'block/gutenbee/post-types' );

		if ( $post_types_supports && ! empty( $post_types_supports[0]['selectImageSize'] ) ) {
			$this->add_control( 'image_size_slug', array(
				'label'     => __( 'Image Size', 'ignition-elementor-widgets' ),
				'type'      => \Elementor\Controls_Manager::SELECT,
				'default'   => 'ignition_item',
				'options'   => $this->get_registered_image_sizes(),
				'condition' => [
					'posts_group_post_type' => $post_types_supports[0]['selectImageSize'],
				],
			) );
		}

		if ( $post_types_supports && ! empty( $post_types_supports[0]['masonry'] ) ) {
			$this->add_control(
				'masonry',
				array(
					'label'        => esc_html__( 'Enable masonry.', 'ignition-elementor-widgets' ),
					'type'         => \Elementor\Controls_Manager::SWITCHER,
					'label_on'     => esc_html__( 'Yes', 'ignition-elementor-widgets' ),
					'label_off'    => esc_html__( 'No', 'ignition-elementor-widgets' ),
					'return_value' => 'yes',
					'default'      => '',
				)
			);
		}

		$this->end_controls_section();

		$this->start_controls_section( 'section_title_style', array(
			'label' => __( 'Post Type Item', 'ignition-elementor-widgets' ),
			'tab'   => \Elementor\Controls_Manager::TAB_STYLE,
		) );

		$this->add_control( 'background_color', array(
			'label'     => __( 'Background Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item' => 'background-color: {{VALUE}};',
			),
		) );

		$this->add_control( 'accent_color', array(
			'label'     => __( 'Accent Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item-product .price, {{WRAPPER}} .entry-meta-top-wrap'        => 'color: {{VALUE}};',
				'{{WRAPPER}} .is-style-ci-theme-post-types-slideshow .slick-arrow:hover'          => 'background-color: {{VALUE}};border-color: {{VALUE}};',
				'{{WRAPPER}} .onsale, {{WRAPPER}} .entry-item-title::after'                       => 'background-color: {{VALUE}};',
				'{{WRAPPER}} .entry-item-thumb>a>img:hover, {{WRAPPER}} .entry-thumb>a>img:hover' => 'border-color: {{VALUE}};',
			),
		) );

		$this->start_controls_tabs( 'post_item_colors' );

		$this->start_controls_tab( 'normal', array(
			'label' => __( 'Normal', 'ignition-elementor-widgets' ),
		) );

		$this->add_control( 'title_color', array(
			'label'     => __( 'Title Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item-title a'                                                                                      => 'color: {{VALUE}};',
				'{{WRAPPER}} .entry-title a'                                                                                           => 'color: {{VALUE}};',
				'{{WRAPPER}} .entry-item-product .entry-item-content .woocommerce-loop-product__link .woocommerce-loop-product__title' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'meta_color', array(
			'label'     => __( 'Meta Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-meta-item, {{WRAPPER}} .entry-item-product .price, {{WRAPPER}} .entry-item-list-meta, {{WRAPPER}} .is-style-ci-theme-entries-compact .entry-time' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'meta_link_color', array(
			'label'     => __( 'Meta Link Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item-list-meta a' => 'color: {{VALUE}};',
				'{{WRAPPER}} .entry-meta-item a'      => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'excerpt_color', array(
			'label'     => __( 'Excerpt Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item-excerpt' => 'color: {{VALUE}};',
			),
		) );

		$this->end_controls_tab();

		$this->start_controls_tab( 'hover', array(
			'label' => __( 'Hover', 'ignition-elementor-widgets' ),
		) );

		$this->add_control( 'title_color_hover', array(
			'label'     => __( 'Title Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item-title a:hover'                                                                                      => 'color: {{VALUE}};',
				'{{WRAPPER}} .entry-title a:hover'                                                                                           => 'color: {{VALUE}};',
				'{{WRAPPER}} .entry-item-product .entry-item-content .woocommerce-loop-product__link:hover .woocommerce-loop-product__title' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'meta_link_hover_color', array(
			'label'     => __( 'Meta Link Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .entry-item-list-meta a:hover' => 'color: {{VALUE}};',
				'{{WRAPPER}} .entry-meta-item a:hover'      => 'color: {{VALUE}};',
			),
		) );

		$this->end_controls_tab();

		$this->end_controls_tabs();

		$this->end_controls_section();

		$this->start_controls_section( 'section_style', array(
			'label' => __( 'Button', 'ignition-elementor-widgets' ),
			'tab'   => \Elementor\Controls_Manager::TAB_STYLE,
		) );

		$this->start_controls_tabs( 'tabs_button_style' );

		$this->start_controls_tab( 'tab_button_normal', array(
			'label' => __( 'Normal', 'ignition-elementor-widgets' ),
		) );

		$this->add_control( 'button_text_color', array(
			'label'     => __( 'Text Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .btn-entry-more, {{WRAPPER}} .entry-more-btn, {{WRAPPER}} .button' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'button_background_color', array(
			'label'     => __( 'Background Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .btn-entry-more, {{WRAPPER}} .entry-more-btn, {{WRAPPER}} .button' => 'background-color: {{VALUE}};',
			),
		) );

		$this->end_controls_tab();

		$this->start_controls_tab( 'tab_button_hover', array(
			'label' => __( 'Hover', 'ignition-elementor-widgets' ),
		) );

		$this->add_control( 'hover_color', array(
			'label'     => __( 'Text Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .btn-entry-more:hover, {{WRAPPER}} .entry-more-btn:hover, {{WRAPPER}} .btn-entry-more:focus, {{WRAPPER}} .entry-more-btn:focus, {{WRAPPER}} .button:hover, {{WRAPPER}} .button:focus' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'button_background_hover_color', array(
			'label'     => __( 'Background Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .btn-entry-more:hover, {{WRAPPER}} .entry-more-btn:hover, {{WRAPPER}} .btn-entry-more:focus, {{WRAPPER}} .entry-more-btn:focus, {{WRAPPER}} .button:hover, {{WRAPPER}} .button:focus' => 'background-color: {{VALUE}};',
			),
		) );

		$this->add_control( 'button_hover_border_color', array(
			'label'     => __( 'Border Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'condition' => array(
				'border_border!' => '',
			),
			'selectors' => array(
				'{{WRAPPER}} .btn-entry-more:hover, {{WRAPPER}} .entry-more-btn:hover, {{WRAPPER}} .btn-entry-more:focus, {{WRAPPER}} .entry-more-btn:focus, {{WRAPPER}} .button:hover, {{WRAPPER}} .button:focus' => 'border-color: {{VALUE}};',
			),
		) );

		$this->end_controls_tab();

		$this->end_controls_tabs();

		$this->add_group_control( \Elementor\Group_Control_Border::get_type(), array(
			'name'      => 'border',
			'selector'  => '{{WRAPPER}} .btn-entry-more, {{WRAPPER}} .entry-more-btn, {{WRAPPER}} .button',
			'separator' => 'before',
		) );

		$this->add_control( 'border_radius', array(
			'label'      => __( 'Border Radius', 'ignition-elementor-widgets' ),
			'type'       => \Elementor\Controls_Manager::DIMENSIONS,
			'size_units' => array( 'px', '%', 'em' ),
			'selectors'  => array(
				'{{WRAPPER}} .btn-entry-more, {{WRAPPER}} .entry-more-btn, {{WRAPPER}} .button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
			),
		) );

		$this->add_group_control( \Elementor\Group_Control_Box_Shadow::get_type(), array(
			'name'     => 'button_box_shadow',
			'selector' => '{{WRAPPER}} .btn-entry-more, {{WRAPPER}} .entry-more-btn, {{WRAPPER}} .button',
		) );

		$this->add_responsive_control( 'text_padding', array(
			'label'      => __( 'Padding', 'ignition-elementor-widgets' ),
			'type'       => \Elementor\Controls_Manager::DIMENSIONS,
			'size_units' => array( 'px', 'em', '%' ),
			'selectors'  => array(
				'{{WRAPPER}} .btn-entry-more, {{WRAPPER}} .entry-more-btn, {{WRAPPER}} .button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
			),
			'separator'  => 'before',
		) );

		$this->end_controls_section();

		$this->start_controls_section( 'section_filters', array(
			'label' => __( 'Filters', 'ignition-elementor-widgets' ),
			'tab'   => \Elementor\Controls_Manager::TAB_STYLE,
		) );

		$this->add_control( 'filter_color', array(
			'label'     => __( 'Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .ci-item-filter' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'filter_active_color', array(
			'label'     => __( 'Active Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .ci-item-filter.filter-active' => 'color: {{VALUE}};',
			),
		) );

		$this->add_control( 'filter_background_color', array(
			'label'     => __( 'Background Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .ci-item-filter' => 'background-color: {{VALUE}};',
			),
		) );

		$this->add_control( 'filter_active_background_color', array(
			'label'     => __( 'Active & Hover Background Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .ci-item-filter.filter-active' => 'background-color: {{VALUE}};',
				'{{WRAPPER}} .ci-item-filter:hover'         => 'background-color: {{VALUE}};',
			),
		) );

		$this->add_control( 'filter_border_color', array(
			'label'     => __( 'Border Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .ci-item-filter' => 'border-color: {{VALUE}};',
			),
		) );

		$this->add_control( 'filter_active_border_color', array(
			'label'     => __( 'Active & Hover Border Color', 'ignition-elementor-widgets' ),
			'type'      => \Elementor\Controls_Manager::COLOR,
			'selectors' => array(
				'{{WRAPPER}} .ci-item-filter.filter-active' => 'border-color: {{VALUE}};',
				'{{WRAPPER}} .ci-item-filter:hover'         => 'border-color: {{VALUE}};',
			),
		) );

		$this->end_controls_section();

	}

	private function print_category_filters( $args ) {
		$terms = array();
		if ( $args['taxonomy'] ) {
			$terms = get_terms( $args );
		}

		?>
		<div class="ci-item-filters">
			<button class="ci-item-filter filter-active" data-filter="*">
				<?php echo esc_html( _x( 'All', 'all categories', 'gutenbee' ) ); ?>
			</button>

			<?php if ( is_array( $terms ) ) : ?>
				<?php foreach ( $terms as $term ) : ?>
					<button class="ci-item-filter" data-filter=".term-<?php echo esc_attr( $term->term_id ); ?>"><?php echo esc_html( $term->name ); ?></button>
				<?php endforeach; ?>
			<?php endif; ?>
		</div>
		<?php
	}

	protected function render() {
		$settings = $this->get_settings();

		// Not implemented like GutenBee. IDs are stored instead.
		//$post_tag_slugs = $attributes['postTagSlugs'];

		$masonry         = isset( $settings['masonry'] ) ? (bool) $settings['masonry'] : false;
		$image_size_slug = isset( $settings['image_size_slug'] ) ? $settings['image_size_slug'] : false;
		$post_type       = $settings['posts_group_post_type'];
		$pagination      = 'yes' === $settings['pagination'] ? true : false;

		// Handled by Widgets_Helper::get_query_args()
		//$posts_per_page    = $settings['posts_per_page'];
		//$offset            = $settings['offset'];
		//$order             = $settings['order'];
		//$order_by          = $settings['orderby'];
		//$excluded_post_ids = $settings[ 'post__not_in_' . $post_type ];
		//$included_post_ids = $settings[ 'post__in_' . $post_type ];
		//$author_ids        = array_filter( array_map( 'intval', $settings['posts_group_authors'] ) );

		$columns                = intval( $settings['columns'] );
		$grid_spacing           = $settings['grid_spacing'];
		$read_more_button_label = $settings['read_more_button_label'];
		$category_filters       = 'yes' === $settings['posts_group_filters'] ? true : false;
		$class_name             = isset( $settings['element_style'] ) ? 'is-style-' . $settings['element_style'] : false;

		$taxonomy_slug = isset( $settings[ 'posts_group_filter_' . $post_type ] ) ? $settings[ 'posts_group_filter_' . $post_type ] : '';

		if ( empty( $taxonomy_slug ) ) {
			$post_type_taxonomies = get_object_taxonomies( $post_type, 'objects' );
			if ( $post_type_taxonomies ) {
				$hierarchical_taxonomies = wp_list_filter( $post_type_taxonomies, array( 'hierarchical' => true ) );
				if ( $hierarchical_taxonomies ) {
					$taxonomy      = reset( $hierarchical_taxonomies );
					$taxonomy_slug = $taxonomy->name;
				}
			}
		}

		if ( ! taxonomy_exists( $taxonomy_slug ) ) {
			$taxonomy_slug = false;
		}

		$get_terms_args = array(
			'hide_empty' => 1,
		);

		if ( $taxonomy_slug ) {
			$get_terms_args['taxonomy'] = $taxonomy_slug;
		}

		$query_args = \CSSIgniter\Ignition\Elementor\Widgets_Helper::get_query_args( 'posts_group', $this->get_settings() );

		if ( $category_filters ) {
			$query_args['posts_per_page'] = -1;
			unset( $query_args['paged'] );
		}

		$columns_classes = ignition_get_columns_classes( $columns );

		$block_classes = array(
			'ignition-elementor-widget-post-types',
			$class_name,
		);

		$container_classes = array(
			'row',
			'row-items',
		);

		if ( 'no-gutters' === $grid_spacing ) {
			$container_classes[] = 'no-gutters';
		}

		if ( $masonry ) {
			$container_classes[] = 'row-isotope';
		}

		$container_classes[] = "row-columns-{$columns}";

		$container_classes = apply_filters( 'ignition_elementor_widgets_post_types_container_classes', $container_classes, $settings );
		$container_classes = array_unique( array_filter( $container_classes ) );

		$item_template_vars = array(
			'columns'                => $columns,
			'classes'                => array_filter( array_map( 'trim', explode( ' ', $class_name ) ) ),
			'image-size'             => $image_size_slug,
			'read-more-button-label' => $read_more_button_label,
		);

		$original_post_id = get_the_ID();

		if ( intval( $settings['offset'] ) > 0 ) {
			add_action( 'pre_get_posts', array( $this, 'apply_offset' ), 1 );
			add_filter( 'found_posts', array( $this, 'adjust_offset_pagination' ), 1 );
		}

		$q = new \WP_Query( $query_args );

		if ( intval( $settings['offset'] ) > 0 ) {
			remove_action( 'pre_get_posts', array( $this, 'apply_offset' ) );
			remove_filter( 'found_posts', array( $this, 'adjust_offset_pagination' ), 1 );
		}

		if ( $q->have_posts() ) {

			?><div class="<?php echo esc_attr( implode( ' ', $block_classes ) ); ?>"><?php

			if ( $category_filters && ! empty( $taxonomy_slug ) ) {
				$this->print_category_filters( $get_terms_args );
			}

			?><div class="<?php echo esc_attr( implode( ' ', $container_classes ) ); ?>"><?php

			while ( $q->have_posts() ) {
				$q->the_post();

				$classes = array();
				if ( $taxonomy_slug ) {
					$terms    = get_the_terms( get_the_ID(), $taxonomy_slug );
					$terms    = ! empty( $terms ) ? $terms : array();
					$classes  = array_map( 'urldecode', wp_list_pluck( $terms, 'slug' ) );
					$term_ids = wp_list_pluck( $terms, 'term_id' );
					foreach ( $term_ids as $term_id ) {
						$classes[] = 'term-' . $term_id;
					}
				}

				$classes[] = $columns_classes;

				?>
				<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>"><?php
				if ( 1 === $columns ) {
					$this->get_template_part( 'article-media', get_post_type(), $item_template_vars );
				} else {
					if ( $masonry ) {
						$this->get_template_part( 'article-default-tall', get_post_type(), $item_template_vars );
					} else {
						$this->get_template_part( 'article-default', get_post_type(), $item_template_vars );
					}
				}
				?></div><?php
			}

			?></div><?php

			if ( class_exists( '\Elementor\Plugin' ) ) {
				if ( ! $this->is_elementor_preview() || $this->is_elementor_preview( $original_post_id ) ) {
					wp_reset_postdata();
				}
			} else {
				wp_reset_postdata();
			}

			if ( $q->max_num_pages > 1 && true === $pagination ) {
				ignition_posts_pagination( array(), $q );
			}

			?></div><?php
		}

	}

	private function is_elementor_preview( $post_id = 0 ) {
		$preview_post_id = 0;

		if ( isset( $_GET['action'] ) && 'elementor' === $_GET['action'] && isset( $_GET['post'] ) && (int) $_GET['post'] > 0 ) {
			$preview_post_id = (int) $_GET['post'];
		} elseif ( isset( $_GET['elementor-preview'] ) && (int) $_GET['elementor-preview'] > 0 ) {
			$preview_post_id = (int) $_GET['elementor-preview'];
		}

		if ( ! $preview_post_id || ! class_exists( '\Elementor\Plugin' ) ) {
			return false;
		}

		if ( ! \Elementor\User::is_current_user_can_edit( $preview_post_id ) ) {
			return false;
		}

		if ( ! empty( $post_id ) && $post_id !== $preview_post_id ) {
			return false;
		}

		return true;
	}

	/**
	 * Applies offset to the custom query. According to https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
	 *
	 * @param object $query the custom query
	 */
	public function apply_offset( &$query ) {

		$settings = $this->get_settings();

		$offset = $settings['offset'];
		$ppp    = $settings['posts_per_page'];

		if ( $query->is_paged ) {

			$page_offset = $offset + ( ( $query->query_vars['paged'] - 1 ) * $ppp );

			$query->set( 'offset', $page_offset );

		} else {
			$query->set( 'offset', $offset );
		}
	}

	/**
	 * Fixes the pagination on custom queries with offset. According to https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
	 *
	 * @param int $found_posts the number of found posts for the custom query.
	 */
	public function adjust_offset_pagination( $found_posts ) {

		$settings = $this->get_settings();
		$offset   = $settings['offset'];

		return $found_posts - $offset;
	}

	private function get_template_part( $slug, $name = '', $args = array() ) {
		$templates = array();
		$name      = (string) $name;
		if ( '' !== $name ) {
			$templates[] = "{$slug}-{$name}.php";
		}

		$templates[] = "{$slug}.php";

		$located = $this->locate_template( $templates, $args );

		if ( ! empty( $located ) ) {
			include $located;
		}
	}

	private function locate_template( $templates, $args ) {
		$plugin_path = plugin_dir_path( __DIR__ );

		// The templates path in the plugin, i.e. /template-parts
		$default_path = untrailingslashit( $plugin_path ) . '/template-parts';

		// The templates path in the theme.
		$theme_path = apply_filters( 'ignition_elementor_widgets_locate_template_theme_path', 'template-parts/ignition-elementor-widgets' );

		$theme_templates = array();
		foreach ( $templates as $template ) {
			$theme_templates[] = trailingslashit( $theme_path ) . $template;
		}

		// Try to find a theme-overridden template.
		$located = locate_template( $theme_templates, false );
		$located = apply_filters( 'ignition_elementor_widgets_locate_template', $located, $theme_templates, $templates, $theme_path, $default_path, $args );

		if ( empty( $located ) ) {
			// Nope. Try the plugin templates instead.
			foreach ( $templates as $template ) {
				if ( file_exists( trailingslashit( $default_path ) . $template ) ) {
					$located = trailingslashit( $default_path ) . $template;
					break;
				}
			}
		}

		return $located;
	}

	/**
	 * Get the registered image size names in WordPress and create labels for them.
	 *
	 * @return array $image_sizes an associative array of registered image sizes and their generated labels.
	 */
	private function get_registered_image_sizes() {
		$registered_sizes   = get_intermediate_image_sizes();
		$registered_sizes[] = 'full';

		$image_sizes = array();

		foreach ( $registered_sizes as $size ) {
			if ( $size === 'full' ) {
				$name  = 'full';
				$label = __( 'Full Size', 'text-domain' );
			} else {
				$name  = $size;
				$words = preg_split( '/[_-]/', $size );
				$label = implode( ' ', array_map( 'ucfirst', $words ) );
			}

			$image_sizes[ $name ] = $label;
		}

		return $image_sizes;
	}

}
