<?php
/**
 * Back to Top element.
 *
 * @package BricksExtras
 */

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

/**
 * Back to Top element class.
 */
class X_Back_To_Top extends \Bricks\Element {

	/**
	 * Element category.
	 *
	 * @var string
	 */
	public $category = 'extras';

	/**
	 * Element name.
	 *
	 * @var string
	 */
	public $name = 'xbacktotop';

	/**
	 * Element icon.
	 *
	 * @var string
	 */
	public $icon = 'ti-arrow-circle-up';

	/**
	 * CSS selector.
	 *
	 * @var string
	 */
	public $css_selector = '';

	/**
	 * Required scripts.
	 *
	 * @var array
	 */
	public $scripts = array( 'xBackToTop' );

	/**
	 * Element is nestable.
	 *
	 * @var bool
	 */
	public $nestable = true;


	/**
	 * Get element label.
	 */
	public function get_label() {
		return esc_html__( 'Back to Top', 'bricks' );
	}

	/**
	 * Get element keywords.
	 */
	public function get_keywords() {
		return array( 'back to top', 'scroll to top' );
	}

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

		$this->control_groups['progress'] = array(
			'title'    => esc_html__( 'Progress', 'bricks' ),
			'tab'      => 'content',
			'required' => array( 'type', '=', array( 'progress' ) ),
		);

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

		$this->control_groups['inner_layout'] = array(
			'title' => esc_html__( 'Inner layout', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['scrolling'] = array(
			'title' => esc_html__( 'Scroll behavior', 'bricksextras' ),
			'tab'   => 'content',
		);

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

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

		$this->controls['type'] = array(
			'tab'       => 'content',
			'inline'    => true,
			'label'     => esc_html__( 'Type', 'bricks' ),
			'type'      => 'select',
			'options'   => array(
				'progress' => esc_html__( 'Progress circle', 'bricksextras' ),
				'regular'  => esc_html__( 'Regular', 'bricksextras' ),
			),
			'clearable' => false,
			'default'   => 'progress',
		);

		$this->controls['content'] = array(
			'tab'         => 'content',
			'inline'      => true,
			'label'       => esc_html__( 'Content', 'bricks' ),
			'type'        => 'select',
			'options'     => array(
				'icon' => esc_html__( 'Icon', 'bricks' ) . ' / ' . esc_html__( 'Text', 'bricks' ),
				'nest' => esc_html__( 'Add elements', 'bricks' ),
			),
			'clearable'   => false,
			'default'     => 'icon',
			'placeholder' => esc_html__( 'Icon', 'bricks' ) . ' / ' . esc_html__( 'Text', 'bricks' ),
		);

		$this->controls['buttonText'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Button text', 'bricks' ),
			'type'           => 'text',
			'inline'         => true,
			'placeholder'    => '',
			'hasDynamicData' => false,
			'required'       => array( 'content', '=', 'icon' ),
		);

		$this->controls['ariaLabel'] = array(
			'tab'            => 'content',
			'label'          => 'aria-label',
			'type'           => 'text',
			'inline'         => true,
			'default'        => esc_html__( 'Back to Top', 'bricks' ),
			'hasDynamicData' => false,
		);

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

		$this->controls['icon'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Icon', 'bricks' ),
			'type'     => 'icon',
			'css'      => array(
				array(
					'selector' => '.x-back-to-top_icon > *',
				),
			),
			'required' => array( 'content', '=', 'icon' ),
			'default'  => array(
				'library' => 'fontawesomeSolid',
				'icon'    => 'fas fa-chevron-up',
			),
		);

		$this->controls['iconTypography'] = array(
			'tab'      => 'content',
			'type'     => 'typography',
			'label'    => esc_html__( 'Icon typography', 'bricks' ),
			'css'      => array(
				array(
					'property' => 'font',
					'selector' => '.x-back-to-top_icon > *',
				),
			),
			'required' => array( 'content', '=', 'icon' ),
		);

		$this->controls['width'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Button width', 'bricks' ),
			'inline'      => true,
			'small'       => true,
			'type'        => 'number',
			'units'       => true,
			'placeholder' => '60px',
			'css'         => array(
				array(
					'selector' => '',
					'property' => 'width',
				),
			),
		);

		$this->controls['height'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Height', 'bricks' ),
			'inline'      => true,
			'small'       => true,
			'type'        => 'number',
			'units'       => true,
			'placeholder' => '60px',
			'required'    => array( 'type', '=', 'regular' ),
			'css'         => array(
				array(
					'selector' => '',
					'property' => 'height',
				),
			),
		);

		$this->controls['buttonTypography'] = array(
			'tab'   => 'content',
			'type'  => 'typography',
			'label' => esc_html__( 'Button typography', 'bricks' ),
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '',
				),
			),
		);

