<?php
/**
 * Offcanvas element.
 *
 * @package BricksExtras
 */

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

/**
 * Offcanvas element class.
 */
class X_Offcanvas extends \Bricks\Element {

	/**
	 * Element category.
	 *
	 * @var string
	 */
	public $category = 'extras';
	/**
	 * Element name.
	 *
	 * @var string
	 */
	public $name = 'xoffcanvas';
	/**
	 * Element icon.
	 *
	 * @var string
	 */
	public $icon = 'ti-layout-sidebar-left';
	/**
	 * CSS selector.
	 *
	 * @var string
	 */
	public $css_selector = '.x-offcanvas_inner';
	/**
	 * Script localized flag.
	 *
	 * @var bool
	 */
	private static $script_localized = false;

	/**
	 * Get element label.
	 */
	public function get_label() {
		return esc_html__( 'OffCanvas', 'bricksextras' ) . ' (' . esc_html__( 'Template', 'bricks' ) . ')';
	}

	/**
	 * Get element keywords.
	 */
	public function get_keywords() {
		return array( 'menu', 'offcanvas' );
	}

	/**
	 * Set control groups.
	 */
	public function set_control_groups() {

		$this->controls['text'] = array(
			'title' => esc_html__( 'Text', 'bricks' ),
			'tab'   => 'content',
		);

		$this->control_groups['layout'] = array(
			'title' => esc_html__( 'Layout', 'bricks' ) . ' / ' . esc_html__( 'Spacing', 'bricks' ),
			'tab'   => 'content',
		);

		$this->control_groups['config'] = array(
			'title' => esc_html__( 'Configure', 'bricks' ),
			'tab'   => 'content',
		);

		$this->control_groups['backdrop'] = array(
			'title' => esc_html__( 'Backdrop', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['accessibility'] = array(
			'title' => esc_html__( 'Accessibility', 'bricks' ),
			'tab'   => 'content',
		);
	}


	/**
	 * Set element controls.
	 */
	public function set_controls() {

		$this->controls['builderHidden'] = array(
			'tab'    => 'content',
			'inline' => true,
			'small'  => true,
			'label'  => esc_html__( 'Hide in builder', 'bricksextras' ),
			'type'   => 'checkbox',
		);

		$this->controls['builderHidden_sep'] = array(
			'tab'  => 'content',
			'type' => 'separator',
		);

		if ( ! class_exists( '\Bricks\Popups' ) ) {
			$templates_list = bricks_is_builder() ? \Bricks\Templates::get_templates_list( get_the_ID() ) : array();
		} else {
			$templates_list = bricks_is_builder() ? \Bricks\Templates::get_templates_list( array( 'section', 'content' ), get_the_ID() ) : array();
		}

			$this->controls['offcanvas_template'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'label'       => esc_html__( 'Template', 'bricks' ),
				'type'        => 'select',
				'options'     => $templates_list,
				'searchable'  => true,
				'placeholder' => esc_html__( 'Select template', 'bricks' ),
			);

			$this->controls['clickTrigger'] = array(
				'tab'            => 'content',
				'type'           => 'text',
				'label'          => esc_html__( 'Selector', 'bricks' ) . ' (' . esc_html__( 'Trigger', 'bricks' ) . ')',
				'placeholder'    => '.your-class-here',
				'hasDynamicData' => false,
				'inline'         => true,
				'default'        => '.brxe-xburgertrigger',
			);

			$this->controls['componentScope'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Component scope', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'True', 'bricks' ),
					'false' => esc_html__( 'False', 'bricks' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'False', 'bricks' ),
				'clearable'   => false,
			);

			$this->controls['offcanvas_color'] = array(
				'tab'    => 'content',
				'label'  => esc_html__( 'Background color', 'bricks' ),
				'type'   => 'color',
				'inline' => true,
				'css'    => array(
					array(
						'property' => 'background-color',
						'selector' => '.x-offcanvas_inner',
					),
				),
			);

			$this->controls['style_sep'] = array(
				'tab'  => 'content',
				'type' => 'separator',
			);

			$this->controls['direction'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Position', 'bricks' ),
				'type'        => 'select',
				'options'     => array(
					'x-offcanvas_left'   => esc_html__( 'Left', 'bricks' ),
					'x-offcanvas_right'  => esc_html__( 'Right', 'bricks' ),
					'x-offcanvas_top'    => esc_html__( 'Top', 'bricks' ),
					'x-offcanvas_bottom' => esc_html__( 'Bottom', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Select', 'bricks' ),
				'default'     => 'x-offcanvas_left',
			);

			$this->controls['transitionDuration'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Duration', 'bricks' ),
				'inline'      => true,
				'type'        => 'number',
				'units'       => true,
				'css'         => array(
					array(
						'selector' => '',
						'property' => '--x-offcanvas-duration',
					),
				),
				'placeholder' => '300ms',
			);

			$this->controls['transitionType'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Transition', 'bricks' ),
				'type'        => 'select',
				'options'     => array(
					'slide' => esc_html__( 'Slide', 'bricks' ),
					'fade'  => esc_html__( 'Fade', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Slide', 'bricks' ),
			);

			$this->controls['offcanvas_width'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Width', 'bricks' ),
				'inline'      => true,
				'type'        => 'number',
				'units'       => true,
				'css'         => array(
					array(
						'selector' => '.x-offcanvas_inner',
						'property' => 'width',
					),
				),
				'placeholder' => '300px',
				'required'    => array( 'direction', '=', array( 'x-offcanvas_left', 'x-offcanvas_right' ) ),
			);

			$this->controls['offcanvas_height'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Height', 'bricks' ),
				'inline'      => true,
				'type'        => 'number',
				'units'       => true,
				'css'         => array(
					array(
						'selector' => '.x-offcanvas_inner',
						'property' => 'height',
					),
				),
				'placeholder' => '100%',
				'required'    => array( 'direction', '=', array( 'x-offcanvas_top', 'x-offcanvas_bottom' ) ),
			);

			/* config */

			$this->controls['maybe_hash_close'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
				'label'       => esc_html__( 'Clicking hashlink will close', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['hashlink_exclude_selector'] = array(
				'tab'         => 'content',
				'group'       => 'config',
				'label'       => esc_html__( 'Exclude hashlinks matching selector', 'bricksextras' ),
				'type'        => 'text',
				'required'    => array( 'maybe_hash_close', '!=', 'false' ),
				'hasDynamicData' => false,
			);

			$this->controls['esc_to_close'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
				'label'       => esc_html__( 'Esc to close', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['move_focus'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Offcanvas', 'bricksextras' ),
				'label'       => esc_html__( 'Move focus to offcanvas', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'content'  => esc_html__( 'Offcanvas', 'bricksextras' ),
					'selector' => esc_html__( 'Selector inside offcanvas', 'bricksextras' ),
					'disable'  => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['trapFocus'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
				'label'       => esc_html__( 'Trap focus', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['returnFocus'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
				'label'       => esc_html__( 'Return focus to trigger on close', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['focus_selector'] = array(
				'tab'            => 'content',
				'group'          => 'config',
				'label'          => esc_html__( 'Selector', 'bricks' ) . ' (' . esc_html__( 'Focus', 'bricks' ) . ')',
				'type'           => 'text',
				'placeholder'    => 'a',
				'required'       => array( 'move_focus', '=', 'selector' ),
				'hasDynamicData' => false,
			);

			$this->controls['preventScroll'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
				'label'       => esc_html__( 'Prevent scroll when open', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['sync_burger_triggers'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
				'label'       => esc_html__( 'Sync burger triggers', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['force_second_close'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'config',
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
				'label'       => esc_html__( 'Close other offcanvas', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['second_offcanvas_selector'] = array(
				'tab'         => 'content',
				'group'       => 'config',
				'label'       => esc_html__( 'Selector', 'bricks' ),
				'type'        => 'text',
				'placeholder' => '.other-offcanvas',
				'required'    => array( 'force_second_close', '=', 'true' ),
			);

			/* backdrop */

			$this->controls['disable_backdrop'] = array(
				'tab'    => 'content',
				'inline' => true,
				'small'  => true,
				'group'  => 'backdrop',
				'label'  => esc_html__( 'Disable backdrop', 'bricks' ),
				'type'   => 'checkbox',

			);

			$this->controls['backdrop_to_close'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'backdrop',
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
				'label'       => esc_html__( 'Click backdrop to close', 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'required'    => array( 'disable_backdrop', '!=', true ),
			);

			$this->controls['backdrop_color'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ) . ' (' . esc_html__( 'Backdrop', 'bricksextras' ) . ')',
				'type'     => 'color',
				'group'    => 'backdrop',
				'inline'   => true,
				'css'      => array(
					array(
						'property' => 'background-color',
						'selector' => '.x-offcanvas_backdrop',
					),
				),
				'required' => array( 'disable_backdrop', '!=', true ),
			);

			$this->controls['backdrop_zindex'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Z-index', 'bricks' ),
				'type'        => 'number',
				'group'       => 'backdrop',
				'min'         => 0,
				'max'         => 1000,
				'step'        => 1,
				'inline'      => true,
				'css'         => array(
					array(
						'property' => 'z-index',
						'selector' => '.x-offcanvas_backdrop',
					),
				),
				'placeholder' => esc_html__( '10', 'bricksextras' ),
				'required'    => array( 'disable_backdrop', '!=', true ),
			);

			/* Accessibility */

			$this->controls['aria_label'] = array(
				'tab'         => 'content',
				'group'       => 'accessibility',
				'label'       => 'aria-label',
				'inline'      => true,
				'type'        => 'text',
				'placeholder' => esc_html__( 'Offcanvas', 'bricksextras' ),
			);

			$this->controls['auto_aria_control'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'accessibility',
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
				/* translators: %s: HTML attribute name */
				'label'       => sprintf( esc_html__( 'Add %s to trigger', 'bricksextras' ), 'aria-controls' ),
				'type'        => 'select',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['reduce_motion'] = array(
				'tab'         => 'content',
				'inline'      => true,
				'group'       => 'accessibility',
				'placeholder' => esc_html__( 'Slide', 'bricks' ),
				'label'       => esc_html__( "If 'Reduce motion' enabled", 'bricksextras' ),
				'type'        => 'select',
				'options'     => array(
					'fade'         => esc_html__( 'Fade', 'bricks' ),
					'slide'        => esc_html__( 'Slide', 'bricks' ),
					'notransition' => esc_html__( 'Disable', 'bricks' ),
				),
			);

			$this->controls['tag'] = array(
				'tab'            => 'content',
				'label'          => esc_html__( 'HTML tag', 'bricks' ),
				'type'           => 'text',
				'hasDynamicData' => false,
				'group'          => 'accessibility',
				'inline'         => true,
				'clearable'      => false,
				'placeholder'    => 'div',
			);

			$this->controls['role'] = array(
				'tab'            => 'content',
				'label'          => esc_html__( 'Role', 'bricks' ),
				'type'           => 'text',
				'hasDynamicData' => false,
				'group'          => 'accessibility',
				'inline'         => true,
				'clearable'      => false,
				'placeholder'    => 'dialog',
			);

			$this->controls['justifyContent'] = array(
				'tab'          => 'content',
				'label'        => esc_html__( 'Justify content', 'bricks' ),
				'group'        => 'layout',
				'type'         => 'justify-content',
				'css'          => array(
					array(
						'property' => 'justify-content',
						'selector' => '.x-offcanvas_inner',
					),
				),
				'isHorizontal' => false,
			);

			$this->controls['alignItems'] = array(
				'tab'          => 'content',
				'label'        => esc_html__( 'Align items', 'bricks' ),
				'group'        => 'layout',
				'type'         => 'align-items',
				'css'          => array(
					array(
						'property' => 'align-items',
						'selector' => '.x-offcanvas_inner',
					),
				),
				'isHorizontal' => false,
			);

			$this->controls['content_padding'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Content padding', 'bricks' ),
				'type'        => 'spacing',
				'group'       => 'layout',
				'css'         => array(
					array(
						'property' => 'padding',
						'selector' => '.x-offcanvas_inner',
					),
				),
				'placeholder' => array(
					'top'    => '30px',
					'right'  => '30px',
					'bottom' => '30px',
					'left'   => '30px',
				),
			);
	}


	/**
	 * Enqueue scripts.
	 */
	public function enqueue_scripts() {

		if ( bricks_is_builder_main() ) {
			return;
		}

		wp_enqueue_script( 'x-offcanvas', BRICKSEXTRAS_URL . 'components/assets/js/' . \BricksExtras\Helpers::maybe_minify_scripts( 'offcanvas' ) . '.js', array( 'bricks-scripts' ), \BricksExtras\Plugin::VERSION, true );

		if ( ! self::$script_localized ) {

			wp_localize_script(
				'x-offcanvas',
				'xProOffCanvas',
				array(
					'Instances' => array(),
				)
			);

			self::$script_localized = true;

		}

		if ( ! \BricksExtras\Helpers::element_css_added( $this->name ) ) {
			wp_enqueue_style( 'x-offcanvas', BRICKSEXTRAS_URL . 'components/assets/css/offcanvas.css', array(), \BricksExtras\Plugin::VERSION );
		}
	}


	/**
	 * Render element output.
	 */
	public function render() {

		$direction                 = isset( $this->settings['direction'] ) ? esc_attr( $this->settings['direction'] ) : 'x-offcanvas_left';
		$aria_label                = isset( $this->settings['aria_label'] ) ? esc_attr( bricks_render_dynamic_data( $this->settings['aria_label'] ) ) : esc_attr__( 'Offcanvas', 'bricksextras' );
		$role                      = isset( $this->settings['role'] ) ? esc_attr( $this->settings['role'] ) : 'dialog';
		$move_focus                = isset( $this->settings['move_focus'] ) ? $this->settings['move_focus'] : 'content';
		$focus_selector            = isset( $this->settings['focus_selector'] ) ? $this->settings['focus_selector'] : 'a';
		$second_offcanvas_selector = isset( $this->settings['second_offcanvas_selector'] ) ? bricks_render_dynamic_data( $this->settings['second_offcanvas_selector'] ) : '.other-offcanvas';

		$maybe_hash_close = isset( $this->settings['maybe_hash_close'] ) ? $this->settings['maybe_hash_close'] : 'true';

		$transition_type = isset( $this->settings['transitionType'] ) ? esc_attr( $this->settings['transitionType'] ) : 'slide';

		$offcanvas_config = array(
			'clickTrigger'   => isset( $this->settings['clickTrigger'] ) ? $this->settings['clickTrigger'] : '',
			'preventScroll'  => isset( $this->settings['preventScroll'] ) ? $this->settings['preventScroll'] : false,
			'returnFocus'    => isset( $this->settings['returnFocus'] ) ? 'enable' === $this->settings['returnFocus'] : true,
			'componentScope' => isset( $this->settings['componentScope'] ) ? $this->settings['componentScope'] : 'false',
		);

		if ( \BricksExtras\Helpers::get_parent_component_id( $this->element ) ) {
			$offcanvas_config += array( 'parentComponent' => \BricksExtras\Helpers::get_parent_component_id( $this->element ) );
		}

		if ( isset( $this->settings['esc_to_close'] ) ) {
			$offcanvas_config += array( 'escClose' => $this->settings['esc_to_close'] );
		}

		if ( isset( $this->settings['trapFocus'] ) ) {
			$offcanvas_config += array( 'trapFocus' => $this->settings['trapFocus'] );
		}

		if ( isset( $this->settings['backdrop_to_close'] ) ) {
			$offcanvas_config += array( 'backdropClose' => $this->settings['backdrop_to_close'] );
		}

		if ( isset( $this->settings['auto_aria_control'] ) ) {
			$offcanvas_config += array( 'autoAriaControl' => $this->settings['auto_aria_control'] );
		}

		if ( isset( $this->settings['force_second_close'] ) && 'true' === $this->settings['force_second_close'] ) {
			$offcanvas_config += array( 'secondClose' => $second_offcanvas_selector );
		}

		if ( isset( $this->settings['sync_burger_triggers'] ) && 'true' === $this->settings['sync_burger_triggers'] ) {
			$offcanvas_config += array( 'syncBurgers' => $this->settings['sync_burger_triggers'] );
		}

		if ( isset( $this->settings['reduce_motion'] ) ) {
			$offcanvas_config += array( 'reduceMotion' => $this->settings['reduce_motion'] );
		}

		if ( 'selector' === $move_focus ) {
			$offcanvas_config += array( 'focus' => $focus_selector );
		} elseif ( 'disable' === $move_focus ) {
			$offcanvas_config += array( 'focus' => 'false' );
		}

		if ( 'false' === $maybe_hash_close ) {
			$offcanvas_config += array( 'disableHashlink' => 'true' );
		}

		if ( ! empty( $this->settings['hashlink_exclude_selector'] ) ) {
			$offcanvas_config += array( 'hashlinkExcludeSelector' => $this->settings['hashlink_exclude_selector'] );
		}

		$template_id = ! empty( $this->settings['offcanvas_template'] ) ? intval( $this->settings['offcanvas_template'] ) : false;

		$prevent_scroll = isset( $this->settings['preventScroll'] ) ? $this->settings['preventScroll'] : false;

		if ( $prevent_scroll ) {
			$this->set_attribute( 'x-offcanvas_inner', 'data-lenis-prevent', '' );
		}

		$this->set_attribute( '_root', 'class', 'x-offcanvas' );
		$this->set_attribute( 'x-offcanvas_inner', 'class', 'x-offcanvas_inner ' . $direction );
		$this->set_attribute( 'x-offcanvas_inner', 'aria-hidden', BricksExtras\Helpers::maybe_preview() ? 'false' : 'true' );
		$this->set_attribute( 'x-offcanvas_inner', 'aria-label', $aria_label );
		$this->set_attribute( 'x-offcanvas_inner', 'role', $role );
		$this->set_attribute( 'x-offcanvas_inner', 'tabindex', '0' );
		$this->set_attribute( 'x-offcanvas_backdrop', 'class', 'x-offcanvas_backdrop' );
		$this->set_attribute( 'x-offcanvas_inner', 'data-type', $transition_type );

		if ( isset( $this->settings['builderHidden'] ) ) {
			$this->set_attribute( 'x-offcanvas_inner', 'data-x-hide', 'true' );
			$this->set_attribute( 'x-offcanvas_backdrop', 'data-x-hide', 'true' );
		}

		if ( ! BricksExtras\Helpers::maybe_preview() ) {
			$this->set_attribute( 'x-offcanvas_inner', 'inert', '' );
		}

		if ( \BricksExtras\Helpers::get_parent_loop_id( $this->element ) ) {
			$offcanvas_config += array( 'isLooping' => \BricksExtras\Helpers::get_parent_loop_id( $this->element ) );
		}

		if ( \BricksExtras\Helpers::get_parent_loop_id( $this->element, true ) ) {
			$offcanvas_config += array( 'isLoopingComponent' => \BricksExtras\Helpers::get_parent_loop_id( $this->element, true ) );
		}

		// Generate and set a unique identifier for this instance.
		$indentifier = \BricksExtras\Helpers::set_identifier_attribute( $this );

		$this->set_attribute( 'x-offcanvas_inner', 'id', "x-offcanvas_inner-{$indentifier}" );

		$this->set_attribute( '_root', 'data-x-offcanvas', wp_json_encode( $offcanvas_config ) );

		$tag = isset( $this->settings['tag'] ) ? \Bricks\Helpers::sanitize_html_tag( $this->settings['tag'], 'div' ) : 'div';

		$output = '';

		$output .= "<div {$this->render_attributes( '_root' )}>";

		$output .= '<' . $tag . " {$this->render_attributes( 'x-offcanvas_inner' )}>";

		$output .= do_shortcode( '[bricks_template id="' . $template_id . '"]' );

		$output .= '</' . $tag . '>';

		$output .= isset( $this->settings['disable_backdrop'] ) ? '' : "<div {$this->render_attributes( 'x-offcanvas_backdrop' )}></div>";

		$output .= '</div>';

		echo $output;
	}
}
