<?php
namespace PowerpackElements\Modules\EventCalendar\Widgets;

use PowerpackElements\Base\Powerpack_Widget;
use PowerpackElements\Classes\PP_Posts_Helper;
use PowerpackElements\Classes\PP_Helper;
use PowerpackElements\Classes\PP_Admin_Settings;

// Elementor Classes
use Elementor\Controls_Manager;
use Elementor\Control_Media;
use Elementor\Utils;
use Elementor\Icons_Manager;
use Elementor\Repeater;
use Elementor\Group_Control_Image_Size;
use Elementor\Group_Control_Background;
use Elementor\Group_Control_Box_Shadow;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Typography;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
use Elementor\Core\Kits\Documents\Tabs\Global_Colors;

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

/**
 * Event Calendar Widget
 */
class Event_Calendar extends Powerpack_Widget {

	/**
	 * Retrieve Event Calendar widget name.
	 *
	 * @access public
	 *
	 * @return string Widget name.
	 */
	public function get_name() {
		return parent::get_widget_name( 'Event_Calendar' );
	}

	/**
	 * Retrieve Event Calendar widget title.
	 *
	 * @access public
	 *
	 * @return string Widget title.
	 */
	public function get_title() {
		return parent::get_widget_title( 'Event_Calendar' );
	}

	/**
	 * Retrieve Event Calendar widget icon.
	 *
	 * @access public
	 *
	 * @return string Widget icon.
	 */
	public function get_icon() {
		return parent::get_widget_icon( 'Event_Calendar' );
	}

	/**
	 * Get widget keywords.
	 *
	 * Retrieve the list of keywords the widget belongs to.
	 *
	 * @access public
	 *
	 * @return array Widget keywords.
	 */
	public function get_keywords() {
		return parent::get_widget_keywords( 'Event_Calendar' );
	}

	/**
	 * Retrieve the list of scripts the Event Calendar widget depended on.
	 *
	 * Used to set scripts dependencies required to run the widget.
	 *
	 * @access public
	 *
	 * @return array Widget scripts dependencies.
	 */
	public function get_script_depends() {
		return [
			'fullcalendar',
			'pp-event-calendar',
		];
	}

	/**
	 * Retrieve the list of styles the Event Calendar widget depended on.
	 *
	 * Used to set styles dependencies required to run the widget.
	 *
	 * @access public
	 *
	 * @return array Widget scripts dependencies.
	 */
	public function get_style_depends() {
		return [
			'widget-pp-event-calendar',
		];
	}

	/**
	 * Register Event Calendar widget controls.
	 *
	 * Adds different input fields to allow the user to change and customize the widget settings.
	 *
	 * @access protected
	 */
	protected function _register_controls() { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
		$this->register_controls();
	}

	/**
	 * Register Event Calendar widget controls.
	 *
	 * Adds different input fields to allow the user to change and customize the widget settings.
	 *
	 * @since 3.0.0
	 * @access protected
	 */
	protected function register_controls() {
		/* Content Tab */
		$this->register_content_event_controls();
		$this->register_content_query_controls();
		$this->register_content_posts_fields_controls();
		$this->register_content_header_toolbar_controls();
		$this->register_content_footer_toolbar_controls();
		$this->register_content_event_click_controls();
		$this->register_content_navigation_controls();
		$this->register_content_settings_controls();

		/* Style Tab */
		$this->register_style_calendar_controls();
		$this->register_style_toolbar_controls();
		$this->register_style_header_controls();
		$this->register_style_rows_controls();
		$this->register_style_days_controls();
		$this->register_style_event_controls();
		$this->register_popup_style_controls();
	}

	/*-----------------------------------------------------------------------------------*/
	/*	CONTENT TAB
	/*-----------------------------------------------------------------------------------*/

