<?php
/**
 * Brentwood Image Gallery — front-end render.
 *
 * A fixed "brick" grid (mirrors brentwood.ca/arts/dance): alternating columns of
 * two stacked images and one tall (2-row) image. Each filled slot is placed
 * explicitly via inline grid-column / grid-row computed from its ordinal; empty
 * editor slots are skipped here, so the front end is always gap-free.
 *
 * Each image is an <a> linking to its full-size file; bw-image-gallery-view
 * intercepts the click and opens a shared lightbox. With JS off the link still
 * opens the image. Images cover their cell (object-fit in CSS).
 *
 * @var array    $attributes Block attributes.
 * @var string   $content    Inner content (unused — dynamic block).
 * @var WP_Block $block      Block instance.
 */

defined( 'ABSPATH' ) || exit;

require_once get_stylesheet_directory() . '/inc/bw-gallery.php';

$slots = is_array( $attributes['images'] ?? null ) ? $attributes['images'] : array();

// Keep only filled slots (an editor slot with no image is skipped on the front end).
$filled = array();
foreach ( $slots as $img ) {
	if ( ! is_array( $img ) ) {
		continue;
	}
	if ( ( (int) ( $img['id'] ?? 0 ) > 0 ) || '' !== (string) ( $img['url'] ?? '' ) ) {
		$filled[] = $img;
	}
}
if ( empty( $filled ) ) {
	return;
}

$variant_raw = $attributes['variant'] ?? 'brick';
$variant     = in_array( $variant_raw, array( 'mosaic', 'single', 'feature' ), true ) ? $variant_raw : 'brick';
$columns = max( 1, min( 8, (int) ( $attributes['columns'] ?? 5 ) ) );
$gap     = max( 0, min( 60, (int) ( $attributes['gap'] ?? 8 ) ) );
$rowh    = max( 80, min( 600, (int) ( $attributes['rowHeight'] ?? 190 ) ) );
$radius  = max( 0, min( 80, (int) ( $attributes['borderRadius'] ?? 0 ) ) );

if ( 'mosaic' === $variant ) {
	$columns      = 3; // the mosaic feature pattern is defined for 3 columns
	$mosaic_tpl   = bw_gallery_mosaic_template();
	$filled_count = count( $filled );
} elseif ( 'feature' === $variant ) {
	$columns      = 3; // the feature pattern is defined for 3 columns
	$feature_tpl  = bw_gallery_feature_template();
	$filled_count = count( $filled );
} elseif ( 'single' === $variant ) {
	// Uniform grid: each image fills one cell on a black frame, kept whole
	// (object-fit:contain in CSS) so portraits keep their shape with letterboxing.
	$template = null;
} else {
	$template = bw_gallery_brick_template( $columns );
	$per      = count( $template );
}

// Single-variant frame ratio: 'auto' sizes each frame to its own image (like the
// live arts gallery — little/no letterbox); otherwise a fixed "<w> / <h>" ratio
// is applied to every frame via a CSS var on the wrapper.
$single_auto  = false;
$single_ratio = '';
if ( 'single' === $variant ) {
	$r = trim( (string) ( $attributes['singleRatio'] ?? '4 / 3' ) );
	if ( 'auto' === $r ) {
		$single_auto = true;
	} elseif ( preg_match( '/^[0-9]+(\.[0-9]+)?\s*\/\s*[0-9]+(\.[0-9]+)?$/', $r ) ) {
		$single_ratio = $r;
	} else {
		$single_ratio = '4 / 3';
	}
}

// Optional magnifying-glass hint (FontAwesome search-plus), shown bottom-right of
// every image to signal it opens in the lightbox — matches the live brentwood.ca
// photo "enlarge" icon. Static, so build it once.
$show_zoom = ! empty( $attributes['showZoom'] );
$zoom_html = $show_zoom
	? '<span class="bw-gallery__zoom" aria-hidden="true">'
		. '<svg viewBox="0 0 512 512" role="img" focusable="false"><path fill="currentColor" d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM184 296c0 13.3 10.7 24 24 24s24-10.7 24-24V232h64c13.3 0 24-10.7 24-24s-10.7-24-24-24H232V120c0-13.3-10.7-24-24-24s-24 10.7-24 24v64H120c-13.3 0-24 10.7-24 24s10.7 24 24 24h64v64z"></path></svg>'
		. '</span>'
	: '';