		$this->controls['strokeWidth'] = array(
			'group'       => 'progress',
			'tab'         => 'content',
			'label'       => esc_html__( 'Line width', 'bricksextras' ),
			'inline'      => true,
			'small'       => true,
			'type'        => 'number',
			'units'       => true,
			'placeholder' => '4px',
			'css'         => array(
				array(
					'selector' => '.x-back-to-top_progress',
					'property' => '--x-backtotop-stroke-width',
				),
			),
		);

		$this->controls['backgroundStrokeColor'] = array(
			'group'  => 'progress',
			'tab'    => 'content',
			'label'  => esc_html__( 'Color', 'bricks' ) . ' (' . esc_html__( 'Circle', 'bricks' ) . ')',
			'inline' => true,
			'type'   => 'color',
			'css'    => array(
				array(
					'selector' => '.x-back-to-top_progress-background',
					'property' => 'stroke',
				),
			),
		);

		$this->controls['strokeColor'] = array(
			'group'  => 'progress',
			'tab'    => 'content',
			'label'  => esc_html__( 'Color', 'bricks' ) . ' (' . esc_html__( 'Progress', 'bricks' ) . ')',
			'inline' => true,
			'type'   => 'color',
			'css'    => array(
				array(
					'selector' => '.x-back-to-top_progress-line',
					'property' => 'stroke',
				),
			),
		);

		$this->controls['lineCap'] = array(
			'group'       => 'progress',
			'tab'         => 'content',
			'label'       => esc_html__( 'Line cap', 'bricks' ),
			'inline'      => true,
			'type'        => 'select',
			'css'         => array(
				array(
					'selector' => '.x-back-to-top_progress-line',
					'property' => 'stroke-linecap',
				),
			),
			'options'     => array(
				'round'  => esc_html__( 'Round', 'bricks' ),
				'square' => esc_html__( 'Square', 'bricks' ),
			),
			'placeholder' => esc_html__( 'Round', 'bricks' ),
		);

		/* positioning */

		$this->controls['position'] = array(
			'tab'     => 'style',
			'group'   => 'positioning',
			'label'   => esc_html__( 'Position', 'bricks' ),
			'type'    => 'select',
			'options' => array(
				'fixed'    => 'Fixed',
				'absolute' => 'Absolute',
				'sticky'   => 'Sticky',
				'static'   => 'Static',
				'relative' => 'Relative',
			),
			'css'     => array(
				array(
					'property' => 'position',
					'selector' => '',
				),
			),
			'inline'  => true,
		);

		$this->controls['top'] = array(
			'tab'   => 'style',
			'group' => 'positioning',
			'label' => esc_html__( 'Top', 'bricks' ),
			'type'  => 'number',
			'units' => true,
			'css'   => array(
				array(
					'property' => 'top',
					'selector' => '',
				),
			),
		);

		$this->controls['right'] = array(
			'tab'     => 'style',
			'group'   => 'positioning',
			'label'   => esc_html__( 'Right', 'bricks' ),
			'type'    => 'number',
			'units'   => true,
			'css'     => array(
				array(
					'property' => 'right',
					'selector' => '',
				),
			),
			'default' => '40px',
		);

		$this->controls['bottom'] = array(
			'tab'     => 'style',
			'group'   => 'positioning',
			'label'   => esc_html__( 'Bottom', 'bricks' ),
			'type'    => 'number',
			'units'   => true,
			'css'     => array(
				array(
					'property' => 'bottom',
					'selector' => '',
				),
			),
			'default' => '40px',
		);

		$this->controls['left'] = array(
			'tab'   => 'style',
			'group' => 'positioning',
			'label' => esc_html__( 'Left', 'bricks' ),
			'type'  => 'number',
			'units' => true,
			'css'   => array(
				array(
					'property' => 'left',
					'selector' => '',
				),
			),
		);

		$this->controls['zIndex'] = array(
			'tab'         => 'style',
			'group'       => 'positioning',
			'label'       => esc_html__( 'Z-index', 'bricks' ),
			'type'        => 'number',
			'css'         => array(
				array(
					'property' => 'z-index',
					'selector' => '',
				),
			),
			'min'         => -999,
			'placeholder' => 10,
		);

		$this->controls['scrollDistance'] = array(
			'tab'         => 'content',
			'type'        => 'number',
			'units'       => true,
			'label'       => esc_html__( 'Visible after', 'bricks' ),
			'placeholder' => '100px',
			'group'       => 'scrolling',
			'inline'      => true,
			'small'       => true,
		);