	/**
	 * Content Tab: Calendar
	 */
	protected function register_content_event_controls() {
		$this->start_controls_section(
			'section_calendar_events',
			[
				'label' => esc_html__( 'Events', 'powerpack' ),
			]
		);

		$source_options = [
			'custom' => esc_html__( 'Custom', 'powerpack' ),
			'posts'  => esc_html__( 'Posts', 'powerpack' ),
			'gcal'   => esc_html__( 'Google Calendar', 'powerpack' ),
		];

		$this->add_control(
			'calendar_source',
			[
				'label'              => esc_html__( 'Source', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'options'            => $source_options,
				'default'            => 'custom',
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'google_calendar_id',
			[
				'label'       => esc_html__( 'Calendar ID', 'powerpack' ),
				'description' => sprintf( esc_html__( 'Click %1$s here %2$s to get your Google Calendar ID.', 'powerpack' ), '<a href="https://docs.simplecalendar.io/find-google-calendar-id/" target="_blank" rel="noopener">', '</a>' ),
				'label_block' => true,
				'type'        => Controls_Manager::TEXT,
				'default'     => '',
				'condition'   => [
					'calendar_source' => 'gcal',
				],
			]
		);

		$this->add_control(
			'google_calendar_start_date',
			[
				'label'     => esc_html__( 'Start Date', 'powerpack' ),
				'type'      => Controls_Manager::DATE_TIME,
				'default'   => gmdate( 'Y-m-d H:i:s', current_time( 'timestamp', 0 ) ),
				'condition' => [
					'calendar_source' => 'gcal',
				],
			]
		);

		$this->add_control(
			'google_calendar_end_date',
			[
				'label'     => esc_html__( 'End Date', 'powerpack' ),
				'type'      => Controls_Manager::DATE_TIME,
				'default'   => gmdate( 'Y-m-d H:i:s', strtotime( '+6 months', current_time( 'timestamp', 0 ) ) ),
				'condition' => [
					'calendar_source' => 'gcal',
				],
			]
		);

		$this->add_control(
			'google_calendar_max_item',
			[
				'label'     => esc_html__( 'Number Of Events', 'powerpack' ),
				'type'      => Controls_Manager::NUMBER,
				'min'       => 1,
				'max'       => 2500,
				'default'   => 100,
				'condition' => [
					'calendar_source' => 'gcal',
				],
			]
		);

		$this->add_control(
			'set_post_limit',
			[
				'label'        => esc_html__( 'Set Post Limit', 'powerpack' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'powerpack' ),
				'label_off'    => esc_html__( 'No', 'powerpack' ),
				'return_value' => 'yes',
				'default'      => '',
				'condition'    => [
					'calendar_source' => 'posts',
				],
			]
		);

		$this->add_control(
			'posts_per_page',
			[
				'label'     => esc_html__( 'Posts Count', 'powerpack' ),
				'type'      => Controls_Manager::NUMBER,
				'default'   => 10,
				'condition' => [
					'calendar_source' => 'posts',
					'set_post_limit'  => 'yes',
				],
			]
		);

		$repeater = new Repeater();

		$repeater->start_controls_tabs( 'tabs_events' );

		$repeater->start_controls_tab(
			'tab_event_details',
			[
				'label' => esc_html__( 'Details', 'powerpack' ),
			]
		);

		$repeater->add_control(
			'event_title',
			[
				'label'       => esc_html__( 'Event Title', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'default'     => esc_html__( 'Event Title', 'powerpack' ),
				'label_block' => true,
				'dynamic'     => [
					'active'   => true,
				],
			]
		);

		$repeater->add_control(
			'guest',
			[
				'label'       => esc_html__( 'Guest/Speaker', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'default'     => esc_html__( 'John Doe', 'powerpack' ),
				'ai'          => [
					'active' => false,
				],
				'dynamic'     => [
					'active' => true,
				],
			]
		);

		$repeater->add_control(
			'location',
			[
				'label'       => esc_html__( 'Location', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'default'     => esc_html__( '4382 Roosevelt Road, KS, Kansas', 'powerpack' ),
				'ai'          => [
					'active' => false,
				],
				'dynamic'     => [
					'active' => true,
				],
			]
		);

		$repeater->add_control(
			'all_day',
			[
				'label'        => esc_html__( 'All Day Event', 'powerpack' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_block'  => false,
				'return_value' => 'yes',
			]
		);

		$repeater->add_control(
			'start_event',
			[
				'label'       => esc_html__( 'Start Time', 'powerpack' ),
				'type'        => Controls_Manager::DATE_TIME,
				'label_block' => true,
				'multiple'    => false,
				'placeholder' => esc_html__( 'Choose', 'powerpack' ),
				'default'     => gmdate( 'Y-m-d H:i', current_time( 'timestamp', 0 ) ),
				'condition'   => [
					'all_day' => '',
				],
			]
		);

		$repeater->add_control(
			'end_event',
			[
				'label'       => esc_html__( 'End Time', 'powerpack' ),
				'type'        => Controls_Manager::DATE_TIME,
				'label_block' => true,
				'multiple'    => false,
				'placeholder' => esc_html__( 'Choose', 'powerpack' ),
				'default'     => gmdate( 'Y-m-d H:i', strtotime( '+59 minute', current_time( 'timestamp', 0 ) ) ),
				'condition'   => [
					'all_day' => '',
				],
			]
		);

		$repeater->add_control(
			'start_event_allday',
			[
				'label'          => esc_html__( 'Start Date', 'powerpack' ),
				'type'           => Controls_Manager::DATE_TIME,
				'picker_options' => ['enableTime' => false],
				'default'        => gmdate( 'Y-m-d', current_time( 'timestamp', 0 ) ),
				'condition'      => [
					'all_day' => 'yes',
				],
			]
		);

		$repeater->add_control(
			'end_event_allday',
			[
				'label'          => esc_html__( 'End Date', 'powerpack' ),
				'type'           => Controls_Manager::DATE_TIME,
				'picker_options' => ['enableTime' => false],
				'default'        => gmdate( 'Y-m-d', current_time( 'timestamp', 0 ) ),
				'condition'      => [
					'all_day' => 'yes',
				],
			]
		);

		$repeater->add_control(
			'event_url',
			[
				'label'       => esc_html__( 'Event Link', 'powerpack' ),
				'type'        => Controls_Manager::URL,
				'label_block' => true,
				'dynamic'     => [
					'active' => true,
				],
				'default'     => [
					'url' => 'https://powerpackelements.com/',
				],
				'placeholder' => esc_html__( 'https://powerpackelements.com/', 'powerpack' ),
				'description' => esc_html__( 'Opened when "On Event Click" is set to "Open Link". Also used as the "Read More" link inside the event popup.', 'powerpack' ),
			]
		);

		$repeater->add_control(
			'image',
			[
				'label'   => esc_html__( 'Choose Image', 'powerpack' ),
				'type'    => Controls_Manager::MEDIA,
				'default' => [
					'url' => Utils::get_placeholder_image_src(),
				],
			]
		);

		$repeater->add_group_control(
			Group_Control_Image_Size::get_type(),
			[
				'name'      => 'thumbnail',
				'label'     => 'Thumbnail Size',
				'default'   => 'thumbnail',
				'separator' => 'before',
				'exclude'   => [
					'custom',
				],
			]
		);

		$repeater->end_controls_tab();

		$repeater->start_controls_tab(
			'tab_event_description',
			[
				'label' => esc_html__( 'Description', 'powerpack' ),
			]
		);

		$repeater->add_control(
			'description',
			[
				'label'      => esc_html__( 'Description', 'powerpack' ),
				'show_label' => true,
				'type'       => Controls_Manager::WYSIWYG,
				'default'    => esc_html__( 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries', 'powerpack' )
			]
		);

		$repeater->end_controls_tab();

		$repeater->start_controls_tab(
			'tab_event_style',
			[
				'label' => esc_html__( 'Style', 'powerpack' ),
			]
		);

		$repeater->add_control(
			'custom_style',
			[
				'label'          => esc_html__( 'Custom Style', 'powerpack' ),
				'type'           => Controls_Manager::SWITCHER,
				'label_on'       => esc_html__( 'Yes', 'powerpack' ),
				'label_off'      => esc_html__( 'No', 'powerpack' ),
				'return_value'   => 'yes',
				'default'        => 'no',
				'style_transfer' => true,
			]
		);

		$repeater->add_control(
			'text_color',
			[
				'label'          => esc_html__( 'Text Color', 'powerpack' ),
				'type'           => Controls_Manager::COLOR,
				'selectors'      => [
					'{{WRAPPER}} .pp-event-calendar-container {{CURRENT_ITEM}}' => 'color: {{VALUE}}!important;',
					'{{WRAPPER}} .pp-event-calendar-container {{CURRENT_ITEM}} .fc-event-main' => 'color: {{VALUE}}!important;',
				],
				'condition'      => [
					'custom_style' => 'yes',
				],
				'style_transfer' => true,
			]
		);

		$repeater->add_control(
			'event_color',
			[
				'label'          => esc_html__( 'Event Color', 'powerpack' ),
				'type'           => Controls_Manager::COLOR,
				'selectors'      => [
					// Block events (all-day, time grid, Block display): fill and border.
					'{{WRAPPER}} .pp-event-calendar-container {{CURRENT_ITEM}}.fc-daygrid-block-event' => 'background-color: {{VALUE}}!important; border-color: {{VALUE}}!important;',
					'{{WRAPPER}} .pp-event-calendar-container {{CURRENT_ITEM}}.fc-timegrid-event' => 'background-color: {{VALUE}}!important; border-color: {{VALUE}}!important;',
					// Dot events (auto timed, list, Dot display): color the dot.
					'{{WRAPPER}} .pp-event-calendar-container {{CURRENT_ITEM}} .fc-daygrid-event-dot' => 'border-color: {{VALUE}}!important;',
					'{{WRAPPER}} .pp-event-calendar-container {{CURRENT_ITEM}} .fc-list-event-dot' => 'border-color: {{VALUE}}!important;',
				],
				'condition'      => [
					'custom_style' => 'yes',
				],
				'style_transfer' => true,
			]
		);

		$repeater->end_controls_tab();

		$month = gmdate( 'Y-m', current_time( 'timestamp', 0 ) );

		$this->add_control(
			'events',
			[
				'label'              => esc_html__( 'Events', 'powerpack' ),
				'type'               => Controls_Manager::REPEATER,
				'default'            => [
					[
						'event_title'  => esc_html__( 'Product Strategy Workshop', 'powerpack' ),
						'guest'        => esc_html__( 'Sarah Mitchell', 'powerpack' ),
						'location'     => esc_html__( 'Convention Center, Hall A, Chicago', 'powerpack' ),
						'start_event'  => $month . '-08 10:00',
						'end_event'    => $month . '-08 11:00',
						'custom_style' => 'yes',
						'event_color'  => '#5b8aa6',
					],
					[
						'event_title'  => esc_html__( 'Annual Design Conference', 'powerpack' ),
						'guest'        => esc_html__( 'James Carter', 'powerpack' ),
						'location'     => esc_html__( 'Grand Plaza Hotel, New York', 'powerpack' ),
						'start_event'  => $month . '-08 14:00',
						'end_event'    => $month . '-08 15:00',
						'custom_style' => 'yes',
						'event_color'  => '#7a9b76',
					],
					[
						'event_title'  => esc_html__( 'Marketing Masterclass', 'powerpack' ),
						'guest'        => esc_html__( 'Emily Roberts', 'powerpack' ),
						'location'     => esc_html__( 'Riverside Auditorium, Austin', 'powerpack' ),
						'start_event'  => $month . '-13 09:30',
						'end_event'    => $month . '-13 10:30',
						'custom_style' => 'yes',
						'event_color'  => '#bd8158',
					],
					[
						'event_title'  => esc_html__( 'Tech Leadership Summit', 'powerpack' ),
						'guest'        => esc_html__( 'Michael Chen', 'powerpack' ),
						'location'     => esc_html__( 'Innovation Hub, San Francisco', 'powerpack' ),
						'start_event'  => $month . '-28 13:00',
						'end_event'    => $month . '-28 14:00',
						'custom_style' => 'yes',
						'event_color'  => '#8d7399',
					],
				],
				'fields'             => $repeater->get_controls(),
				'title_field'        => '{{{ event_title }}}',
				'frontend_available' => true,
				'condition'          => [
					'calendar_source' => 'custom',
				],
			]
		);

		$this->end_controls_section();
	}

	protected function register_content_query_controls() {
		/**
		 * Content Tab: Query
		 */
		$this->start_controls_section(
			'section_post_query',
			[
				'label'                 => esc_html__( 'Query', 'powerpack' ),
				'condition'             => [
					'calendar_source'    => 'posts',
				],
			]
		);

		$this->add_control(
			'post_type',
			[
				'label'                 => esc_html__( 'Post Type', 'powerpack' ),
				'type'                  => Controls_Manager::SELECT,
				'options'               => PP_Posts_Helper::get_post_types(),
				'default'               => 'post',

			]
		);

		$post_types = PP_Posts_Helper::get_post_types();

		foreach ( $post_types as $post_type_slug => $post_type_label ) {

			$taxonomy = PP_Posts_Helper::get_post_taxonomies( $post_type_slug );

			if ( ! empty( $taxonomy ) ) {

				foreach ( $taxonomy as $index => $tax ) {

					$terms = PP_Posts_Helper::get_tax_terms( $index );

					$tax_terms = [];

					if ( ! empty( $terms ) ) {

						foreach ( $terms as $term_index => $term_obj ) {

							$tax_terms[ $term_obj->term_id ] = $term_obj->name;
						}

						if ( 'post' === $post_type_slug ) {
							if ( 'post_tag' === $index ) {
								$tax_control_key = 'tags';
							} elseif ( 'category' === $index ) {
								$tax_control_key = 'categories';
							} else {
								$tax_control_key = $index . '_' . $post_type_slug;
							}
						} else {
							$tax_control_key = $index . '_' . $post_type_slug;
						}

						// Taxonomy filter type
						$this->add_control(
							$index . '_' . $post_type_slug . '_filter_type',
							[
								/* translators: %s Label */
								'label'       => sprintf( esc_html__( '%s Filter Type', 'powerpack' ), $tax->label ),
								'type'        => Controls_Manager::SELECT,
								'default'     => 'IN',
								'label_block' => true,
								'options'     => [
									/* translators: %s label */
									'IN'     => sprintf( esc_html__( 'Include %s', 'powerpack' ), $tax->label ),
									/* translators: %s label */
									'NOT IN' => sprintf( esc_html__( 'Exclude %s', 'powerpack' ), $tax->label ),
								],
								'separator'         => 'before',
								'condition'   => [
									'post_type' => $post_type_slug,
								],
							]
						);

						$this->add_control(
							$tax_control_key,
							[
								'label'         => $tax->label,
								'type'          => 'pp-query',
								'post_type'     => $post_type_slug,
								'options'       => [],
								'label_block'   => true,
								'multiple'      => true,
								'query_type'    => 'terms',
								'object_type'   => $index,
								'include_type'  => true,
								'condition'   => [
									'post_type' => $post_type_slug,
								],
							]
						);

					}
				}
			}
		}

		$this->add_control(
			'author_filter_type',
			[
				'label'       => esc_html__( 'Authors Filter Type', 'powerpack' ),
				'type'        => Controls_Manager::SELECT,
				'default'     => 'author__in',
				'label_block' => true,
				'separator'         => 'before',
				'options'     => [
					'author__in'     => esc_html__( 'Include Authors', 'powerpack' ),
					'author__not_in' => esc_html__( 'Exclude Authors', 'powerpack' ),
				],
			]
		);

		$this->add_control(
			'authors',
			[
				'label'                 => esc_html__( 'Authors', 'powerpack' ),
				'type'                  => 'pp-query',
				'label_block'           => true,
				'multiple'              => true,
				'query_type'            => 'authors',
				'condition'         => [
					'post_type!' => 'related',
				],
			]
		);

		foreach ( $post_types as $post_type_slug => $post_type_label ) {

			if ( 'post' === $post_type_slug ) {
				$posts_control_key = 'exclude_posts';
			} else {
				$posts_control_key = $post_type_slug . '_filter';
			}

			$this->add_control(
				$post_type_slug . '_filter_type',
				[
					'label'             => sprintf( esc_html__( '%s Filter Type', 'powerpack' ), $post_type_label ),
					'type'              => Controls_Manager::SELECT,
					'default'           => 'post__not_in',
					'label_block'       => true,
					'separator'         => 'before',
					'options'           => [
						'post__in'     => sprintf( esc_html__( 'Include %s', 'powerpack' ), $post_type_label ),
						'post__not_in' => sprintf( esc_html__( 'Exclude %s', 'powerpack' ), $post_type_label ),
					],
					'condition'   => [
						'post_type' => $post_type_slug,
					],
				]
			);

			$this->add_control(
				$posts_control_key,
				[
					/* translators: %s Label */
					'label'             => $post_type_label,
					'type'              => 'pp-query',
					'default'           => '',
					'multiple'          => true,
					'label_block'       => true,
					'query_type'        => 'posts',
					'object_type'       => $post_type_slug,
					'condition'         => [
						'post_type' => $post_type_slug,
					],
				]
			);
		}

		$this->add_control(
			'select_date',
			[
				'label'             => esc_html__( 'Date', 'powerpack' ),
				'type'              => Controls_Manager::SELECT,
				'options'           => [
					'anytime'   => esc_html__( 'All', 'powerpack' ),
					'today'     => esc_html__( 'Past Day', 'powerpack' ),
					'week'      => esc_html__( 'Past Week', 'powerpack' ),
					'month'     => esc_html__( 'Past Month', 'powerpack' ),
					'quarter'   => esc_html__( 'Past Quarter', 'powerpack' ),
					'year'      => esc_html__( 'Past Year', 'powerpack' ),
					'exact'     => esc_html__( 'Custom', 'powerpack' ),
				],
				'default'           => 'anytime',
				'label_block'       => false,
				'multiple'          => false,
				'separator'         => 'before',
			]
		);

		$this->add_control(
			'date_before',
			[
				'label'             => esc_html__( 'Before', 'powerpack' ),
				'description'       => esc_html__( 'Setting a ‘Before’ date will show all the posts published until the chosen date (inclusive).', 'powerpack' ),
				'type'              => Controls_Manager::DATE_TIME,
				'label_block'       => false,
				'multiple'          => false,
				'placeholder'       => esc_html__( 'Choose', 'powerpack' ),
				'condition'         => [
					'select_date' => 'exact',
				],
			]
		);

		$this->add_control(
			'date_after',
			[
				'label'             => esc_html__( 'After', 'powerpack' ),
				'description'       => esc_html__( 'Setting an ‘After’ date will show all the posts published since the chosen date (inclusive).', 'powerpack' ),
				'type'              => Controls_Manager::DATE_TIME,
				'label_block'       => false,
				'multiple'          => false,
				'placeholder'       => esc_html__( 'Choose', 'powerpack' ),
				'condition'         => [
					'select_date' => 'exact',
				],
			]
		);

		$this->add_control(
			'order',
			[
				'label'             => esc_html__( 'Order', 'powerpack' ),
				'type'              => Controls_Manager::SELECT,
				'options'           => [
					'DESC'      => esc_html__( 'Descending', 'powerpack' ),
					'ASC'       => esc_html__( 'Ascending', 'powerpack' ),
				],
				'default'           => 'DESC',
				'separator'         => 'before',
			]
		);

		$this->add_control(
			'orderby',
			[
				'label'             => esc_html__( 'Order By', 'powerpack' ),
				'type'              => Controls_Manager::SELECT,
				'options'           => [
					'date'           => esc_html__( 'Date', 'powerpack' ),
					'modified'       => esc_html__( 'Last Modified Date', 'powerpack' ),
					'rand'           => esc_html__( 'Random', 'powerpack' ),
					'comment_count'  => esc_html__( 'Comment Count', 'powerpack' ),
					'title'          => esc_html__( 'Title', 'powerpack' ),
					'ID'             => esc_html__( 'Post ID', 'powerpack' ),
					'author'         => esc_html__( 'Post Author', 'powerpack' ),
				],
				'default'           => 'date',
			]
		);

		$this->add_control(
			'exclude_current',
			[
				'label'        => esc_html__( 'Exclude Current Post', 'powerpack' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'powerpack' ),
				'label_off'    => esc_html__( 'No', 'powerpack' ),
				'return_value' => 'yes',
				'default'      => '',
				'description'  => esc_html__( 'Enable this option to remove current post from the query.', 'powerpack' ),
			]
		);

		$this->add_control(
			'offset',
			[
				'label'             => esc_html__( 'Offset', 'powerpack' ),
				'description'       => esc_html__( 'Use this setting to skip this number of initial posts', 'powerpack' ),
				'type'              => Controls_Manager::NUMBER,
				'default'           => '',
				'separator'         => 'before',
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Content Tab: Event Fields (Posts source field mapping).
	 *
	 * Lets the user map each calendar event property (start/end date, location,
	 * speaker, description, image) to a post-meta key or an ACF field so the
	 * Posts source can show the same information as the Custom source.
	 *
	 * @since 3.0.0
	 * @access protected
	 */
	protected function register_content_posts_fields_controls() {
		$this->start_controls_section(
			'section_posts_fields',
			[
				'label'     => esc_html__( 'Event Fields', 'powerpack' ),
				'condition' => [
					'calendar_source' => 'posts',
				],
			]
		);

		$field_source_options = [
			'meta' => esc_html__( 'Custom Field', 'powerpack' ),
		];

		if ( class_exists( 'acf' ) ) {
			$field_source_options['acf'] = esc_html__( 'ACF', 'powerpack' );
		}

		$this->add_control(
			'posts_field_source',
			[
				'label'       => esc_html__( 'Read Fields From', 'powerpack' ),
				'type'        => Controls_Manager::SELECT,
				'options'     => $field_source_options,
				'default'     => 'meta',
				'description' => esc_html__( 'Choose where each event detail is read from for every post in the query.', 'powerpack' ),
			]
		);

		$acf_query = function( $field_types ) {
			return [
				'type'          => 'pp-query',
				'label_block'   => true,
				'multiple'      => false,
				'query_type'    => 'acf',
				'query_options' => [
					'show_type'       => false,
					'show_field_type' => true,
					'field_type'      => $field_types,
				],
			];
		};

		// Event Date & Time.
		$this->add_control(
			'posts_date_heading',
			[
				'label'     => esc_html__( 'Event Date & Time', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'posts_start_meta_key',
			[
				'label'       => esc_html__( 'Start Date Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'description' => esc_html__( 'Custom field (meta) key that stores the event start date/time. If empty, the post published date is used as an all-day event.', 'powerpack' ),
				'condition'   => [
					'posts_field_source' => 'meta',
				],
			]
		);

		$this->add_control(
			'posts_start_acf_field',
			array_merge(
				$acf_query( [ 'date' ] ),
				[
					'label'       => esc_html__( 'Start Date Field', 'powerpack' ),
					'description' => esc_html__( 'ACF date field for the event start. If empty, the post published date is used as an all-day event.', 'powerpack' ),
					'condition'   => [
						'posts_field_source' => 'acf',
					],
				]
			)
		);

		$this->add_control(
			'posts_end_meta_key',
			[
				'label'       => esc_html__( 'End Date Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'description' => esc_html__( 'Optional. Custom field (meta) key that stores the event end date/time.', 'powerpack' ),
				'condition'   => [
					'posts_field_source' => 'meta',
				],
			]
		);

		$this->add_control(
			'posts_end_acf_field',
			array_merge(
				$acf_query( [ 'date' ] ),
				[
					'label'       => esc_html__( 'End Date Field', 'powerpack' ),
					'description' => esc_html__( 'Optional ACF date field for the event end.', 'powerpack' ),
					'condition'   => [
						'posts_field_source' => 'acf',
					],
				]
			)
		);

		$this->add_control(
			'posts_all_day',
			[
				'label'   => esc_html__( 'All Day', 'powerpack' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'auto',
				'options' => [
					'auto'  => esc_html__( 'Auto (detect from start value)', 'powerpack' ),
					'yes'   => esc_html__( 'Always All Day', 'powerpack' ),
					'no'    => esc_html__( 'Never All Day', 'powerpack' ),
					'field' => esc_html__( 'From Field', 'powerpack' ),
				],
			]
		);

		$this->add_control(
			'posts_all_day_meta_key',
			[
				'label'       => esc_html__( 'All Day Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'description' => esc_html__( 'Custom field (meta) key holding a truthy value when the event lasts all day.', 'powerpack' ),
				'condition'   => [
					'posts_field_source' => 'meta',
					'posts_all_day'      => 'field',
				],
			]
		);

		$this->add_control(
			'posts_all_day_acf_field',
			array_merge(
				$acf_query( [ 'boolean' ] ),
				[
					'label'     => esc_html__( 'All Day Field', 'powerpack' ),
					'condition' => [
						'posts_field_source' => 'acf',
						'posts_all_day'      => 'field',
					],
				]
			)
		);

		// Event Details.
		$this->add_control(
			'posts_details_heading',
			[
				'label'     => esc_html__( 'Event Details', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'posts_location_meta_key',
			[
				'label'       => esc_html__( 'Location Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'condition'   => [
					'posts_field_source' => 'meta',
				],
			]
		);

		$this->add_control(
			'posts_location_acf_field',
			array_merge(
				$acf_query( [ 'textual', 'googlemap' ] ),
				[
					'label'     => esc_html__( 'Location Field', 'powerpack' ),
					'condition' => [
						'posts_field_source' => 'acf',
					],
				]
			)
		);

		$this->add_control(
			'posts_speaker_meta_key',
			[
				'label'       => esc_html__( 'Speaker / Guest Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'condition'   => [
					'posts_field_source' => 'meta',
				],
			]
		);

		$this->add_control(
			'posts_speaker_acf_field',
			array_merge(
				$acf_query( [ 'textual' ] ),
				[
					'label'     => esc_html__( 'Speaker / Guest Field', 'powerpack' ),
					'condition' => [
						'posts_field_source' => 'acf',
					],
				]
			)
		);

		// Description.
		$this->add_control(
			'posts_description_source',
			[
				'label'     => esc_html__( 'Description', 'powerpack' ),
				'type'      => Controls_Manager::SELECT,
				'default'   => 'excerpt',
				'separator' => 'before',
				'options'   => [
					'none'    => esc_html__( 'None', 'powerpack' ),
					'excerpt' => esc_html__( 'Post Excerpt', 'powerpack' ),
					'content' => esc_html__( 'Post Content', 'powerpack' ),
					'field'   => esc_html__( 'Field', 'powerpack' ),
				],
			]
		);

		$this->add_control(
			'posts_description_meta_key',
			[
				'label'       => esc_html__( 'Description Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'condition'   => [
					'posts_field_source'       => 'meta',
					'posts_description_source' => 'field',
				],
			]
		);

		$this->add_control(
			'posts_description_acf_field',
			array_merge(
				$acf_query( [ 'textual' ] ),
				[
					'label'     => esc_html__( 'Description Field', 'powerpack' ),
					'condition' => [
						'posts_field_source'       => 'acf',
						'posts_description_source' => 'field',
					],
				]
			)
		);

		// Image.
		$this->add_control(
			'posts_image_source',
			[
				'label'     => esc_html__( 'Image', 'powerpack' ),
				'type'      => Controls_Manager::SELECT,
				'default'   => 'featured',
				'separator' => 'before',
				'options'   => [
					'none'     => esc_html__( 'None', 'powerpack' ),
					'featured' => esc_html__( 'Featured Image', 'powerpack' ),
					'field'    => esc_html__( 'Field', 'powerpack' ),
				],
			]
		);

		$this->add_control(
			'posts_image_meta_key',
			[
				'label'       => esc_html__( 'Image Field', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [ 'active' => true ],
				'ai'          => [ 'active' => false ],
				'description' => esc_html__( 'Custom field (meta) key holding an attachment ID or an image URL.', 'powerpack' ),
				'condition'   => [
					'posts_field_source'  => 'meta',
					'posts_image_source'  => 'field',
				],
			]
		);

		$this->add_control(
			'posts_image_acf_field',
			array_merge(
				$acf_query( [ 'image' ] ),
				[
					'label'     => esc_html__( 'Image Field', 'powerpack' ),
					'condition' => [
						'posts_field_source' => 'acf',
						'posts_image_source' => 'field',
					],
				]
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Button options shared across every toolbar slot.
	 */
	protected function get_toolbar_button_options() {
		return [
			'title'        => esc_html__( 'Calendar Title', 'powerpack' ),
			'prevYear'     => esc_html__( 'Previous Year', 'powerpack' ),
			'prev'         => esc_html__( 'Previous Month', 'powerpack' ),
			'next'         => esc_html__( 'Next Month', 'powerpack' ),
			'nextYear'     => esc_html__( 'Next Year', 'powerpack' ),
			'today'        => esc_html__( 'Today', 'powerpack' ),
			'dayGridMonth' => esc_html__( 'Day Grid Month', 'powerpack' ),
			'dayGridWeek'  => esc_html__( 'Day Grid Week', 'powerpack' ),
			'dayGridDay'   => esc_html__( 'Day Grid Day', 'powerpack' ),
			'listMonth'    => esc_html__( 'List Month', 'powerpack' ),
		];
	}

	/**
	 * Register a single toolbar slot (header/footer × left/center/right) as a repeater of button groups.
	 * Each row is one group: buttons within a row render touching; rows render space-separated.
	 *
	 * @param string $key       Control key (e.g. 'header_left_groups').
	 * @param string $label     Visible label (e.g. 'Header Left').
	 * @param array  $defaults  Default groups, each a [ 'buttons' => [..] ] entry.
	 * @param array  $condition Optional Elementor condition.
	 */
	protected function add_toolbar_slot_control( $key, $label, $defaults = [], $condition = [] ) {
		$group_repeater = new Repeater();
		$group_repeater->add_control(
			'buttons',
			[
				'label'       => esc_html__( 'Buttons in Group', 'powerpack' ),
				'type'        => Controls_Manager::SELECT2,
				'label_block' => true,
				'multiple'    => true,
				'options'     => $this->get_toolbar_button_options(),
				'description' => esc_html__( 'Buttons in a single group are placed together with no space between them. Add another group to insert a space.', 'powerpack' ),
			]
		);

		$args = [
			'label'              => $label,
			'type'               => Controls_Manager::REPEATER,
			'fields'             => $group_repeater->get_controls(),
			'default'            => $defaults,
			'title_field'        => '<# if ( buttons && buttons.length ) { print( "[ " + buttons.join(" · ") + " ]" ); } else { print("Empty group"); } #>',
			'frontend_available' => true,
			'prevent_empty'      => false,
		];

		if ( ! empty( $condition ) ) {
			$args['condition'] = $condition;
		}

		$this->add_control( $key, $args );
	}

	protected function register_content_header_toolbar_controls() {
		$this->start_controls_section(
			'section_header_toolbar_settings',
			[
				'label' => esc_html__( 'Header Toolbar', 'powerpack' ),
			]
		);

		$this->add_toolbar_slot_control(
			'header_left_groups',
			esc_html__( 'Header Left', 'powerpack' ),
			[ [ 'buttons' => [ 'prev', 'next' ] ] ]
		);

		$this->add_toolbar_slot_control(
			'header_center_groups',
			esc_html__( 'Header Center', 'powerpack' ),
			[ [ 'buttons' => [ 'title' ] ] ]
		);

		$this->add_toolbar_slot_control(
			'header_right_groups',
			esc_html__( 'Header Right', 'powerpack' ),
			[ [ 'buttons' => [ 'dayGridMonth', 'dayGridWeek', 'dayGridDay', 'listMonth' ] ] ]
		);

		$this->end_controls_section();
	}

	protected function register_content_footer_toolbar_controls() {
		$this->start_controls_section(
			'section_footer_toolbar_settings',
			[
				'label' => esc_html__( 'Footer Toolbar', 'powerpack' ),
			]
		);

		$this->add_control(
			'show_footer_toolbar',
			[
				'label'              => esc_html__( 'Show Footer Toolbar', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'default'            => '',
				'label_on'           => esc_html__( 'Yes', 'powerpack' ),
				'label_off'          => esc_html__( 'No', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$footer_condition = [ 'show_footer_toolbar' => 'yes' ];

		$this->add_toolbar_slot_control(
			'footer_left_groups',
			esc_html__( 'Footer Left', 'powerpack' ),
			[],
			$footer_condition
		);

		$this->add_toolbar_slot_control(
			'footer_center_groups',
			esc_html__( 'Footer Center', 'powerpack' ),
			[],
			$footer_condition
		);

		$this->add_toolbar_slot_control(
			'footer_right_groups',
			esc_html__( 'Footer Right', 'powerpack' ),
			[],
			$footer_condition
		);

		$this->end_controls_section();
	}

	protected function register_content_event_click_controls() {
		$this->start_controls_section(
			'section_event_click',
			[
				'label' => esc_html__( 'Event Click', 'powerpack' ),
			]
		);

		$this->add_control(
			'event_click_action',
			[
				'label'              => esc_html__( 'On Event Click', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => 'popup',
				'options'            => [
					'popup' => esc_html__( 'Open Popup', 'powerpack' ),
					'link'  => esc_html__( 'Open Link', 'powerpack' ),
					'none'  => esc_html__( 'Do Nothing', 'powerpack' ),
				],
				'description'        => esc_html__( 'Choose what happens when a visitor clicks an event. "Open Link" uses each event\'s "Event Link" field.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'event_popup_layout',
			[
				'label'     => esc_html__( 'Popup Layout', 'powerpack' ),
				'type'      => Controls_Manager::SELECT,
				'default'   => 'layout-1',
				'options'   => [
					'layout-1' => esc_html__( 'Layout 1', 'powerpack' ),
					'layout-2' => esc_html__( 'Layout 2', 'powerpack' ),
					'layout-3' => esc_html__( 'Layout 3', 'powerpack' ),
				],
				'condition' => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_control(
			'event_popup_header_fields_heading',
			[
				'label'     => esc_html__( 'Popup Header Fields', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => [
					'event_click_action' => 'popup',
				],
			]
		);

		$repeater_popup = new Repeater();

		$repeater_popup->add_control(
			'field_type',
			[
				'label'       => esc_html__( 'Field Type', 'powerpack' ),
				'type'        => Controls_Manager::SELECT,
				'default'     => 'event_time',
				'label_block' => true,
				'options'     => [
					'event_time'     => esc_html__( 'Event Time', 'powerpack' ),
					'event_speaker'  => esc_html__( 'Event Speaker', 'powerpack' ),
					'event_location' => esc_html__( 'Event Location', 'powerpack' ),
				],
			]
		);

		$repeater_popup->add_control(
			'field_title',
			[
				'label'       => esc_html__( 'Field Title', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [
					'active' => true,
				],
			]
		);

		$repeater_popup->add_control(
			'field_allday_text',
			[
				'label'       => esc_html__( 'All Day Text', 'powerpack' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'dynamic'     => [
					'active' => true,
				],
				'condition'   => [
					'field_type' => 'event_time',
				],
			]
		);

		$repeater_popup->add_control(
			'field_icon',
			[
				'label'       => esc_html__( 'Field Icon', 'powerpack' ),
				'type'        => Controls_Manager::ICONS,
				'label_block' => false,
				'skin'        => 'inline',
			]
		);

		$this->add_control(
			'popup_header_fields',
			[
				'label'              => '',
				'type'               => Controls_Manager::REPEATER,
				'default'               => [
					[
						'field_type'  => 'event_time',
						'field_title' => esc_html__( 'Event Time', 'powerpack' ),
						'field_icon'  => [
							'value'   => 'fas fa-clock',
							'library' => 'fa-solid',
						]
					],
					[
						'field_type'  => 'event_speaker',
						'field_title' => esc_html__( 'Speaker', 'powerpack' ),
						'field_icon'  => [
							'value'   => 'fas fa-user',
							'library' => 'fa-solid',
						]
					],
					[
						'field_type'  => 'event_location',
						'field_title' => esc_html__( 'Location', 'powerpack' ),
						'field_icon'  => [
							'value'   => 'fas fa-map-marker-alt',
							'library' => 'fa-solid',
						]
					],
				],
				'fields'             => $repeater_popup->get_controls(),
				'title_field'        => sprintf(
					'{{{ "event_time" === field_type ? "%1$s" : ( "event_speaker" === field_type ? "%2$s" : ( "event_location" === field_type ? "%3$s" : field_type ) ) }}}',
					esc_js( esc_html__( 'Event Time', 'powerpack' ) ),
					esc_js( esc_html__( 'Event Speaker', 'powerpack' ) ),
					esc_js( esc_html__( 'Event Location', 'powerpack' ) )
				),
				'frontend_available' => true,
				'condition'          => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_control(
			'allday_text',
			[
				'label'              => esc_html__( 'All Day Text', 'powerpack' ),
				'label_block'        => false,
				'type'               => Controls_Manager::TEXT,
				'default'            => esc_html__( 'All Day', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_control(
			'popup_read_more_heading',
			[
				'label'     => esc_html__( 'Read More', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_control(
			'show_read_more',
			[
				'label'        => esc_html__( 'Show Read More', 'powerpack' ),
				'label_block'  => false,
				'type'         => Controls_Manager::SWITCHER,
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_control(
			'read_more_text',
			[
				'label'       => esc_html__( 'Read More Text', 'powerpack' ),
				'label_block' => false,
				'type'        => Controls_Manager::TEXT,
				'default'     => esc_html__( 'Read More', 'powerpack' ),
				'condition'   => [
					'event_click_action' => 'popup',
					'show_read_more'     => 'yes',
				],
			]
		);

		$this->add_control(
			'event_popup_close_popup_heading',
			[
				'label'     => esc_html__( 'Popup Close Icon', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_control(
			'popup_close_icon',
			[
				'label'       => esc_html__( 'Close Icon', 'powerpack' ),
				'type'        => Controls_Manager::ICONS,
				'label_block' => false,
				'default'     => [
					'value'   => 'fa fa-times',
					'library' => 'fa-solid',
				],
				'skin'        => 'inline',
				'condition'   => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->end_controls_section();
	}

	protected function register_content_navigation_controls() {
		$this->start_controls_section(
			'section_calendar_navigation',
			[
				'label' => esc_html__( 'Navigation', 'powerpack' ),
			]
		);

		$this->add_control(
			'nav_links',
			[
				'label'              => esc_html__( 'Navigation Links', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Yes', 'powerpack' ),
				'label_off'          => esc_html__( 'No', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => 'yes',
				'description'        => esc_html__( 'Determines if day names and week names are clickable.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'nav_button_style',
			[
				'label'              => esc_html__( 'Prev/Next Button Style', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => 'arrows',
				'options'            => [
					'arrows' => esc_html__( 'Arrows', 'powerpack' ),
					'text'   => esc_html__( 'Text', 'powerpack' ),
				],
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'prev_button_text',
			[
				'label'              => esc_html__( 'Previous Button Text', 'powerpack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => esc_html__( 'Prev', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'nav_button_style' => 'text',
				],
			]
		);

		$this->add_control(
			'next_button_text',
			[
				'label'              => esc_html__( 'Next Button Text', 'powerpack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => esc_html__( 'Next', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'nav_button_style' => 'text',
				],
			]
		);

		$this->add_control(
			'prev_year_button_text',
			[
				'label'              => esc_html__( 'Previous Year Button Text', 'powerpack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => esc_html__( 'Prev Year', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'nav_button_style' => 'text',
				],
			]
		);

		$this->add_control(
			'next_year_button_text',
			[
				'label'              => esc_html__( 'Next Year Button Text', 'powerpack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => esc_html__( 'Next Year', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'nav_button_style' => 'text',
				],
			]
		);

		$this->end_controls_section();
	}

	protected function register_content_settings_controls() {
		$this->start_controls_section(
			'section_calendar_settings',
			[
				'label' => esc_html__( 'Settings', 'powerpack' ),
			]
		);

		$this->add_control(
			'initial_view',
			[
				'label'              => esc_html__( 'Default View', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => 'dayGridMonth',
				'options'            => [
					'timeGridDay'  => esc_html__( 'Time Grid - Day', 'powerpack' ),
					'timeGridWeek' => esc_html__( 'Time Grid - Week', 'powerpack' ),
					'dayGridDay'   => esc_html__( 'Day Grid - Day', 'powerpack' ),
					'dayGridWeek'  => esc_html__( 'Day Grid - Week', 'powerpack' ),
					'dayGridMonth' => esc_html__( 'Day Grid - Month', 'powerpack' ),
					'dayGridYear'  => esc_html__( 'Day Grid - Year', 'powerpack' ),
					'listDay'      => esc_html__( 'List - Day', 'powerpack' ),
					'listWeek'     => esc_html__( 'List - Week', 'powerpack' ),
					'listMonth'    => esc_html__( 'List - Month', 'powerpack' ),
					'listYear'     => esc_html__( 'List - Year', 'powerpack' ),
				],
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'first_day',
			[
				'label'              => esc_html__( 'First Day of Week', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => '1',
				'options'            => [
					'0' => esc_html__( 'Sunday', 'powerpack' ),
					'1' => esc_html__( 'Monday', 'powerpack' ),
					'2' => esc_html__( 'Tuesday', 'powerpack' ),
					'3' => esc_html__( 'Wednesday', 'powerpack' ),
					'4' => esc_html__( 'Thursday', 'powerpack' ),
					'5' => esc_html__( 'Friday', 'powerpack' ),
					'6' => esc_html__( 'Saturday', 'powerpack' ),
				],
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'default_current_month',
			[
				'label'              => esc_html__( 'Default to Current Month', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'default'            => 'yes',
				'label_on'           => esc_html__( 'Yes', 'powerpack' ),
				'label_off'          => esc_html__( 'No', 'powerpack' ),
				'return_value'       => 'yes',
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'default_month',
			[
				'label'              => esc_html__( 'Default Month', 'powerpack' ),
				'type'               => Controls_Manager::DATE_TIME,
				'label_block'        => false,
				'picker_options'     => [
					'enableTime' => false,
					'dateFormat' => 'Y-m',
				],
				'default'            => gmdate( 'Y-m-d' ),
				'frontend_available' => true,
				'condition'          => [
					'default_current_month' => '',
				],
			]
		);

		$this->add_control(
			'localization_heading',
			[
				'label'     => esc_html__( 'Localization', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'timezone',
			[
				'label'              => esc_html__( 'Timezone', 'powerpack' ),
				'type'               => Controls_Manager::SELECT2,
				'options'            => PP_Helper::get_timezones(),
				'default'            => ( '' !== get_option( 'timezone_string' ) ) ? get_option( 'timezone_string' ) : 'UTC',
				'label_block'        => true,
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'display_heading',
			[
				'label'     => esc_html__( 'Display', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'calendar_height_type',
			[
				'label'              => esc_html__( 'Height', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => 'auto',
				'options'            => [
					'auto'        => esc_html__( 'Auto', 'powerpack' ),
					'fixed'       => esc_html__( 'Fixed', 'powerpack' ),
					'aspectRatio' => esc_html__( 'Aspect Ratio', 'powerpack' ),
				],
				'description'        => esc_html__( 'Auto expands to fit all content. Fixed sets a pixel height. Aspect Ratio sizes the height relative to the calendar width.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'calendar_height',
			[
				'label'              => esc_html__( 'Custom Height', 'powerpack' ),
				'type'               => Controls_Manager::SLIDER,
				'size_units'         => [ 'px', 'vh' ],
				'range'              => [
					'px' => [
						'min'  => 300,
						'max'  => 2000,
						'step' => 10,
					],
					'vh' => [
						'min'  => 20,
						'max'  => 100,
						'step' => 1,
					],
				],
				'default'            => [
					'size' => 600,
					'unit' => 'px',
				],
				'frontend_available' => true,
				'condition'          => [
					'calendar_height_type' => 'fixed',
				],
			]
		);

		$this->add_control(
			'calendar_aspect_ratio',
			[
				'label'              => esc_html__( 'Aspect Ratio', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => '4:3',
				'options'            => [
					'1:1'  => '1:1',
					'3:2'  => '3:2',
					'4:3'  => '4:3',
					'9:16' => '9:16',
					'16:9' => '16:9',
					'21:9' => '21:9',
				],
				'description'        => esc_html__( 'The calendar height scales with its width to keep this ratio.', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'calendar_height_type' => 'aspectRatio',
				],
			]
		);

		$this->add_control(
			'show_weekends',
			[
				'label'              => esc_html__( 'Weekends', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Show', 'powerpack' ),
				'label_off'          => esc_html__( 'Hide', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => 'yes',
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'hidden_days',
			[
				'label'              => esc_html__( 'Hide Days', 'powerpack' ),
				'type'               => Controls_Manager::SELECT2,
				'multiple'           => true,
				'label_block'        => true,
				'options'            => [
					'0' => esc_html__( 'Sunday', 'powerpack' ),
					'1' => esc_html__( 'Monday', 'powerpack' ),
					'2' => esc_html__( 'Tuesday', 'powerpack' ),
					'3' => esc_html__( 'Wednesday', 'powerpack' ),
					'4' => esc_html__( 'Thursday', 'powerpack' ),
					'5' => esc_html__( 'Friday', 'powerpack' ),
					'6' => esc_html__( 'Saturday', 'powerpack' ),
				],
				'description'        => esc_html__( 'Days selected here are hidden from every view.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'show_week_numbers',
			[
				'label'              => esc_html__( 'Week Numbers', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Yes', 'powerpack' ),
				'label_off'          => esc_html__( 'No', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => '',
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'events_heading',
			[
				'label'     => esc_html__( 'Events', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'event_display',
			[
				'label'              => esc_html__( 'Event Display', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => 'auto',
				'options'            => [
					'auto'      => esc_html__( 'Auto', 'powerpack' ),
					'block'     => esc_html__( 'Block', 'powerpack' ),
					'list-item' => esc_html__( 'Dot', 'powerpack' ),
				],
				'description'        => esc_html__( 'How events appear in month and day-grid views. Auto shows blocks for all-day events and dots for timed events.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'display_event_time',
			[
				'label'              => esc_html__( 'Event Time', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Show', 'powerpack' ),
				'label_off'          => esc_html__( 'Hide', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => 'yes',
				'description'        => esc_html__( 'Show or hide the time text on events.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'display_event_end',
			[
				'label'              => esc_html__( 'Event End Time', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Show', 'powerpack' ),
				'label_off'          => esc_html__( 'Hide', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => 'yes',
				'description'        => esc_html__( 'Show or hide an event\'s end time alongside its start time.', 'powerpack' ),
				'frontend_available' => true,
				'condition'          => [
					'display_event_time' => 'yes',
				],
			]
		);

		$time_slots = [];
		for ( $m = 0; $m <= 1440; $m += 30 ) {
			$time_slots[ sprintf( '%02d:%02d:00', intdiv( $m, 60 ), $m % 60 ) ] = sprintf( '%02d:%02d', intdiv( $m, 60 ), $m % 60 );
		}

		$this->add_control(
			'time_grid_heading',
			[
				'label'       => esc_html__( 'Time Grid Views', 'powerpack' ),
				'type'        => Controls_Manager::HEADING,
				'separator'   => 'before',
				'description' => esc_html__( 'Applies to the Day and Week time-grid views.', 'powerpack' ),
			]
		);

		$this->add_control(
			'slot_min_time',
			[
				'label'              => esc_html__( 'Start Time', 'powerpack' ),
				'type'               => Controls_Manager::SELECT2,
				'default'            => '00:00:00',
				'options'            => array_slice( $time_slots, 0, 48, true ),
				'description'        => esc_html__( 'Earliest time slot shown on the time grid.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'slot_max_time',
			[
				'label'              => esc_html__( 'End Time', 'powerpack' ),
				'type'               => Controls_Manager::SELECT2,
				'default'            => '24:00:00',
				'options'            => array_slice( $time_slots, 1, 48, true ),
				'description'        => esc_html__( 'Latest time slot shown on the time grid.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'scroll_time',
			[
				'label'              => esc_html__( 'Initial Scroll Time', 'powerpack' ),
				'type'               => Controls_Manager::SELECT2,
				'default'            => '06:00:00',
				'options'            => array_slice( $time_slots, 0, 48, true ),
				'description'        => esc_html__( 'Time the grid is scrolled to when first displayed.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'slot_duration',
			[
				'label'              => esc_html__( 'Slot Duration', 'powerpack' ),
				'type'               => Controls_Manager::SELECT,
				'default'            => '00:30:00',
				'options'            => [
					'00:15:00' => esc_html__( '15 minutes', 'powerpack' ),
					'00:30:00' => esc_html__( '30 minutes', 'powerpack' ),
					'01:00:00' => esc_html__( '1 hour', 'powerpack' ),
				],
				'description'        => esc_html__( 'Length of each time slot.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'all_day_slot',
			[
				'label'              => esc_html__( 'All-Day Slot', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Show', 'powerpack' ),
				'label_off'          => esc_html__( 'Hide', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => 'yes',
				'description'        => esc_html__( 'Show or hide the all-day row at the top of the time grid.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'now_indicator',
			[
				'label'              => esc_html__( 'Current Time Indicator', 'powerpack' ),
				'type'               => Controls_Manager::SWITCHER,
				'label_on'           => esc_html__( 'Show', 'powerpack' ),
				'label_off'          => esc_html__( 'Hide', 'powerpack' ),
				'return_value'       => 'yes',
				'default'            => 'yes',
				'description'        => esc_html__( 'Shows a marker indicating the current time on the time grid.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->add_control(
			'list_grid_heading',
			[
				'label'       => esc_html__( 'List Views', 'powerpack' ),
				'type'        => Controls_Manager::HEADING,
				'separator'   => 'before',
				'description' => esc_html__( 'Applies to the Day, Week, Month, and Year list views.', 'powerpack' ),
			]
		);

		$this->add_control(
			'no_events_text',
			[
				'label'              => esc_html__( 'No Events Text', 'powerpack' ),
				'type'               => Controls_Manager::TEXT,
				'default'            => esc_html__( 'No events to display', 'powerpack' ),
				'label_block'        => true,
				'description'        => esc_html__( 'Text shown in list views when there are no events.', 'powerpack' ),
				'frontend_available' => true,
			]
		);

		$this->end_controls_section();
	}

	protected function register_style_calendar_controls() {
		$this->start_controls_section(
			'section_calendar_style',
			[
				'label' => esc_html__( 'Calendar', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'calendar_bg_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-view-harness' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name'        => 'calendar_border',
				'label'       => esc_html__( 'Border', 'powerpack' ),
				'placeholder' => '1px',
				'default'     => '1px',
				'selector'    => '{{WRAPPER}} .pp-event-calendar-container .fc-view-harness th, {{WRAPPER}} .pp-event-calendar-container .fc-view-harness td',
			]
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			[
				'name'     => 'calendar_box_shadow',
				'label'    => esc_html__( 'Box Shadow', 'powerpack' ),
				'selector' => '{{WRAPPER}} .pp-event-calendar-container .fc-view-harness',
			]
		);

		$this->end_controls_section();
	}

	protected function register_style_toolbar_controls() {
		$this->start_controls_section(
			'section_toolbar_style',
			[
				'label' => esc_html__( 'Toolbar', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_responsive_control(
			'toolbar_spacing',
			[
				'label'       => esc_html__( 'Toolbar Spacing', 'powerpack' ),
				'type'        => Controls_Manager::SLIDER,
				'size_units'  => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
				'range'       => [
					'px' => [
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					],
				],
				'description' => esc_html__( 'Gap between the calendar and the header/footer toolbars.', 'powerpack' ),
				'selectors'   => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-header-toolbar' => 'margin-bottom: {{SIZE}}{{UNIT}};',
					'{{WRAPPER}} .pp-event-calendar-container .fc-footer-toolbar' => 'margin-top: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'toolbar_title_heading',
			[
				'label'     => esc_html__( 'Title', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'calendar_title_color',
			[
				'label'     => esc_html__( 'Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-toolbar-title' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'calendar_title_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'global'   => [
					'default' => Global_Typography::TYPOGRAPHY_ACCENT,
				],
				'selector' => '{{WRAPPER}} .pp-event-calendar-container .fc-toolbar-title',
			]
		);

		$this->add_control(
			'buttons_heading',
			[
				'label'     => esc_html__( 'Buttons', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'button_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'selector' => '{{WRAPPER}} .pp-event-calendar-container .fc-button',
			]
		);

		$this->start_controls_tabs( 'tabs_button_style' );

		$this->start_controls_tab(
			'tab_button_normal',
			[
				'label' => esc_html__( 'Normal', 'powerpack' ),
			]
		);

		$this->add_control(
			'button_text_color_normal',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button' => 'color: {{VALUE}}',
					'{{WRAPPER}} .pp-event-calendar-container .fc-button svg' => 'fill: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'button_bg_color_normal',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'global'    => [
					'default' => Global_Colors::COLOR_ACCENT,
				],
				'default'   => '#ffffff',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name'        => 'button_border_normal',
				'label'       => esc_html__( 'Border', 'powerpack' ),
				'placeholder' => '1px',
				'default'     => '1px',
				'selector'    => '{{WRAPPER}} .pp-event-calendar-container .fc-button',
			]
		);

		$this->add_control(
			'button_border_radius',
			[
				'label'      => esc_html__( 'Border Radius', 'powerpack' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => [ 'px', '%' ],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			[
				'name'     => 'button_box_shadow',
				'selector' => '{{WRAPPER}} .pp-event-calendar-container .fc-button',
			]
		);

		$this->add_responsive_control(
			'button_padding',
			[
				'label'      => esc_html__( 'Padding', 'powerpack' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => [ 'px', 'em', '%' ],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->end_controls_tab();

		$this->start_controls_tab(
			'tab_button_hover',
			[
				'label'     => esc_html__( 'Hover', 'powerpack' ),
			]
		);

		$this->add_control(
			'button_text_color_hover',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button:hover, {{WRAPPER}} .pp-event-calendar-container .fc-button:focus' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'button_bg_color_hover',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '#000000',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button:hover, {{WRAPPER}} .pp-event-calendar-container .fc-button:focus' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'button_border_color_hover',
			[
				'label'     => esc_html__( 'Border Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button:hover, {{WRAPPER}} .pp-event-calendar-container .fc-button:focus' => 'border-color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			[
				'name'      => 'button_box_shadow_hover',
				'selector'  => '{{WRAPPER}} .pp-event-calendar-container .fc-button:hover, {{WRAPPER}} .pp-event-calendar-container .fc-button:focus',
			]
		);

		$this->end_controls_tab();

		$this->start_controls_tab(
			'tab_button_active',
			[
				'label'     => esc_html__( 'Active', 'powerpack' ),
			]
		);

		$this->add_control(
			'button_text_color_active',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button.fc-button-active' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'button_bg_color_active',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '#000000',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button.fc-button-active' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'button_border_color_active',
			[
				'label'     => esc_html__( 'Border Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-button.fc-button-active' => 'border-color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			[
				'name'      => 'button_box_shadow_active',
				'selector'  => '{{WRAPPER}} .pp-event-calendar-container .fc-button.fc-button-active',
			]
		);

		$this->end_controls_tab();
		$this->end_controls_tabs();

		$this->end_controls_section();
	}

	protected function register_style_header_controls() {

		$this->start_controls_section(
			'section_calendar_header_style',
			[
				'label' => esc_html__( 'Header', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_responsive_control(
			'header_text_align',
			[
				'label'       => esc_html__( 'Text Align', 'powerpack' ),
				'type'        => Controls_Manager::CHOOSE,
				'label_block' => false,
				'options'     => [
					'left'   => [
						'title' => esc_html__( 'Left', 'powerpack' ),
						'icon'  => 'eicon-text-align-left',
					],
					'center' => [
						'title' => esc_html__( 'Center', 'powerpack' ),
						'icon'  => 'eicon-text-align-center',
					],
					'right'  => [
						'title' => esc_html__( 'Right', 'powerpack' ),
						'icon'  => 'eicon-text-align-right',
					],
				],
				'default'     => 'center',
				'selectors'   => [
					'{{WRAPPER}} .fc-scrollgrid thead .fc-scrollgrid-sync-inner, {{WRAPPER}} tr.fc-list-day th'   => 'text-align: {{VALUE}};',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'calendar_header_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'global'   => [
					'default' => Global_Typography::TYPOGRAPHY_ACCENT,
				],
				'selector' => '{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell,{{WRAPPER}} tr.fc-list-day th',
			]
		);

		$this->start_controls_tabs( 'tabs_header_style' );

		$this->start_controls_tab(
			'tab_header_normal',
			[
				'label' => esc_html__( 'Normal', 'powerpack' ),
			]
		);

		$this->add_control(
			'calendar_header_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell .fc-scrollgrid-sync-inner a,{{WRAPPER}} tr.fc-list-day th a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'calendar_header_background_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '#F3F3F4',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell,{{WRAPPER}} tr.fc-list-day th' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name'        => 'calendar_header_border',
				'label'       => esc_html__( 'Border', 'powerpack' ),
				'placeholder' => '1px',
				'default'     => '1px',
				'selector'    => '{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell,{{WRAPPER}} tr.fc-list-day th',
			]
		);

		$this->add_responsive_control(
			'calendar_header_padding',
			[
				'label'      => esc_html__( 'Padding', 'powerpack' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => [ 'px', '%' ],
				'selectors'  => [
					'{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell,{{WRAPPER}} tr.fc-list-day th' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->end_controls_tab();

		$this->start_controls_tab(
			'tab_header_hover',
			[
				'label' => esc_html__( 'Hover', 'powerpack' ),
			]
		);

		$this->add_control(
			'calendar_header_text_color_hover',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell:hover .fc-scrollgrid-sync-inner a,{{WRAPPER}} tr.fc-list-day th:hover a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'calendar_header_background_color_hover',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid .fc-col-header th.fc-col-header-cell:hover,{{WRAPPER}} tr.fc-list-day th:hover' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->end_controls_tab();

		$this->end_controls_tabs();

		$this->end_controls_section();
	}

	protected function register_style_rows_controls() {
		$this->start_controls_section(
			'section_calendar_rows_style',
			[
				'label' => esc_html__( 'Rows', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'calendar_striped_rows',
			[
				'label'        => esc_html__( 'Striped Rows', 'powerpack' ),
				'type'         => Controls_Manager::SELECT,
				'default'      => 'none',
				'options'      => [
					'none' => esc_html__( 'None', 'powerpack' ),
					'even' => esc_html__( 'Even', 'powerpack' ),
					'odd'  => esc_html__( 'Odd', 'powerpack' ),
				],
				'prefix_class' => 'pp-event-calendar-rows--',
			]
		);

		$this->add_control(
			'calendar_rows_bg_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid-sync-table tbody tr td:not(.fc-day-today),{{WRAPPER}} tr.fc-list-event td' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'calendar_rows_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid-sync-table tbody tr .fc-scrollgrid-sync-inner a,{{WRAPPER}} tr.fc-list-event td' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name'        => 'calendar_rows_border',
				'label'       => esc_html__( 'Border', 'powerpack' ),
				'placeholder' => '1px',
				'default'     => '1px',
				'selector'    => '{{WRAPPER}} .fc-scrollgrid-sync-table tr,{{WRAPPER}} tr.fc-list-event',
			]
		);

		$this->add_control(
			'alternate_rows_heading',
			[
				'label'     => esc_html__( 'Alternate Rows', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => [
					'calendar_striped_rows' => [ 'even', 'odd' ],
				],
			]
		);

		$this->add_control(
			'calendar_alt_rows_bg_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}}.pp-event-calendar-rows--even .fc-scrollgrid-sync-table tbody tr:nth-child(even) td:not(.fc-day-today)' => 'background-color: {{VALUE}}',
					'{{WRAPPER}}.pp-event-calendar-rows--odd .fc-scrollgrid-sync-table tbody tr:nth-child(odd) td:not(.fc-day-today)' => 'background-color: {{VALUE}}',
				],
				'condition' => [
					'calendar_striped_rows' => [ 'even', 'odd' ],
				],
			]
		);

		$this->add_control(
			'calendar_alt_rows_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}}.pp-event-calendar-rows--even .fc-scrollgrid-sync-table tbody tr:nth-child(even) .fc-scrollgrid-sync-inner a' => 'color: {{VALUE}}',
					'{{WRAPPER}}.pp-event-calendar-rows--odd .fc-scrollgrid-sync-table tbody tr:nth-child(odd) .fc-scrollgrid-sync-inner a' => 'color: {{VALUE}}',
				],
				'condition' => [
					'calendar_striped_rows' => [ 'even', 'odd' ],
				],
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name'        => 'calendar_alt_rows_border',
				'label'       => esc_html__( 'Border', 'powerpack' ),
				'placeholder' => '1px',
				'default'     => '1px',
				'selector'    => '{{WRAPPER}}.pp-event-calendar-rows--even .fc-scrollgrid-sync-table tr:nth-child(even), {{WRAPPER}}.pp-event-calendar-rows--odd .fc-scrollgrid-sync-table tr:nth-child(odd)',
				'condition'   => [
					'calendar_striped_rows' => [ 'even', 'odd' ],
				],
			]
		);

		$this->end_controls_section();
	}

	protected function register_style_days_controls() {
		$this->start_controls_section(
			'section_days_style',
			[
				'label' => esc_html__( 'Days', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'days_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'global'   => [
					'default' => Global_Typography::TYPOGRAPHY_TEXT,
				],
				'selector' => '{{WRAPPER}} .fc-scrollgrid-sync-table td .fc-scrollgrid-sync-inner',
			]
		);

		$this->add_control(
			'all_days_heading',
			[
				'label'     => esc_html__( 'All Days', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->start_controls_tabs( 'tabs_days_style' );

		$this->start_controls_tab(
			'tab_days_normal',
			[
				'label' => esc_html__( 'Normal', 'powerpack' ),
			]
		);

		$this->add_control(
			'days_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'global'    => [
					'default' => Global_Colors::COLOR_TEXT,
				],
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid-sync-table td .fc-scrollgrid-sync-inner a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'days_background_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid-sync-table td:not(.fc-day-today)' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->end_controls_tab();

		$this->start_controls_tab(
			'tab_cell_hover',
			[
				'label' => esc_html__( 'Hover', 'powerpack' ),
			]
		);

		$this->add_control(
			'days_text_color_hover',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid-sync-table td:hover .fc-scrollgrid-sync-inner a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'days_background_color_hover',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .fc-scrollgrid-sync-table td:hover:not(.fc-day-today)' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->end_controls_tab();

		$this->end_controls_tabs();

		$this->add_control(
			'calendar_today_heading',
			[
				'label'     => esc_html__( 'Today', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'today_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-scrollgrid td.fc-day-today a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'today_background_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '#F3F3F4',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-scrollgrid td.fc-day-today' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'past_day_heading',
			[
				'label'     => esc_html__( 'Past Day', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'past_day_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-scrollgrid td.fc-day-past a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'past_day_background_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-scrollgrid td.fc-day-past' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'adjacent_days_heading',
			[
				'label'     => esc_html__( 'Adjacent Days', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'adjacent_day_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-scrollgrid td.fc-day-other a' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'adjacent_day_background_color',
			[
				'label'     => esc_html__( 'Background Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-scrollgrid td.fc-day-other' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->end_controls_section();
	}

	protected function register_style_event_controls() {
		$this->start_controls_section(
			'section_event_style',
			[
				'label' => esc_html__( 'Event', 'powerpack' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'event_color',
			[
				'label'              => esc_html__( 'Event Color', 'powerpack' ),
				'type'               => Controls_Manager::COLOR,
				'default'            => '#3788d8',
				'frontend_available' => true,
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'event_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'global'   => [
					'default' => Global_Typography::TYPOGRAPHY_ACCENT,
				],
				'selector' => '{{WRAPPER}} .fc-daygrid-event',
			]
		);

		$this->start_controls_tabs( 'tabs_event_style' );

		$this->start_controls_tab(
			'tab_event_normal',
			[
				'label' => esc_html__( 'Normal', 'powerpack' ),
			]
		);

		$this->add_control(
			'event_text_color_normal',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container' => '--fc-event-text-color: {{VALUE}};',
				],
			]
		);

		$this->add_responsive_control(
			'event_padding',
			[
				'label'      => esc_html__( 'Padding', 'powerpack' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => [ 'px', 'em', '%' ],
				'selectors'  => [
					'{{WRAPPER}} .fc-daygrid-event' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->end_controls_tab();

		$this->start_controls_tab(
			'tab_event_hover',
			[
				'label' => esc_html__( 'Hover', 'powerpack' ),
			]
		);

		$this->add_control(
			'event_text_color_hover',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-container .fc-event:hover' => '--fc-event-text-color: {{VALUE}};',
				],
			]
		);

		$this->end_controls_tab();
		$this->end_controls_tabs();

		$this->end_controls_section();
	}

	protected function register_popup_style_controls() {

		$this->start_controls_section(
			'section_style_event_popup',
			[
				'label'     => esc_html__( 'Event Popup', 'powerpack' ),
				'tab'       => Controls_Manager::TAB_STYLE,
				'condition' => [
					'event_click_action' => 'popup',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_width',
			[
				'label'      => esc_html__( 'Popup Width', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 1200,
						'step' => 1,
					],
					'%'  => [
						'min' => 0,
						'max' => 100,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup' => 'width: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_padding',
			[
				'label'      => esc_html__( 'Content Padding', 'powerpack' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => ['px', '%'],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'event_popup_overlay_background',
			[
				'label'     => esc_html__( 'Overlay Background', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper.pp-event-calendar-popup-ready:before' => 'background: {{VALUE}}',
				],
				'separator' => 'before',
			]
		);

		$this->add_control(
			'event_popup_background',
			[
				'label'     => esc_html__( 'Popup Background', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup' => 'background-color: {{VALUE}}',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_border_radius',
			[
				'label'      => esc_html__( 'Border Radius', 'powerpack' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => ['px', '%'],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			[
				'name'     => 'event_popup_border',
				'label'    => esc_html__( 'Border', 'powerpack' ),
				'selector' => '{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup',
			]
		);

		$this->add_control(
			'event_popup_image_heading',
			[
				'label'     => esc_html__( 'Image', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'event_popup_image_height',
			[
				'label'      => esc_html__( 'Height', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%', 'custom' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 500,
						'step' => 1,
					],
					'%'  => [
						'min' => 0,
						'max' => 100,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper' => '--pp-event-calendar-popup-image-height: {{SIZE}}{{UNIT}};',
				],
				'condition'  => [
					'event_popup_layout!' => 'layout-3',
				],
			]
		);

		$this->add_control(
			'event_popup_image_width',
			[
				'label'      => esc_html__( 'Width', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%', 'custom' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 500,
						'step' => 1,
					],
					'%'  => [
						'min' => 0,
						'max' => 100,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper' => '--pp-event-calendar-popup-image-width: {{SIZE}}{{UNIT}};',
				],
				'condition'  => [
					'event_popup_layout' => 'layout-3',
				],
			]
		);

		$this->add_control(
			'event_popup_title_heading',
			[
				'label'     => esc_html__( 'Title', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'event_popup_title_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'exclude'  => [
					'font_family',
				],
				'selector' => '{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content h3',
			]
		);

		$this->add_control(
			'event_popup_title_color',
			[
				'label'     => esc_html__( 'Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content h3' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_title_margin_bottom',
			[
				'label'      => esc_html__( 'Margin Bottom', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content h3' => 'margin-bottom: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'event_popup_desc_heading',
			[
				'label'     => esc_html__( 'Description', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'event_popup_desc_typography',
				'label'    => esc_html__( 'Typography', 'powerpack' ),
				'exclude'  => [
					'font_family',
				],
				'selector' => '{{WRAPPER}} .pp-event-calendar-popup-wrapper p.pp-event-calendar-popup-desc',
			]
		);

		$this->add_control(
			'event_popup_desc_color',
			[
				'label'     => esc_html__( 'Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper p.pp-event-calendar-popup-desc' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'event_popup_details_heading',
			[
				'label'     => esc_html__( 'Event Details', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'     => 'event_popup_details_text_typography',
				'label'    => esc_html__( 'Text Typography', 'powerpack' ),
				'exclude'  => [
					'font_family',
				],
				'selector' => '{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content .pp-event-calendar-event-detail',
			]
		);

		$this->add_control(
			'event_popup_details_text_color',
			[
				'label'     => esc_html__( 'Text Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content .pp-event-calendar-event-detail' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'event_popup_details_icon_color',
			[
				'label'     => esc_html__( 'Icon Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content .pp-event-calendar-popup-field-icon' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_details_icon_size',
			[
				'label'      => esc_html__( 'Icon Size', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 200,
						'step' => 1,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content .pp-event-calendar-popup-field-icon' => 'font-size: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_details_items_gap',
			[
				'label'      => esc_html__( 'Items Gap', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', 'em', '%' ],
				'default'    => [
					'size' => 15,
					'unit' => 'px',
				],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-content ul' => 'gap: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'event_popup_readmore_heading',
			[
				'label'     => esc_html__( 'Read More', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => [
					'event_click_action' => 'popup',
					'show_read_more'     => 'yes',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			[
				'name'      => 'event_popup_readmore_typography',
				'label'     => esc_html__( 'Typography', 'powerpack' ),
				'selector'  => '{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-readmore-link',
				'condition' => [
					'event_click_action' => 'popup',
					'show_read_more'     => 'yes',
				],
			]
		);

		$this->add_control(
			'event_popup_readmore_color',
			[
				'label'     => esc_html__( 'Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper a.pp-event-calendar-popup-readmore-link' => 'color: {{VALUE}}',
				],
				'condition' => [
					'event_click_action' => 'popup',
					'show_read_more'     => 'yes',
				],
			]
		);

		$this->add_responsive_control(
			'event_popup_readmore_spacing',
			[
				'label'      => esc_html__( 'Margin Top', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-readmore-link' => 'margin-top: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'event_popup_close_button_heading',
			[
				'label'     => esc_html__( 'Close Button', 'powerpack' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_responsive_control(
			'event_popup_close_button_font_size',
			[
				'label'      => esc_html__( 'Icon Size', 'powerpack' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px', '%' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 200,
						'step' => 1,
					],
				],
				'selectors'  => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-close' => 'font-size: {{SIZE}}{{UNIT}};',
				],
			]
		);

		$this->add_control(
			'event_popup_close_button_color',
			[
				'label'     => esc_html__( 'Color', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-close' => 'color: {{VALUE}}',
				],
			]
		);

		$this->add_control(
			'event_popup_close_button_background',
			[
				'label'     => esc_html__( 'Background', 'powerpack' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-close' => 'background: {{VALUE}}',
				],
			]
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			[
				'name'     => 'event_popup_close_button_box_shadow',
				'label'    => esc_html__( 'Box Shadow', 'powerpack' ),
				'selector' => '{{WRAPPER}} .pp-event-calendar-popup-wrapper .pp-event-calendar-popup-close',
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Get post query arguments.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @return array WP_Query arguments.
	 */
	protected function get_posts_query_arguments() {
		$settings = $this->get_settings();
		if ( 'yes' === $settings['set_post_limit'] ) {
			$posts_count = ! empty( $settings['posts_per_page'] ) ? absint( $settings['posts_per_page'] ) : 10;
		} else {
			$posts_count = -1;
		}

		// Query Arguments.
		// The calendar is never paginated, so skip the found-rows count and the
		// term cache. Post meta IS primed because the result loop maps event
		// fields (start/end/location/etc.) to post meta or ACF fields.
		$query_args = [
			'post_status'            => [ 'publish' ],
			'post_type'              => $settings['post_type'],
			'orderby'                => $settings['orderby'],
			'order'                  => $settings['order'],
			'offset'                 => absint( $settings['offset'] ),
			'posts_per_page'         => $posts_count,
			'no_found_rows'          => true,
			'update_post_meta_cache' => true,
			'update_post_term_cache' => false,
			'ignore_sticky_posts'    => true,
		];

		// Author Filter
		if ( ! empty( $settings['authors'] ) ) {
			$query_args[ $settings['author_filter_type'] ] = $settings['authors'];
		}

		// Posts Filter
		$post_type = $settings['post_type'];

		if ( 'post' === $post_type ) {
			$posts_control_key = 'exclude_posts';
		} else {
			$posts_control_key = $post_type . '_filter';
		}

		if ( ! empty( $settings[ $posts_control_key ] ) ) {
			$query_args[ $settings[ $post_type . '_filter_type' ] ] = $settings[ $posts_control_key ];
		}

		// Taxonomy Filter
		$taxonomy = PP_Posts_Helper::get_post_taxonomies( $post_type );

		if ( ! empty( $taxonomy ) && ! is_wp_error( $taxonomy ) ) {

			foreach ( $taxonomy as $index => $tax ) {

				if ( 'post' === $post_type ) {
					if ( 'post_tag' === $index ) {
						$tax_control_key = 'tags';
					} elseif ( 'category' === $index ) {
						$tax_control_key = 'categories';
					} else {
						$tax_control_key = $index . '_' . $post_type;
					}
				} else {
					$tax_control_key = $index . '_' . $post_type;
				}

				if ( ! empty( $settings[ $tax_control_key ] ) ) {

					$operator = $settings[ $index . '_' . $post_type . '_filter_type' ];

					$query_args['tax_query'][] = [
						'taxonomy' => $index,
						'field'    => 'term_id',
						'terms'    => $settings[ $tax_control_key ],
						'operator' => $operator,
					];
				}
			}
		}

		if ( 'anytime' !== $settings['select_date'] ) {
			$select_date = $settings['select_date'];
			if ( ! empty( $select_date ) ) {
				$date_query = [];
				if ( 'today' === $select_date ) {
					$date_query['after'] = '-1 day';
				} elseif ( 'week' === $select_date ) {
					$date_query['after'] = '-1 week';
				} elseif ( 'month' === $select_date ) {
					$date_query['after'] = '-1 month';
				} elseif ( 'quarter' === $select_date ) {
					$date_query['after'] = '-3 month';
				} elseif ( 'year' === $select_date ) {
					$date_query['after'] = '-1 year';
				} elseif ( 'exact' === $select_date ) {
					$after_date = $settings['date_after'];
					if ( ! empty( $after_date ) ) {
						$date_query['after'] = $after_date;
					}
					$before_date = $settings['date_before'];
					if ( ! empty( $before_date ) ) {
						$date_query['before'] = $before_date;
					}
					$date_query['inclusive'] = true;
				}

				$query_args['date_query'] = $date_query;
			}
		}

		// Exclude current post.
		if ( 'yes' === $settings['exclude_current'] ) {
			if ( is_singular() ) {
				$query_args['post__not_in'] = [ get_queried_object_id() ];
			}
		}

		/**
		 * Filters the WP_Query arguments used by the Event Calendar widget posts source.
		 *
		 * @since 3.0.0
		 * @param array $query_args The WP_Query arguments.
		 * @param array $settings   The widget settings.
		 */
		return apply_filters( 'ppe_calendar_query_args', $query_args, $settings );
	}

	/**
	 * Resolve a mapped event value for the current post in the posts loop.
	 *
	 * Reads either a post-meta key or an ACF field, depending on the
	 * "Read Fields From" setting.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @param array  $settings Widget settings.
	 * @param int    $post_id  Current post ID.
	 * @param string $field    Logical field name: start|end|location|speaker|description|image|all_day.
	 * @return string The resolved value, or '' when not configured/empty.
	 */
	protected function get_posts_mapped_value( $settings, $post_id, $field ) {
		$source = ! empty( $settings['posts_field_source'] ) ? $settings['posts_field_source'] : 'meta';

		if ( 'acf' === $source ) {
			$acf_key = ! empty( $settings[ 'posts_' . $field . '_acf_field' ] ) ? $settings[ 'posts_' . $field . '_acf_field' ] : '';
			if ( '' === $acf_key || ! function_exists( 'get_field_object' ) ) {
				return '';
			}
			return $this->get_posts_acf_value( $acf_key, $post_id, $field );
		}

		$meta_key = ! empty( $settings[ 'posts_' . $field . '_meta_key' ] ) ? $settings[ 'posts_' . $field . '_meta_key' ] : '';
		if ( '' === $meta_key ) {
			return '';
		}

		$value = get_post_meta( $post_id, $meta_key, true );

		return is_array( $value ) ? '' : (string) $value;
	}

	/**
	 * Resolve an ACF field value for a specific post.
	 *
	 * Date fields use the raw stored value (Ymd / Y-m-d H:i:s) so the date can
	 * be parsed reliably regardless of the field's display return format.
	 * Image fields are reduced to an attachment ID or URL.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @param string $acf_key ACF field key.
	 * @param int    $post_id Post ID.
	 * @param string $field   Logical field name.
	 * @return string
	 */
	protected function get_posts_acf_value( $acf_key, $post_id, $field ) {
		$object = get_field_object( $acf_key, $post_id, false );

		if ( empty( $object ) || ! is_array( $object ) ) {
			return '';
		}

		$type = ! empty( $object['type'] ) ? $object['type'] : '';
		$name = ! empty( $object['name'] ) ? $object['name'] : '';

		if ( in_array( $type, [ 'date_picker', 'date_time_picker' ], true ) && $name && function_exists( 'acf_get_metadata' ) ) {
			$raw = acf_get_metadata( $post_id, $name );
			if ( '' !== $raw && null !== $raw ) {
				return (string) $raw;
			}
		}

		$value = get_field( $acf_key, $post_id, false );

		if ( is_array( $value ) ) {
			if ( ! empty( $value['url'] ) ) {
				return $value['url'];
			}
			if ( ! empty( $value['ID'] ) ) {
				return (string) $value['ID'];
			}
			return '';
		}

		return (string) $value;
	}

	/**
	 * Whether a mapped date value carries a time component.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @param string $raw Raw date value.
	 * @return bool
	 */
	protected function posts_value_has_time( $raw ) {
		$raw = trim( (string) $raw );

		if ( '' === $raw ) {
			return false;
		}
		if ( preg_match( '/^\d{8}$/', $raw ) ) {            // ACF date_picker "Ymd".
			return false;
		}
		if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $raw ) ) { // Date only.
			return false;
		}
		if ( false !== strpos( $raw, 'T' ) ) {               // ISO 8601 datetime.
			return true;
		}

		return (bool) preg_match( '/\d{1,2}:\d{2}/', $raw ); // Contains HH:MM.
	}

	/**
	 * Normalize a mapped date value to a string DateTime can parse.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @param string $raw     Raw date value.
	 * @param bool   $all_day Whether the event is all-day.
	 * @return string Normalized date string, or '' when unparseable.
	 */
	protected function get_posts_normalized_date( $raw, $all_day ) {
		$raw = trim( (string) $raw );

		if ( '' === $raw ) {
			return '';
		}

		if ( preg_match( '/^\d{8}$/', $raw ) ) {
			$date = \DateTime::createFromFormat( 'Ymd', $raw );
			if ( false === $date ) {
				return '';
			}
		} else {
			$timestamp = strtotime( $raw );
			if ( false === $timestamp || ! $timestamp ) {
				return '';
			}
			$date = new \DateTime();
			$date->setTimestamp( $timestamp );
		}

		return $all_day ? $date->format( 'Y-m-d' ) : $date->format( 'Y-m-d H:i:s' );
	}

	/**
	 * Build calendar event data from the posts source.
	 *
	 * Each event property (start/end date, location, speaker, description,
	 * image) is mapped to a post-meta key or an ACF field via the
	 * "Event Fields" section. When no start mapping resolves, the post's
	 * published date is used as an all-day event (legacy behavior).
	 *
	 * @since 3.0.0
	 * @access protected
	 * @return array Calendar data with 'status', 'error' and 'data' keys.
	 */
	protected function get_calendar_posts() {
		$settings = $this->get_settings_for_display();
		$timezone = $settings['timezone'];

		$cale_data = $calendar_data = [];

		$description_source = ! empty( $settings['posts_description_source'] ) ? $settings['posts_description_source'] : 'excerpt';
		$image_source       = ! empty( $settings['posts_image_source'] ) ? $settings['posts_image_source'] : 'featured';
		$all_day_mode       = ! empty( $settings['posts_all_day'] ) ? $settings['posts_all_day'] : 'auto';

		// Query Arguments
		$args = $this->get_posts_query_arguments();
		$posts_query = new \WP_Query( $args );

		if ( $posts_query->have_posts() ) :
			while ( $posts_query->have_posts() ) :
				$posts_query->the_post();

				$post_id = get_the_ID();

				$start_raw = $this->get_posts_mapped_value( $settings, $post_id, 'start' );
				$end_raw   = $this->get_posts_mapped_value( $settings, $post_id, 'end' );

				// Resolve the all-day flag.
				if ( 'yes' === $all_day_mode ) {
					$is_all_day = true;
				} elseif ( 'no' === $all_day_mode ) {
					$is_all_day = false;
				} elseif ( 'field' === $all_day_mode ) {
					$all_day_val = strtolower( trim( $this->get_posts_mapped_value( $settings, $post_id, 'all_day' ) ) );
					$is_all_day  = ! in_array( $all_day_val, [ '', '0', 'false', 'no' ], true );
				} else { // auto
					$is_all_day = ( '' === trim( $start_raw ) ) ? true : ! $this->posts_value_has_time( $start_raw );
				}

				// Resolve start/end dates, falling back to the post date.
				$format = $is_all_day ? 'Y-m-d' : 'Y-m-d H:i:s';
				$start  = '';
				$end    = '';

				if ( '' !== trim( $start_raw ) ) {
					$start_norm = $this->get_posts_normalized_date( $start_raw, $is_all_day );
					if ( '' !== $start_norm ) {
						$start = PP_Helper::get_timezones_converted_date( $start_norm, $format, $timezone );
					}

					if ( '' !== trim( $end_raw ) ) {
						$end_norm = $this->get_posts_normalized_date( $end_raw, $is_all_day );
						if ( '' !== $end_norm ) {
							$end = PP_Helper::get_timezones_converted_date( $end_norm, $format, $timezone );
						}
					}
				}

				if ( '' === $start ) {
					// No (parseable) start mapping: use the published date, all-day.
					$start      = PP_Helper::get_timezones_converted_date( get_the_date( 'Y-m-d H:i:s' ), 'Y-m-d', $timezone );
					$end        = '';
					$is_all_day = true;
				}

				// Description.
				$description = '';
				if ( 'excerpt' === $description_source ) {
					$description = get_the_excerpt();
				} elseif ( 'content' === $description_source ) {
					$description = apply_filters( 'the_content', get_the_content() );
				} elseif ( 'field' === $description_source ) {
					$description = $this->get_posts_mapped_value( $settings, $post_id, 'description' );
				}

				// Image.
				$image = '';
				if ( 'featured' === $image_source ) {
					$image = get_the_post_thumbnail_url( $post_id, 'large' );
					$image = $image ? $image : '';
				} elseif ( 'field' === $image_source ) {
					$image_val = $this->get_posts_mapped_value( $settings, $post_id, 'image' );
					if ( is_numeric( $image_val ) ) {
						$image_val = wp_get_attachment_image_url( (int) $image_val, 'large' );
					}
					$image = $image_val ? esc_url( $image_val ) : '';
				}

				$cale_data[] = [
					'id'          => $post_id,
					'title'       => get_the_title(),
					'description' => wp_kses_post( $description ),
					'start'       => $start,
					'end'         => $end,
					'url'         => get_permalink(),
					'allDay'      => $is_all_day ? 'yes' : '',
					'external'    => '',
					'nofollow'    => '',
					'guest'       => esc_html( $this->get_posts_mapped_value( $settings, $post_id, 'speaker' ) ),
					'location'    => esc_html( $this->get_posts_mapped_value( $settings, $post_id, 'location' ) ),
					'image'       => $image,
				];
			endwhile;
		endif;
		wp_reset_postdata();

		if ( empty( $cale_data ) ) {
			$calendar_data['status'] = false;
			$calendar_data['error']  = '';
			$calendar_data['data']   = [];
		} else {
			$calendar_data['status'] = true;
			$calendar_data['error']  = '';
			$calendar_data['data']   = $cale_data;
		}

		return $calendar_data;
	}

	/**
	 * Build calendar event data from the custom (repeater) source.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @return array {
	 *     @type bool   $status Whether any events were found.
	 *     @type string $error  Error message, empty on success.
	 *     @type array  $data   List of event arrays for FullCalendar.
	 * }
	 */
	protected function get_calendar_custom() {
		$settings = $this->get_settings_for_display();

		$cale_data     = [];
		$calendar_data = [];
		$events        = ! empty( $settings['events'] ) ? $settings['events'] : [];

		if ( empty( $events) ) {
			$calendar_data['status'] = false;
			$calendar_data['error']  = '';
			$calendar_data['data']   = [];

			return $calendar_data;
		}

		foreach ( $settings['events'] as $index => $item ) {

			if ( isset( $item['all_day'] ) && 'yes' === $item['all_day'] ) {
				$start = PP_Helper::get_timezones_converted_date( $item['start_event_allday'], 'Y-m-d', $settings['timezone'] );
				$end   = PP_Helper::get_timezones_converted_date( $item['end_event_allday'], 'Y-m-d', $settings['timezone'] );
			} else {
				$start = PP_Helper::get_timezones_converted_date( $item['start_event'], 'Y-m-d H:i:s', $settings['timezone'] );
				$end   = PP_Helper::get_timezones_converted_date( $item['end_event'], 'Y-m-d H:i:s', $settings['timezone'] );
			}

			$details_link = ! empty( $item['event_url']['url'] ) ? esc_url( $item['event_url']['url'] ) : '';
			if ( 'none' === $settings['event_click_action'] ) {
				// Non-clickable: drop the URL so FullCalendar renders a plain event.
				$details_link = '';
			} elseif ( 'popup' === $settings['event_click_action'] && empty( $details_link ) ) {
				// Popup with no link still needs an href so the event is clickable.
				$details_link = '#';
			}

			$image = ! empty( $item['image']['url'] ) ? esc_url( $item['image']['url'] ) : '';
			if ( ! empty( $item['image']['id'] ) ) {
				$image = esc_url( wp_get_attachment_image_url( $item['image']['id'], $item['thumbnail_size'] ) );
			}

			$cale_data[ $index ]['id']          = $index;
			$cale_data[ $index ]['classNames']  = 'elementor-repeater-item-' . esc_attr( $item['_id'] );
			$cale_data[ $index ]['title']       = esc_html( $item['event_title'] );
			$cale_data[ $index ]['description'] = wp_kses_post( $item['description'] );
			$cale_data[ $index ]['start']       = $start;
			$cale_data[ $index ]['end']         = $end;
			$cale_data[ $index ]['url']         = $details_link;
			$cale_data[ $index ]['allDay']      = esc_html( $item['all_day'] );
			$cale_data[ $index ]['external']    = esc_attr( $item['event_url']['is_external'] );
			$cale_data[ $index ]['nofollow']    = esc_attr( $item['event_url']['nofollow'] );
			$cale_data[ $index ]['guest']       = esc_html( $item['guest'] );
			$cale_data[ $index ]['location']    = esc_html( $item['location'] );
			$cale_data[ $index ]['image']       = $image;
		}
		$calendar_data['status'] = true;
		$calendar_data['error']  = '';
		$calendar_data['data']   = $cale_data;

		return $calendar_data;
	}

	/**
	 * Get Google calendar API Key.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @return string
	 */
	protected function google_calendar_api_key() {
		return PP_Admin_Settings::get_option( 'pp_google_calendar_api' );
	}

	/**
	 * Fetch and normalize events from the Google Calendar API.
	 *
	 * Results are cached in a transient for 10 minutes.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @return array {
	 *     @type bool   $status Whether the request succeeded.
	 *     @type string $error  Error message, empty on success.
	 *     @type array  $data   List of event arrays for FullCalendar.
	 * }
	 */
	protected function get_calendar_google_calendar() {
		$settings = $this->get_settings_for_display();

		$google_calendar_api_key = $this->google_calendar_api_key();

		$calendar_data = [];
		if ( empty( $google_calendar_api_key ) || empty( $settings['google_calendar_id'] ) ) {
			$calendar_data['status'] = false;
			$calendar_data['error']  = esc_html__( 'Please input API key & Calendar ID.', 'powerpack' );
			$calendar_data['data']   = [];
			return $calendar_data;
		}

		$calendar_id = rawurlencode( $settings['google_calendar_id'] );
		$base_url    = 'https://www.googleapis.com/calendar/v3/calendars/' . $calendar_id . '/events';

		$start_date = strtotime( $settings['google_calendar_start_date'] );
		$end_date   = strtotime( $settings['google_calendar_end_date'] );

		$arg = [
			'key'          => $google_calendar_api_key,
			'maxResults'   => $settings['google_calendar_max_item'],
			'timeMin'      => rawurlencode( gmdate( 'c', $start_date ) ),
			'singleEvents' => 'true',
		];

		if ( ! empty( $end_date ) && $end_date > $start_date ) {
			$arg['timeMax'] = rawurlencode( gmdate( 'c', $end_date ) );
		}

		// Do not place the API key in the option name; hash the request signature instead.
		$transient_key = 'ppe_google_calendar_' . md5( $base_url . wp_json_encode( $arg ) );
		$data          = get_transient( $transient_key );

		if ( false === $data ) {
			$response = wp_remote_get(
				add_query_arg( $arg, $base_url ),
				[ 'timeout' => 15 ]
			);

			if ( is_wp_error( $response ) ) {
				$calendar_data['status'] = false;
				$calendar_data['error']  = esc_html__( 'Unable to connect to Google Calendar. Please try again later.', 'powerpack' );
				$calendar_data['data']   = [];
				return $calendar_data;
			}

			$data    = wp_remote_retrieve_body( $response );
			$decoded = json_decode( $data );

			if ( is_object( $decoded ) && ! property_exists( $decoded, 'error' ) ) {
				set_transient( $transient_key, $data, 10 * MINUTE_IN_SECONDS );
			}
		}

		$decoded = ( false !== $data && '' !== $data ) ? json_decode( $data ) : null;

		if ( is_object( $decoded ) && property_exists( $decoded, 'error' ) ) {
			$calendar_data['status'] = false;
			$calendar_data['error']  = esc_html__( 'Please input valid API key & Calendar ID.', 'powerpack' );
			$calendar_data['data']   = [];
			return $calendar_data;
		}

		$data = $decoded;

		$cale_data = [];

		if ( isset( $data->items ) ) {

			foreach ( $data->items as $key => $item ) {

				if ( 'confirmed' !== $item->status ) {
					continue;
				}

				$all_day = '';

				if ( isset( $item->start->date ) ) {
					$all_day       = 'yes';
					$ev_start_date = $item->start->date;
					$ev_end_date   = $item->end->date;
				} else {
					$ev_start_date = $item->start->dateTime;
					$ev_end_date   = $item->end->dateTime;
				}

				$cale_data[] = [
					'id'          => esc_attr( ++$key ),
					'title'       => ! empty( $item->summary ) ? esc_html( $item->summary ) : esc_html__( 'No Title', 'powerpack' ),
					'description' => isset( $item->description ) ? wp_kses_post( $item->description ) : '',
					'start'       => esc_html( $ev_start_date ),
					'end'         => esc_html( $ev_end_date ),
					'url'         => ! empty( $item->htmlLink ) ? esc_url( $item->htmlLink ) : '',
					'allDay'      => esc_html( $all_day ),
					'external'    => 'on',
					'nofollow'    => 'on',
					'guest'       => ! empty( $item->creator->displayName ) ? esc_html( $item->creator->displayName ) : '',
					'location'    => ! empty( $item->location ) ? esc_html( $item->location ) : '',
				];
			}
		}

		$calendar_data['status'] = true;
		$calendar_data['error']  = '';
		$calendar_data['data']   = $cale_data;

		return $calendar_data;
	}

	/**
	 * Get the normalized calendar data for the given source.
	 *
	 * @since 3.0.0
	 * @access public
	 * @param string $cal_source Event source: 'posts', 'custom' or 'gcal'.
	 * @return array Calendar data with 'status', 'error' and 'data' keys.
	 */
	public function get_calendar_items( $cal_source ) {
		$settings = $this->get_settings_for_display();

		if ( 'posts' === $cal_source ) {
			return $this->get_calendar_posts();
		} elseif ( 'custom' === $cal_source ) {
			return $this->get_calendar_custom();
		} elseif ( 'gcal' === $cal_source ) {
			return $this->get_calendar_google_calendar();
		} else {
			return [
				'status' => false,
				'error'  => '',
				'data'   => [],
			];
		}
	}

	/**
	 * Print the event popup markup.
	 *
	 * @since 3.0.0
	 * @access public
	 * @param array $settings Widget settings.
	 * @return void
	 */
	public function get_popup_markup( $settings ) {
		ob_start();

		$event_popup_layout = $settings['event_popup_layout'];
		?>
		<div class="pp-event-calendar-popup-wrapper pp-event-calendar-popup-<?php echo esc_attr( $event_popup_layout ); ?>">
			<div class="pp-event-calendar-popup">
				<?php if ( ! empty( $settings['popup_close_icon']['value'] ) ) { ?>
					<span class="pp-event-calendar-popup-close pp-icon">
						<?php Icons_Manager::render_icon( $settings['popup_close_icon'], [ 'aria-hidden' => 'true' ] ); ?>
					</span>
				<?php } ?>
				<div class="pp-event-calendar-popup-body-wrap">
					<div class="pp-event-calendar-popup-body">
						<div class="pp-event-calendar-popup-image">
							<img src="" alt="">
							<h3 class="pp-event-calendar-popup-image-title"></h3>
						</div>
						<div class="pp-event-calendar-popup-content">
							<h3 class="pp-event-calendar-event-title"></h3>
							<?php $popup_header_fields = $settings['popup_header_fields']; ?>
							<?php if ( ! empty( $popup_header_fields ) ) { ?>
								<ul>
									<?php
										$popup_header_fields = $settings['popup_header_fields'];

										foreach ( $popup_header_fields as $index => $field ) {
											$field_type  = $field['field_type'];

											switch ( $field_type ) {
												case 'event_time':
													$field_wrap_class = 'pp-event-calendar-event-time-wrap';
													$field_class = 'pp-event-calendar-event-time';
													break;

												case 'event_speaker':
													$field_wrap_class = 'pp-event-calendar-event-guest-wrap';
													$field_class = 'pp-event-calendar-event-guest';
													break;

												case 'event_location':
													$field_wrap_class = 'pp-event-calendar-event-location-wrap';
													$field_class = 'pp-event-calendar-event-location';
													break;

												default:
													$field_wrap_class = '';
													$field_class = '';
											}

											$this->add_render_attribute( 'popup-field-wrap-' . $index, 'class', $field_wrap_class );
											$this->add_render_attribute( 'popup-field-' . $index, 'class', [ 'pp-event-calendar-event-detail', $field_class ] );
											?>
											<li <?php $this->print_render_attribute_string( 'popup-field-wrap-' . $index ); ?>>
												<div class="pp-event-calendar-popup-field-icon">
													<?php Icons_Manager::render_icon( $field['field_icon'], [ 'aria-hidden' => 'true' ] ); ?>
												</div>
												<div class="pp-event-calendar-popup-field-content">
													<span <?php $this->print_render_attribute_string( 'popup-field-' . $index ); ?>></span>
												</div>
											</li>
											<?php
										}
									?>
								</ul>
							<?php } ?>
							<div class="pp-event-calendar-popup-desc"></div>
							<?php if ( 'yes' === $settings['show_read_more'] ) { ?>
								<?php $read_more_text = ! empty( $settings['read_more_text'] ) ? $settings['read_more_text'] : ''; ?>
								<div class="pp-event-calendar-popup-readmore">
									<a class="pp-event-calendar-popup-readmore-link" href=""><?php echo esc_html( $read_more_text ); ?></a>
								</div>
							<?php } ?>
						</div>
					</div>
				</div>
			</div>
		</div>
		<?php
		echo ob_get_clean();
	}

	/**
	 * Render the calendar widget output on the frontend.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @return void
	 */
	protected function render() {
		$settings = $this->get_settings_for_display();
		$page_id  = '';

		if ( null !== \Elementor\Plugin::$instance->documents->get_current() ) {
			$page_id = \Elementor\Plugin::$instance->documents->get_current()->get_main_id();
		}

		$time_format = get_option( 'time_format' );
		$cal_source  = $settings['calendar_source'];

		if ( 'gcal' === $cal_source && ( empty( $this->google_calendar_api_key() ) || empty( $settings['google_calendar_id'] ) ) ) {
			?>
			<span class="pp-event-calendar-error-message" role="alert"><?php echo esc_html__( 'Please input API key & Calendar ID.', 'powerpack' ); ?></span>
			<?php
			return;
		}

		$calendar_data = $this->get_calendar_items( $cal_source );

		$this->add_render_attribute(
			'wrapper',
			[
				'class'            => 'pp-event-calendar-container',
				'data-page'        => $page_id,
				'data-source'      => $cal_source,
				'data-time-format' => ! empty( $time_format ) ? $time_format : 'g:i a',
				'data-cal-status'  => ! empty( $calendar_data['status'] ) ? 'true' : 'false',
				'data-cal-error'   => ! empty( $calendar_data['error'] ) ? $calendar_data['error'] : '',
				'id'               => 'pp-event-calendar-' . $this->get_id(),
			]
		);
		?>

		<div <?php echo wp_kses_post( $this->get_render_attribute_string( 'wrapper' ) ); ?>></div>
		<script type="application/json" class="pp-event-calendar-events" id="pp-event-calendar-events-<?php echo esc_attr( $this->get_id() ); ?>"><?php
			// JSON_HEX_TAG escapes "<"/">" so the payload can never break out of
			// the script element; JSON.parse reverses the escaping client-side.
			echo wp_json_encode( ! empty( $calendar_data['data'] ) ? $calendar_data['data'] : [], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		?></script>

		<?php
		if ( 'popup' === $settings['event_click_action'] ) {
			$this->get_popup_markup( $settings );
		}
	}
}
