<?php
/**
 * Logo Grid element.
 *
 * A responsive grid of client / partner / sponsor logos. Each logo can link
 * out and carry a name (alt + tooltip). Best-of from the competitors: a
 * grayscale-until-hover treatment, per-breakpoint columns, hover effects
 * (colour / zoom / lift), adjustable logo size, gap and cell styling
 * (background, padding, radius, border).
 *
 * @package CraftAddonsForWPBakery
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class CAFW_Element_Logo_Grid
 */
class CAFW_Element_Logo_Grid extends CAFW_Element_Base {

	/**
	 * {@inheritDoc}
	 */
	public function get_shortcode_tag() {
		return 'cafw_logo_grid';
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_label() {
		return esc_html__( 'Logo Grid', 'craft-addons-for-wpbakery' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_description() {
		return esc_html__( 'Responsive grid of client logos.', 'craft-addons-for-wpbakery' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_admin_icon() {
		return 'dashicons-screenoptions';
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_editor_icon() {
		return 'cafw-vc-icon cafw-vc-icon-logo-grid';
	}

	/**
	 * {@inheritDoc}
	 */
	protected function get_defaults() {
		return array(
			'items'             => $this->default_items(),
			'columns'           => '4',
			'columns_tablet'    => '3',
			'columns_mobile'    => '2',
			'gap'               => '24',
			'align'             => 'center',
			'logo_height'       => '60',
			'grayscale'         => '',
			'opacity'           => '100',
			'hover_effect'      => 'color',
			'cell_bg'           => '',
			'cell_padding'      => '20',
			'cell_radius'       => '8',
			'cell_border_color' => '',
			'cell_border_width' => '',
		);
	}

	/**
	 * Four empty slots so a freshly dropped grid shows placeholder cells.
	 *
	 * @return string URL-encoded JSON for the param_group field.
	 */
	private function default_items() {
		return rawurlencode( wp_json_encode( array( array(), array(), array(), array() ) ) );
	}

	/**
	 * Build a columns dropdown (2..6).
	 *
	 * @param string $param Param name.
	 * @param string $label Heading.
	 * @param string $std   Default value.
	 * @return array
	 */
	private function columns_field( $param, $label, $std ) {
		return array(
			'type'             => 'dropdown',
			'heading'          => $label,
			'param_name'       => $param,
			'value'            => array( '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6' ),
			'std'              => $std,
			'edit_field_class' => 'vc_col-sm-4 vc_column',
		);
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_params() {
		$styles = esc_html__( 'Styles', 'craft-addons-for-wpbakery' );

		return array(
			array(
				'type'        => 'param_group',
				'heading'     => esc_html__( 'Logos', 'craft-addons-for-wpbakery' ),
				'param_name'  => 'items',
				'value'       => $this->default_items(),
				'description' => esc_html__( 'Add, remove and reorder the logos.', 'craft-addons-for-wpbakery' ),
				'params'      => array(
					array(
						'type'        => 'attach_image',
						'heading'     => esc_html__( 'Logo', 'craft-addons-for-wpbakery' ),
						'param_name'  => 'image',
						'admin_label' => true,
					),
					array(
						'type'        => 'textfield',
						'heading'     => esc_html__( 'Name', 'craft-addons-for-wpbakery' ),
						'param_name'  => 'name',
						'description' => esc_html__( 'Shown as the alt text and tooltip.', 'craft-addons-for-wpbakery' ),
					),
					array(
						'type'        => 'vc_link',
						'heading'     => esc_html__( 'Link', 'craft-addons-for-wpbakery' ),
						'param_name'  => 'link',
						'description' => esc_html__( 'Optional - makes the logo a link.', 'craft-addons-for-wpbakery' ),
					),
				),
			),
			$this->columns_field( 'columns', esc_html__( 'Columns', 'craft-addons-for-wpbakery' ), '4' ),
			$this->columns_field( 'columns_tablet', esc_html__( 'Columns (tablet)', 'craft-addons-for-wpbakery' ), '3' ),
			$this->columns_field( 'columns_mobile', esc_html__( 'Columns (mobile)', 'craft-addons-for-wpbakery' ), '2' ),
			array(
				'type'             => 'textfield',
				'heading'          => esc_html__( 'Gap (px)', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'gap',
				'value'            => '24',
				'edit_field_class' => 'vc_col-sm-6 vc_column',
			),
			array(
				'type'             => 'dropdown',
				'heading'          => esc_html__( 'Logo alignment', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'align',
				'value'            => array(
					esc_html__( 'Center', 'craft-addons-for-wpbakery' ) => 'center',
					esc_html__( 'Left', 'craft-addons-for-wpbakery' )   => 'left',
					esc_html__( 'Right', 'craft-addons-for-wpbakery' )  => 'right',
				),
				'std'              => 'center',
				'edit_field_class' => 'vc_col-sm-6 vc_column',
			),
			// ---- Styles ----
			array(
				'type'             => 'textfield',
				'heading'          => esc_html__( 'Logo height (px)', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'logo_height',
				'value'            => '60',
				'description'      => esc_html__( 'Max height; logos scale down to fit.', 'craft-addons-for-wpbakery' ),
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-6 vc_column',
			),
			array(
				'type'             => 'textfield',
				'heading'          => esc_html__( 'Opacity (%)', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'opacity',
				'value'            => '100',
				'description'      => esc_html__( 'Resting opacity; full on hover.', 'craft-addons-for-wpbakery' ),
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-6 vc_column',
			),
			array(
				'type'             => 'checkbox',
				'heading'          => esc_html__( 'Grayscale', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'grayscale',
				'value'            => array( esc_html__( 'Show logos in grayscale (colour on hover)', 'craft-addons-for-wpbakery' ) => 'yes' ),
				'group'            => $styles,
				'edit_field_class' => 'vc_col-xs-12 vc_column',
			),
			array(
				'type'             => 'dropdown',
				'heading'          => esc_html__( 'Hover effect', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'hover_effect',
				'value'            => array(
					esc_html__( 'Colour / fade in', 'craft-addons-for-wpbakery' ) => 'color',
					esc_html__( 'Zoom', 'craft-addons-for-wpbakery' )             => 'zoom',
					esc_html__( 'Lift', 'craft-addons-for-wpbakery' )             => 'lift',
					esc_html__( 'None', 'craft-addons-for-wpbakery' )             => 'none',
				),
				'std'              => 'color',
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-6 vc_column',
			),
			array(
				'type'             => 'colorpicker',
				'heading'          => esc_html__( 'Cell background', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'cell_bg',
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-6 vc_column cafw-bg-sep',
			),
			array(
				'type'             => 'textfield',
				'heading'          => esc_html__( 'Cell padding (px)', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'cell_padding',
				'value'            => '20',
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-4 vc_column cafw-bg-sep',
			),
			array(
				'type'             => 'textfield',
				'heading'          => esc_html__( 'Cell radius (px)', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'cell_radius',
				'value'            => '8',
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-4 vc_column cafw-bg-sep',
			),
			array(
				'type'             => 'textfield',
				'heading'          => esc_html__( 'Cell border width (px)', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'cell_border_width',
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-4 vc_column cafw-bg-sep',
			),
			array(
				'type'             => 'colorpicker',
				'heading'          => esc_html__( 'Cell border color', 'craft-addons-for-wpbakery' ),
				'param_name'       => 'cell_border_color',
				'group'            => $styles,
				'edit_field_class' => 'vc_col-sm-6 vc_column',
			),
		);
	}

	/**
	 * Append "px" to a numeric value, or '' when blank / non-numeric.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private function px( $value ) {
		$value = trim( (string) $value );
		if ( '' === $value || ! is_numeric( $value ) ) {
			return '';
		}
		return absint( $value ) . 'px';
	}

	/**
	 * Clamp a 2..6 column value.
	 *
	 * @param mixed $value Raw value.
	 * @param int   $std   Fallback.
	 * @return int
	 */
	private function cols( $value, $std ) {
		$value = absint( $value );
		return ( $value >= 1 && $value <= 6 ) ? $value : $std;
	}

	/**
	 * {@inheritDoc}
	 */
	public function render( $atts, $content, $el_id ) {
		$items = array();
		if ( ! empty( $atts['items'] ) && function_exists( 'vc_param_group_parse_atts' ) ) {
			$items = vc_param_group_parse_atts( $atts['items'] );
		}
		if ( empty( $items ) || ! is_array( $items ) ) {
			return '';
		}

		$align  = in_array( $atts['align'], array( 'center', 'left', 'right' ), true ) ? $atts['align'] : 'center';
		$hover  = in_array( $atts['hover_effect'], array( 'color', 'zoom', 'lift', 'none' ), true ) ? $atts['hover_effect'] : 'color';
		$gray   = ( false !== strpos( (string) $atts['grayscale'], 'yes' ) );
		$justify = array(
			'center' => 'center',
			'left'   => 'flex-start',
			'right'  => 'flex-end',
		);

		// Skin via custom properties on the root.
		$opacity = max( 0, min( 100, absint( $atts['opacity'] ) ) );
		$vars    = array(
			'--cafw-lg-cols'    => $this->cols( $atts['columns'], 4 ),
			'--cafw-lg-cols-t'  => $this->cols( $atts['columns_tablet'], 3 ),
			'--cafw-lg-cols-m'  => $this->cols( $atts['columns_mobile'], 2 ),
			'--cafw-lg-gap'     => $this->px( $atts['gap'] ),
			'--cafw-lg-logo-h'  => $this->px( $atts['logo_height'] ),
			'--cafw-lg-opacity' => $opacity / 100,
			'--cafw-lg-justify' => $justify[ $align ],
			'--cafw-lg-pad'     => $this->px( $atts['cell_padding'] ),
			'--cafw-lg-radius'  => $this->px( $atts['cell_radius'] ),
		);
		$bg = sanitize_hex_color( $atts['cell_bg'] );
		if ( $bg ) {
			$vars['--cafw-lg-cell-bg'] = $bg;
		}
		$bw = absint( $atts['cell_border_width'] );
		$bc = sanitize_hex_color( $atts['cell_border_color'] );
		if ( $bw && $bc ) {
			$vars['--cafw-lg-cell-border'] = $bw . 'px solid ' . $bc;
		}
		$vars = array_filter(
			$vars,
			static function ( $v ) {
				return '' !== $v && null !== $v;
			}
		);

		$classes = array(
			'cafw-logo-grid',
			'cafw-logo-grid--hover-' . $hover,
		);
		if ( $gray ) {
			$classes[] = 'cafw-logo-grid--grayscale';
		}
		$dclass = CAFW_Element_Base::design_options_class( $atts );
		if ( $dclass ) {
			$classes[] = $dclass;
		}
		if ( '' !== trim( (string) $atts['el_class'] ) ) {
			$classes[] = $atts['el_class'];
		}

		ob_start();
		?>
		<div id="<?php echo esc_attr( $el_id ); ?>" class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>"<?php echo $this->style_attr( $vars ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- style_attr escapes internally. ?>>
			<?php
			foreach ( $items as $item ) {
				$img_id = isset( $item['image'] ) ? absint( $item['image'] ) : 0;
				$name   = isset( $item['name'] ) ? (string) $item['name'] : '';

				// Logo markup (real image, or a placeholder when none is set yet).
				if ( $img_id ) {
					$logo = wp_get_attachment_image(
						$img_id,
						'medium',
						false,
						array(
							'class' => 'cafw-logo-grid__img',
							'alt'   => $name,
						)
					);
				} else {
					$logo = '<span class="cafw-logo-grid__placeholder" aria-hidden="true">'
						. '<svg viewBox="0 0 132 36" width="120" height="33" xmlns="http://www.w3.org/2000/svg" fill="none"><circle cx="18" cy="18" r="14" stroke="currentColor" stroke-width="3"/><circle cx="18" cy="18" r="5.5" fill="currentColor"/><text x="44" y="25" font-family="Arial, Helvetica, sans-serif" font-size="19" font-weight="700" letter-spacing="1" fill="currentColor">LOGO</text></svg>'
						. '</span>';
				}

				// Optional link wrapper.
				$href = '';
				$tgt  = '';
				$rel  = '';
				if ( ! empty( $item['link'] ) && function_exists( 'vc_build_link' ) ) {
					$link = vc_build_link( $item['link'] );
					if ( ! empty( $link['url'] ) ) {
						$href = $link['url'];
						$tgt  = ! empty( $link['target'] ) ? trim( $link['target'] ) : '';
						$rel  = ! empty( $link['rel'] ) ? trim( $link['rel'] ) : '';
					}
				}

				$title = ( '' !== $name ) ? ' title="' . esc_attr( $name ) . '"' : '';
				?>
				<div class="cafw-logo-grid__item">
					<?php if ( $href ) : ?>
						<a class="cafw-logo-grid__link" href="<?php echo esc_url( $href ); ?>"<?php
						echo $tgt ? ' target="' . esc_attr( $tgt ) . '"' : '';
						echo $rel ? ' rel="' . esc_attr( $rel ) . '"' : '';
						echo $title; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- esc_attr'd above.
						?>><?php echo $logo; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_get_attachment_image / static SVG. ?></a>
					<?php else : ?>
						<span class="cafw-logo-grid__link"<?php echo $title; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- esc_attr'd above. ?>><?php echo $logo; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_get_attachment_image / static SVG. ?></span>
					<?php endif; ?>
				</div>
				<?php
			}
			?>
		</div>
		<?php
		return ob_get_clean();
	}
}