		$this->controls['scrollUp'] = array(
			'tab'    => 'content',
			'inline' => true,
			'group'  => 'scrolling',
			'label'  => esc_html__( 'Only visible when scrolling up', 'bricksextras' ),
			'type'   => 'checkbox',
		);

		$this->controls['animationDescription'] = array(
			'tab'         => 'content',
			'type'        => 'seperator',
			'group'       => 'animation',
			'description' => esc_html__( 'Set the opacity/transform for the button in for the hidden state', 'bricksextras' ),
		);

		$this->controls['previewHidden'] = array(
			'tab'    => 'content',
			'inline' => true,
			'group'  => 'animation',
			'label'  => esc_html__( 'Preview', 'bricks' ),
			'type'   => 'checkbox',
		);

		$this->controls['hiddenOpacity'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Opacity', 'bricks' ),
			'inline'      => true,
			'small'       => true,
			'group'       => 'animation',
			'type'        => 'number',
			'min'         => 0,
			'max'         => 1,
			'step'        => '0.1',
			'placeholder' => '0',
			'css'         => array(
				array(
					'selector' => '',
					'property' => 'opacity',
				),
			),
		);

		$this->controls['hiddenTransform'] = array(
			'tab'     => 'style',
			'group'   => 'animation',
			'type'    => 'transform',
			'label'   => esc_html__( 'Transform', 'bricks' ),
			'css'     => array(
				array(
					'selector' => '',
					'property' => 'transform',
				),
			),
			'default' => array(
				'translateY' => '10px',
			),
			'inline'  => true,
			'small'   => true,
		);

		$inner_content = '.x-back-to-top_content';

		// Display.

		$this->controls['_flexWrap'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Flex wrap', 'bricks' ),
			'group'       => 'inner_layout',
			'tooltip'     => array(
				'content'  => 'flex-wrap',
				'position' => 'top-left',
			),
			'type'        => 'select',
			'options'     => array(
				'nowrap'       => esc_html__( 'No wrap', 'bricks' ),
				'wrap'         => esc_html__( 'Wrap', 'bricks' ),
				'wrap-reverse' => esc_html__( 'Wrap reverse', 'bricks' ),
			),
			'inline'      => true,
			'css'         => array(
				array(
					'property' => 'flex-wrap',
					'selector' => $inner_content,
				),
			),
			'placeholder' => esc_html__( 'No wrap', 'bricks' ),
		);

		$this->controls['_direction'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Direction', 'bricks' ),
			'group'    => 'inner_layout',
			'tooltip'  => array(
				'content'  => 'flex-direction',
				'position' => 'top-left',
			),
			'type'     => 'direction',
			'css'      => array(
				array(
					'property' => 'flex-direction',
					'selector' => $inner_content,
				),
			),
			'inline'   => true,
			'rerender' => true,
		);

		$this->controls['_justifyContent'] = array(
			'tab'     => 'content',
			'label'   => esc_html__( 'Align main axis', 'bricks' ),
			'group'   => 'inner_layout',
			'tooltip' => array(
				'content'  => 'justify-content',
				'position' => 'top-left',
			),
			'type'    => 'justify-content',
			'css'     => array(
				array(
					'property' => 'justify-content',
					'selector' => $inner_content,
				),
			),
		);

		$this->controls['_alignItems'] = array(
			'tab'     => 'content',
			'label'   => esc_html__( 'Align cross axis', 'bricks' ),
			'group'   => 'inner_layout',
			'tooltip' => array(
				'content'  => 'align-items',
				'position' => 'top-left',
			),
			'type'    => 'align-items',
			'css'     => array(
				array(
					'property' => 'align-items',
					'selector' => $inner_content,
				),
			),
		);

		$this->controls['_columnGap'] = array(
			'tab'   => 'content',
			'label' => esc_html__( 'Column gap', 'bricks' ),
			'group' => 'inner_layout',
			'type'  => 'number',
			'units' => true,
			'css'   => array(
				array(
					'property' => 'column-gap',
					'selector' => $inner_content,
				),
			),
		);

		$this->controls['_rowGap'] = array(
			'tab'   => 'content',
			'label' => esc_html__( 'Row gap', 'bricks' ),
			'group' => 'inner_layout',
			'type'  => 'number',
			'units' => true,
			'css'   => array(
				array(
					'property' => 'row-gap',
					'selector' => $inner_content,
				),
			),
		);

