<?php
/**
 * Star Rating element.
 *
 * @package BricksExtras
 */

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

/**
 * Star Rating element class.
 */
class X_Star_Rating extends \Bricks\Element {

	/**
	 * Element category.
	 *
	 * @var string
	 */
	public $category = 'extras';
	/**
	 * Element name.
	 *
	 * @var string
	 */
	public $name = 'xstarrating';
	/**
	 * Element icon.
	 *
	 * @var string
	 */
	public $icon = 'ion-md-star-outline';
	/**
	 * CSS selector.
	 *
	 * @var string
	 */
	public $css_selector = '';


	/**
	 * Get element label.
	 */
	public function get_label() {
		return esc_html__( 'Star Rating', 'bricksextras' );
	}

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

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

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

		$this->controls['starRating'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Rating', 'bricks' ),
			'type'        => 'text',
			'min'         => 0,
			'step'        => 1,
			'inline'      => true,
			'placeholder' => esc_html__( '4', 'bricksextras' ),
		);

		$this->controls['totalStars'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Total', 'bricks' ),
			'type'        => 'text',
			'min'         => 0,
			'step'        => 1,
			'inline'      => true,
			'placeholder' => esc_html__( '5', 'bricksextras' ),
		);

		$this->controls['iconSeparator'] = array(
			'tab'    => 'content',
			'label'  => esc_html__( 'Icons', 'bricks' ),
			'type'   => 'separator',
			'inline' => true,
		);

		$this->controls['iconBehaviour'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Type', 'bricks' ),
			'type'        => 'select',
			'inline'      => true,
			'small'       => true,
			'options'     => array(
				'color' => esc_html__( 'Colors', 'bricks' ),
				'icons' => esc_html__( 'Icons', 'bricks' ),
			),
			'placeholder' => esc_html__( 'Icons', 'bricks' ),
		);

		$this->controls['markedIcon'] = array(
			'tab'     => 'content',
			'label'   => esc_html__( 'Icon', 'bricks' ),
			'type'    => 'icon',
			'css'     => array(
				array(
					'selector' => '.x-star-rating_star-marked > *',
				),
			),
			'default' => array(
				'library' => 'fontawesomeSolid',
				'icon'    => 'fas fa-star',
			),
		);

		$this->controls['halfmarkedIcon'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Icon', 'bricks' ) . ' (' . esc_html__( 'Half', 'bricks' ) . ')',
			'type'     => 'icon',
			'css'      => array(
				array(
					'selector' => '.x-star-rating_star-half-marked > *',
				),
			),
			'default'  => array(
				'library' => 'fontawesomeSolid',
				'icon'    => 'fas fa-star-half-stroke',
			),
			'required' => array(
				array( 'iconBehaviour', '!=', 'color' ),
			),
		);

		$this->controls['icon'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Icon', 'bricks' ) . ' (' . esc_html__( 'Empty', 'bricks' ) . ')',
			'type'     => 'icon',
			'css'      => array(
				array(
					'selector' => '.x-star-rating_star > *',
				),
			),
			'default'  => array(
				'library' => 'fontawesomeRegular',
				'icon'    => 'fa fa-star',
			),
			'required' => array(
				array( 'iconBehaviour', '!=', 'color' ),
			),
		);