$items_html = '';
foreach ( $filled as $i => $img ) {
	if ( 'single' === $variant ) {
		$col_start = $col_end = $row_start = $row_end = 0; // auto-flow, no explicit placement
	} elseif ( 'mosaic' === $variant ) {
		$p         = bw_gallery_mosaic_position( $i, $mosaic_tpl, $filled_count );
		$col_start = $p['colStart'];
		$col_end   = $p['colEnd'];
		$row_start = $p['rowStart'];
		$row_end   = $p['rowEnd'];
	} elseif ( 'feature' === $variant ) {
		$p         = bw_gallery_feature_position( $i, $feature_tpl, $filled_count );
		$col_start = $p['colStart'];
		$col_end   = $p['colEnd'];
		$row_start = $p['rowStart'];
		$row_end   = $p['rowEnd'];
	} else {
		$pos       = bw_gallery_brick_position( $i, $template, $per );
		$col_start = $pos['col'];
		$col_end   = $pos['col'] + 1;
		$row_start = $pos['rowStart'];
		$row_end   = $pos['rowEnd'];
	}

	$id      = (int) ( $img['id'] ?? 0 );
	$alt     = isset( $img['alt'] ) ? (string) $img['alt'] : '';
	$caption = isset( $img['caption'] ) ? (string) $img['caption'] : '';

	// Thumbnail: a single high-resolution source (no srcset). object-fit:cover
	// scales it to the cell — letting the browser pick a small srcset candidate
	// (it sizes off the narrow cell WIDTH, ignoring the taller cell HEIGHT) made
	// it upscale and look blurry. A large source downscales cleanly instead.
	$src = '';
	if ( $id > 0 ) {
		$src = wp_get_attachment_image_url( $id, '1536x1536' );
		if ( ! $src ) { $src = wp_get_attachment_image_url( $id, 'large' ); }
		if ( ! $src ) { $src = wp_get_attachment_image_url( $id, 'full' ); }
		$full = wp_get_attachment_image_url( $id, 'full' );
		if ( '' === $alt ) {
			$alt = (string) get_post_meta( $id, '_wp_attachment_image_alt', true );
		}
	} else {
		$full = '';
	}
	if ( ! $src ) {
		$src = (string) ( $img['url'] ?? '' );
	}
	if ( '' === $src ) {
		continue;
	}
	if ( ! $full ) {
		$full = (string) ( $img['full'] ?? $img['url'] ?? '' );
	}
	if ( '' === $full ) {
		$full = $src;
	}

	$thumb = '<img class="bw-gallery__img" src="' . esc_url( $src ) . '" alt="' . esc_attr( $alt ) . '" loading="lazy" decoding="async" />';

	if ( 'single' === $variant ) {
		$style = '';
		// "Auto" ratio: set each frame's aspect-ratio from the image's real size.
		if ( $single_auto && $id > 0 ) {
			$dim = wp_get_attachment_image_src( $id, 'full' );
			if ( is_array( $dim ) && ! empty( $dim[1] ) && ! empty( $dim[2] ) ) {
				$style = 'aspect-ratio:' . (int) $dim[1] . ' / ' . (int) $dim[2] . ';';
			}
		}
	} else {
		$style = 'grid-column:' . $col_start . ' / ' . $col_end . ';grid-row:' . $row_start . ' / ' . $row_end . ';';
	}

	// Visible caption (bottom-left), shown when one is set.
	$caption_html = ( '' !== $caption )
		? '<span class="bw-gallery__caption">' . esc_html( $caption ) . '</span>'
		: '';
	// Lightbox label prefers the caption, then alt.
	$label        = ( '' !== $caption ) ? $caption : ( '' !== $alt ? $alt : 'View image' );
	$data_caption = ( '' !== $caption ) ? ' data-caption="' . esc_attr( $caption ) . '"' : '';

	$items_html .= '<a class="bw-gallery__item" style="' . esc_attr( $style ) . '" href="' . esc_url( $full ) . '" data-bw-lightbox' . $data_caption . ' aria-label="' . esc_attr( $label ) . '">'
		. $thumb // phpcs:ignore WordPress.Security.EscapeOutput -- wp_get_attachment_image / escaped fallback
		. $caption_html // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above
		. $zoom_html // phpcs:ignore WordPress.Security.EscapeOutput -- literal SVG markup
		. '</a>';
}

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

$style = '--bw-gallery-cols:' . $columns . ';--bw-gallery-gap:' . $gap . 'px;--bw-gallery-rowh:' . $rowh . 'px;';
if ( '' !== $single_ratio ) {
	$style .= '--bw-ig-ratio:' . $single_ratio . ';';
}
// "Full bleed" — single-variant images cover-crop (zoom to fill) instead of the
// default contain-on-black. Only meaningful with a fixed ratio (not Auto).
if ( 'single' === $variant && ! $single_auto && 'cover' === ( $attributes['singleFit'] ?? 'contain' ) ) {
	$style .= '--bw-ig-fit:cover;';
}
// Rounded bottom corners (like the live gallery's rounded-b-lg): the wrapper clips
// its corner images so the bottom-left/right images get the rounded corner.
$wrap_class = 'bw-gallery bw-gallery--' . $variant;
if ( $radius > 0 ) {
	$style     .= '--bw-gallery-radius:' . $radius . 'px;';
	$wrap_class .= ' bw-gallery--rounded';
}

printf(
	'<div %s>%s</div>',
	get_block_wrapper_attributes( array( 'class' => $wrap_class, 'style' => $style ) ), // phpcs:ignore WordPress.Security.EscapeOutput
	$items_html // phpcs:ignore WordPress.Security.EscapeOutput -- assembled from escaped parts above
);