		$this->controls['innerBackgroundColor'] = array(
			'tab'   => 'content',
			'group' => 'inner_layout',
			'label' => esc_html__( 'Background color', 'bricks' ),
			'type'  => 'color',
			'css'   => array(
				array(
					'property' => 'background-color',
					'selector' => $inner_content,
				),
			),
		);

		$this->controls['innerBorder'] = array(
			'tab'   => 'content',
			'label' => esc_html__( 'Border', 'bricks' ),
			'group' => 'inner_layout',
			'type'  => 'border',
			'css'   => array(
				array(
					'property' => 'border',
					'selector' => $inner_content,
				),
			),
		);
	}

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

		if ( bricks_is_builder_main() ) {
			return;
		}

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

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

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

		$settings = $this->settings;

		$icon            = ! empty( $settings['icon'] ) ? self::render_icon( $settings['icon'] ) : false;
		$aria_label      = isset( $settings['ariaLabel'] ) ? esc_attr( $settings['ariaLabel'] ) : false;
		$scroll_distance = isset( $settings['scrollDistance'] ) ? intval( $settings['scrollDistance'] ) : 100;
		$type            = isset( $settings['type'] ) ? esc_attr( $settings['type'] ) : 'progress';
		$content         = isset( $settings['content'] ) ? $settings['content'] : 'icon';

		$config = array(
			'type'           => $type,
			'scrollDistance' => $scroll_distance,
			'scrollUp'       => isset( $settings['scrollUp'] ),
		);

		$this->set_attribute( '_root', 'data-x-backtotop', wp_json_encode( $config ) );
		$this->set_attribute( '_root', 'class', 'x-back-to-top' );

		if ( $aria_label ) {
			$this->set_attribute( '_root', 'aria-label', $aria_label );
		}

		$output = '';

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

		if ( 'progress' === $type ) {

			$output .= '<svg class="x-back-to-top_progress" height="100%" viewBox="0 0 100 100" width="100%">
              <path class="x-back-to-top_progress-background" d="M50,1 a50,50 0 0,1 0,100 a50,50 0 0,1 0,-100"></path>
              <path class="x-back-to-top_progress-line" d="M50,1 a50,50 0 0,1 0,100 a50,50 0 0,1 0,-100"></path>
          </svg>';

		}

		$output .= "<span class='x-back-to-top_content'>";

		if ( 'icon' === $content ) {

			$output .= "<span class='x-back-to-top_icon'>" . $icon . '</span>';

			$button_text = isset( $settings['buttonText'] ) ? $settings['buttonText'] : false;

			if ( $button_text ) {
				$output .= "<span class='x-back-to-top_text'>" . esc_html( $button_text ) . '</span>';
			}
		} elseif ( method_exists( '\Bricks\Frontend', 'render_children' ) ) {

			$output .= \Bricks\Frontend::render_children( $this );
		}

		$output .= '</span>';

		$output .= '</button>';

		echo $output;
	}

	/**
	 * Render builder template.
	 */
	public static function render_builder() {
		?>

		<script type="text/x-template" id="tmpl-bricks-element-xbacktotop">

			<component 
				is=button 
				class="x-back-to-top"
				aria-label="back to top"
				:data-x-backtotop="'regular' != settings.type ? 'progress' : 'regular'"
				:class="!settings.previewHidden ? 'x-back-to-top_builder-preview': ''"
			>

			<svg 
				v-show="'regular' !== settings.type"
				class="x-back-to-top_progress"
				:class="'regular' == settings.type ? 'x-back-to-top_progress-invisible' : ''" 
				height="100%" 
				viewBox="0 0 100 100" 
				width="100%"
				>
				<path class="x-back-to-top_progress-background" d="M50,1 a50,50 0 0,1 0,100 a50,50 0 0,1 0,-100"></path>
				<path class="x-back-to-top_progress-line" d="M50,1 a50,50 0 0,1 0,100 a50,50 0 0,1 0,-100" style="transition: stroke-dashoffset 10ms linear 0s; stroke-dasharray: 307.919, 307.919; stroke-dashoffset: 237.098;"></path>
			</svg>

			<span class='x-back-to-top_content'>

				<span v-if="'nest' != settings.content && settings.icon" class='x-back-to-top_icon'>
					<icon-svg :iconSettings="settings.icon"/>
				</span>
				<contenteditable
					tag="span"
					v-if="'nest' != settings.content && settings.buttonText" 
					class="x-back-to-top_text"
					:name="name"
					controlKey="buttonText"
					toolbar="style"
					:settings="settings"
				/>

				<bricks-element-children
				v-if="'nest' == settings.content"
				:element="element"
				/>
				</span>
			</component>
			
		</script>

		<?php
	}
}