			$this->controls['iconColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'css'      => array(
					array(
						'property' => 'color',
					),
				),
				'required' => array(
					array( 'iconBehaviour', '!=', 'color' ),
				),
			);

			$this->controls['fullColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'css'      => array(
					array(
						'selector' => '&[data-x-icon=color]',
						'property' => '--x-star-color',
					),
				),
				'required' => array(
					array( 'iconBehaviour', '=', 'color' ),
				),
			);

			$this->controls['empytyColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Empty star color', 'bricks' ),
				'type'     => 'color',
				'css'      => array(
					array(
						'selector' => '&[data-x-icon=color]',
						'property' => '--x-star-empty-color',
					),
				),
				'required' => array(
					array( 'iconBehaviour', '=', 'color' ),
				),
			);

			$this->controls['iconSize'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Icon size', 'bricks' ),
				'type'        => 'number',
				'units'       => true,
				'css'         => array(
					array(
						'property' => 'font-size',
						'selector' => '& > div > *',
					),
					array(
						'property' => 'font-size',
					),
				),
				'placeholder' => '20px',

			);

			$this->controls['iconGap'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Gap', 'bricks' ),
				'type'        => 'number',
				'units'       => true,
				'css'         => array(
					array(
						'property' => 'gap',
						'selector' => '',
					),
				),
				'placeholder' => '0',

			);

			$this->controls['iconMargin'] = array(
				'tab'   => 'content',
				'label' => esc_html__( 'Margin', 'bricks' ),
				'type'  => 'spacing',
				'css'   => array(
					array(
						'property' => 'margin',
						'selector' => '& > div > *',
					),
				),
			);
	}

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

		if ( bricks_is_builder_main() ) {
			return;
		}

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

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

		$this->set_attribute( 'x-star-rating_star-marked', 'class', 'x-star-rating_star-marked' );
		$this->set_attribute( 'x-star-rating_star-half-marked', 'class', 'x-star-rating_star-half-marked' );
		$this->set_attribute( 'x-star-rating_star', 'class', 'x-star-rating_star' );

		$settings = $this->settings;

		$icon_behaviour = isset( $settings['iconBehaviour'] ) ? $settings['iconBehaviour'] : 'icons';

		$star_rating_setting = isset( $settings['starRating'] ) ? $settings['starRating'] : 4;
		$total_stars_setting = isset( $settings['totalStars'] ) ? $settings['totalStars'] : 5;

		$star_rating_original = strstr( $star_rating_setting, '{' ) ? $this->render_dynamic_data_tag( $star_rating_setting, 'text' ) : $star_rating_setting;
		$star_rating_original = is_numeric( $star_rating_original ) ? (float) $star_rating_original : 0;
		$total_stars          = strstr( $total_stars_setting, '{' ) ? $this->render_dynamic_data_tag( $total_stars_setting, 'text' ) : $total_stars_setting;
		$total_stars          = is_numeric( $total_stars ) ? (float) $total_stars : 0;

		$star_rating = round( floatval( $star_rating_original ) * 2 ) / 2;

		if ( 'color' === $icon_behaviour ) {

			$icon            = ! empty( $settings['markedIcon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star' )}>" . self::render_icon( $settings['markedIcon'] ) . '</div>' : false;
			$marked_icon     = ! empty( $settings['markedIcon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star-marked' )}>" . self::render_icon( $settings['markedIcon'] ) . '</div>' : false;
			$halfmarked_icon = ! empty( $settings['markedIcon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star-half-marked' )}>" . self::render_icon( $settings['markedIcon'] ) . '</div>' : false;

			if ( $icon && strpos( $icon, 'svg' ) !== false ) {
				$halfmarked_icon = ! empty( $settings['markedIcon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star-half-marked' )}>" . self::render_icon( $settings['markedIcon'] ) . '<span>' . self::render_icon( $settings['markedIcon'] ) . '</span></div>' : false;
			}
		} else {

			$icon            = ! empty( $settings['icon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star' )}>" . self::render_icon( $settings['icon'] ) . '</div>' : false;
			$marked_icon     = ! empty( $settings['markedIcon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star-marked' )}>" . self::render_icon( $settings['markedIcon'] ) . '</div>' : false;
			$halfmarked_icon = ! empty( $settings['halfmarkedIcon'] ) ? "<div {$this->render_attributes( 'x-star-rating_star-half-marked' )}>" . self::render_icon( $settings['halfmarkedIcon'] ) . '</div>' : false;

		}

		/* translators: 1: star rating value, 2: total stars */
		$aria_label = esc_attr( sprintf( __( 'Rating: %1$s out of %2$s stars', 'bricksextras' ), $star_rating_original, $total_stars ) );

		$this->set_attribute( '_root', 'aria-label', $aria_label );
		$this->set_attribute( '_root', 'role', 'img' );
		$this->set_attribute( '_root', 'data-x-star-rating', esc_attr( $star_rating_original ) );
		$this->set_attribute( '_root', 'data-x-icon', esc_attr( $icon_behaviour ) );

		$percentage = ( $star_rating_original - floor( $star_rating_original ) ) * 100;

		if ( 0.0 === $percentage && floatval( $total_stars ) === floatval( $star_rating ) ) {
			$percentage = 100;
		}

		$this->set_attribute( '_root', 'style', esc_attr( "--x-star-percentage: {$percentage}%" ) );

		$include_half_star = ( $star_rating * 2 ) % 2 !== 0;

		$rounding_up = floor( $star_rating ) > $star_rating_original;

		$output = '';

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

		if ( is_numeric( $star_rating ) && is_numeric( $total_stars ) ) {

			if ( 'color' === $icon_behaviour && ! $include_half_star ) {

				$marked_icons = $rounding_up ? str_repeat( $marked_icon, floor( $star_rating ) - 1 ) : str_repeat( $marked_icon, floor( $star_rating ) );
				$output      .= $total_stars > $star_rating ? $marked_icons . "<div {$this->render_attributes( 'x-star-rating_star-half-marked' )}>" . self::render_icon( $settings['markedIcon'] ) . '<span>' . self::render_icon( $settings['markedIcon'] ) . '</span></div>' : str_repeat( $marked_icon, $total_stars );
			} else {
				$output .= $total_stars >= $star_rating ? str_repeat( $marked_icon, floor( $star_rating ) ) : str_repeat( $marked_icon, $total_stars );
			}

			$output .= $include_half_star ? $halfmarked_icon : '';

			if ( $total_stars - $star_rating > 0 ) {

				if ( 'color' === $icon_behaviour && ! $rounding_up && ! $include_half_star && ( floatval( $total_stars ) !== floatval( $star_rating ) ) ) {
					$output .= str_repeat( $icon, $total_stars - 1 - round( $star_rating ) );
				} else {
					$output .= str_repeat( $icon, $total_stars - round( $star_rating ) );
				}
			}
		}

		$output .= '</div>';

		echo $output;
	}
}
