<?php
/**
 * [bw_subnav] — sticky section sub-navigation bar, mirroring the bar on
 * brentwood.ca inner pages (e.g. /why-brentwood/choice).
 *
 * Which menu appears is configured per page in the page editor ("Sub Nav"
 * box in the sidebar), using ordinary WordPress menus (Appearance → Menus)
 * so the bar can hold any mix of pages, custom ordering, and external
 * links — it is NOT auto-generated from child pages.
 *
 * Two settings per page:
 *   - "Sub nav on this page":  Default (inherit from parent section),
 *     Hide, Breadcrumb, or a specific menu.
 *   - "Sub nav for child pages": set this on a section parent (e.g.
 *     Why Brentwood) and every descendant shows that menu automatically —
 *     while the parent page itself shows nothing, like the live site.
 *     Descendants can still override or hide it via their own setting.
 *
 * Breadcrumb mode (either setting): instead of a menu strip the bar shows
 * a breadcrumb trail — ancestor page links, then the current page in bold —
 * for sections with too many child pages to list flat (e.g. Athletics,
 * matching brentwood.ca/athletics/facilities). Labels use the raw page
 * titles, not the long Title Override headlines.
 *
 * Intended to be placed site-wide via a Kadence Element — it renders
 * nothing on pages with no menu resolved, so it's safe to hook globally.
 *
 * Only top-level menu items are rendered (the bar is a flat strip);
 * nested items in the chosen menu are ignored.
 *
 * Shortcode attributes:
 *   top    Sticky offset from the top of the viewport. Default "auto":
 *          a small script keeps the bar pinned to the bottom edge of
 *          #masthead, which handles Kadence transparent headers (the
 *          header overlays the page top, so a bar at top:0 would sit
 *          behind it) and sticky headers (the offset follows the header
 *          as it shrinks/sticks on scroll). Pass a CSS length (e.g.
 *          top="36px") to pin it at a fixed offset instead.
 *   class  Extra CSS class(es) on the container.
 *
 * Item labels are read from the menu item's own label, falling back to
 * the linked page's raw post_title — never through the_title — because
 * the bw-dev Title Override filters the_title for the queried page and
 * we don't want the long H1 headline in navigation (see
 * brentwood_nav_menu_label() in functions.php for the same issue in the
 * main menu).
 *
 * @package Kadence-Child
 */

const BW_SUBNAV_META_SELF     = '_bw_subnav_menu';
const BW_SUBNAV_META_CHILDREN = '_bw_subnav_children_menu';
// Sentinel stored in either meta: show a breadcrumb trail instead of a menu.
// For sections with too many children for a flat strip (e.g. Athletics).
const BW_SUBNAV_BREADCRUMB    = -2;

/* -------------------------------------------------------------------------
 * Page settings (meta box)
 * ---------------------------------------------------------------------- */

function bw_subnav_add_meta_box() {
	// Pages (hierarchical) and Landing Pages (flat CPT) both get the box. On
	// Landing the bar is driven by picking a menu directly — see the meta box
	// and bw_subnav_resolve_menu(), which degrade gracefully with no ancestors.
	add_meta_box(
		'bw-subnav',
		__( 'Sub Nav', 'kadence-child' ),
		'bw_subnav_render_meta_box',
		array( 'page', 'landing' ),
		'side',
		'default'
	);
}
add_action( 'add_meta_boxes', 'bw_subnav_add_meta_box' );

function bw_subnav_render_meta_box( $post ) {
	wp_nonce_field( 'bw_subnav_save', 'bw_subnav_nonce' );

	$menus    = wp_get_nav_menus();
	$self     = (int) get_post_meta( $post->ID, BW_SUBNAV_META_SELF, true );
	$children = (int) get_post_meta( $post->ID, BW_SUBNAV_META_CHILDREN, true );
	?>
	<p>
		<label for="bw-subnav-self"><strong><?php esc_html_e( 'Sub nav on this page', 'kadence-child' ); ?></strong></label><br>
		<select id="bw-subnav-self" name="bw_subnav_self" style="width:100%">
			<option value="0" <?php selected( $self, 0 ); ?>><?php esc_html_e( 'Default (inherit from parent section)', 'kadence-child' ); ?></option>
			<option value="-1" <?php selected( $self, -1 ); ?>><?php esc_html_e( 'Hide — no sub nav on this page', 'kadence-child' ); ?></option>
			<option value="-2" <?php selected( $self, -2 ); ?>><?php esc_html_e( 'Breadcrumb — show a breadcrumb trail instead', 'kadence-child' ); ?></option>
			<?php foreach ( $menus as $menu ) : ?>
				<option value="<?php echo esc_attr( $menu->term_id ); ?>" <?php selected( $self, $menu->term_id ); ?>><?php echo esc_html( $menu->name ); ?></option>
			<?php endforeach; ?>
		</select>
	</p>
	<?php // "For child pages" only makes sense on hierarchical types. Landing
	// Pages are flat, so they resolve their bar solely from the setting above. ?>
	<?php if ( is_post_type_hierarchical( $post->post_type ) ) : ?>
	<p>
		<label for="bw-subnav-children"><strong><?php esc_html_e( 'Sub nav for child pages', 'kadence-child' ); ?></strong></label><br>
		<select id="bw-subnav-children" name="bw_subnav_children" style="width:100%">
			<option value="0" <?php selected( $children, 0 ); ?>><?php esc_html_e( 'None', 'kadence-child' ); ?></option>
			<option value="-2" <?php selected( $children, -2 ); ?>><?php esc_html_e( 'Breadcrumb — child pages show a breadcrumb trail', 'kadence-child' ); ?></option>
			<?php foreach ( $menus as $menu ) : ?>
				<option value="<?php echo esc_attr( $menu->term_id ); ?>" <?php selected( $children, $menu->term_id ); ?>><?php echo esc_html( $menu->name ); ?></option>
			<?php endforeach; ?>
		</select>
	</p>
	<p class="description">
		<?php esc_html_e( 'Set "for child pages" on a section parent (e.g. Why Brentwood) and every page below it shows that menu — the parent itself stays without a bar. A child page can override or hide it with its own setting. Pick "Breadcrumb" for sections with too many pages for a menu strip (e.g. Athletics). Manage the menus under Appearance → Menus.', 'kadence-child' ); ?>
	</p>
	<?php else : ?>
	<p class="description">
		<?php esc_html_e( 'Pick a menu above to show a sub nav bar on this landing page. Manage the menus under Appearance → Menus.', 'kadence-child' ); ?>
	</p>
	<?php endif; ?>
	<?php
}

function bw_subnav_save_meta( $post_id ) {
	if ( ! isset( $_POST['bw_subnav_nonce'] )
		|| ! wp_verify_nonce( $_POST['bw_subnav_nonce'], 'bw_subnav_save' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	foreach ( array(
		'bw_subnav_self'     => BW_SUBNAV_META_SELF,
		'bw_subnav_children' => BW_SUBNAV_META_CHILDREN,
	) as $field => $meta_key ) {
		if ( ! isset( $_POST[ $field ] ) ) {
			continue;
		}
		$value = (int) $_POST[ $field ];
		if ( 0 === $value ) {
			delete_post_meta( $post_id, $meta_key );
		} else {
			update_post_meta( $post_id, $meta_key, $value );
		}
	}
}
add_action( 'save_post_page', 'bw_subnav_save_meta' );
add_action( 'save_post_landing', 'bw_subnav_save_meta' );

/* -------------------------------------------------------------------------
 * Menu resolution + rendering
 * ---------------------------------------------------------------------- */

/**
 * What should this page show? 0 = none, BW_SUBNAV_BREADCRUMB = breadcrumb
 * trail, otherwise a menu term_id.
 *
 * Own setting wins (a menu, breadcrumb, or -1 to hide); otherwise the
 * nearest ancestor with a "for child pages" setting provides it.
 */
function bw_subnav_resolve_menu( $page ) {
	$self = (int) get_post_meta( $page->ID, BW_SUBNAV_META_SELF, true );
	if ( -1 === $self ) {
		return 0;
	}
	if ( BW_SUBNAV_BREADCRUMB === $self ) {
		return BW_SUBNAV_BREADCRUMB;
	}
	if ( $self > 0 && wp_get_nav_menu_object( $self ) ) {
		return $self;
	}
	foreach ( get_post_ancestors( $page ) as $ancestor_id ) { // nearest first
		$menu = (int) get_post_meta( $ancestor_id, BW_SUBNAV_META_CHILDREN, true );
		if ( BW_SUBNAV_BREADCRUMB === $menu ) {
			return BW_SUBNAV_BREADCRUMB;
		}
		if ( $menu > 0 && wp_get_nav_menu_object( $menu ) ) {
			return $menu;
		}
	}
	return 0;
}

/**
 * Menu item label from raw titles, bypassing the_title (Title Override).
 */
function bw_subnav_item_label( $item ) {
	if ( '' !== (string) $item->post_title ) {
		return wptexturize( $item->post_title );
	}
	if ( 'post_type' === $item->type && ! empty( $item->object_id ) ) {
		$original = get_post( (int) $item->object_id );
		if ( $original instanceof WP_Post ) {
			return wptexturize( $original->post_title );
		}
	}
	return $item->title;
}

function bw_subnav_shortcode( $atts ) {
	$atts = shortcode_atts(
		array(
			'top'   => 'auto',
			'class' => '',
		),
		$atts,
		'bw_subnav'
	);

	// Pages and single Landing Pages both render the bar; every other context
	// (posts, archives, CPTs without this box) shows nothing.
	if ( ! is_page() && ! is_singular( 'landing' ) ) {
		return '';
	}

	$current = get_post( get_queried_object_id() );
	if ( ! $current instanceof WP_Post ) {
		return '';
	}

	$menu_id = bw_subnav_resolve_menu( $current );
	if ( ! $menu_id ) {
		return '';
	}

	$is_breadcrumb = ( BW_SUBNAV_BREADCRUMB === $menu_id );

	$items = array();
	if ( ! $is_breadcrumb ) {
		$items = wp_get_nav_menu_items( $menu_id );
		if ( empty( $items ) ) {
			return '';
		}
		// Flat strip: top-level items only.
		$items = array_filter(
			$items,
			function ( $item ) {
				return empty( $item->menu_item_parent );
			}
		);
		if ( empty( $items ) ) {
			return '';
		}
	}

	// Shared stylesheet, emitted once per page render.
	static $printed_style = false;
	$style = '';
	if ( ! $printed_style ) {
		$printed_style = true;
		$style = '<style id="bw-subnav-style">'
			. '.bw-subnav{display:none;position:sticky;z-index:10;align-items:center;'
			. 'max-width:80rem;width:100%;margin:0 auto;padding:4px 0;background:#fff;'
			. 'border-left:2px solid var(--global-palette1);'
			. 'border-bottom-right-radius:.25rem;'
			. 'box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px rgba(0,0,0,.06);}'
			. '@media (min-width:768px){.bw-subnav{display:flex;}}'
			. '@media print{.bw-subnav{display:none !important;}}'
			. '.bw-subnav__chevron{width:1rem;margin-left:.5rem;flex-shrink:0;'
			. 'color:var(--global-palette1);}'
			. '.bw-subnav__chevron svg{display:block;width:.65em;height:1em;margin:0 auto;}'
			. '.bw-subnav__links{display:flex;flex-wrap:wrap;align-items:center;}'
			. '.bw-subnav__link{display:inline-block;margin:0 .75rem;padding:2px .5rem 0;'
			. 'margin-bottom:-2px;border-bottom:1px solid transparent;font-weight:400;'
			. 'color:var(--global-palette1);text-decoration:none;}'
			. '.bw-subnav__link:hover,.bw-subnav__link:focus{'
			. 'color:var(--global-palette1);'
			. 'border-bottom-color:var(--global-palette1);}'
			. '.bw-subnav__link.sub-page-active{font-weight:700;'
			. 'border-bottom-color:transparent;}'
			. '.bw-subnav__crumb-sep{flex-shrink:0;color:var(--global-palette1);}'
			. '.bw-subnav__crumb-sep svg{display:block;width:.5em;height:.9em;}'
			. '</style>';
	}

	$auto_top = 'auto' === strtolower( trim( $atts['top'] ) );

	$out = '<div class="bw-subnav sub-menu-container'
		. ( $atts['class'] ? ' ' . esc_attr( $atts['class'] ) : '' ) . '"'
		. ( $auto_top
			? ' data-autotop="1"'
			: ' style="top:' . esc_attr( $atts['top'] ) . '"' )
		. '>';

	// FontAwesome "angle-right" solid icon — same path as brentwood.ca.
	$chevron_svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" '
		. 'role="img" focusable="false">'
		. '<path fill="currentColor" d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 '
		. '160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5'
		. '-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"></path></svg>';

	$out .= '<div class="bw-subnav__chevron" aria-hidden="true">' . $chevron_svg . '</div>';

	if ( $is_breadcrumb ) {
		// Breadcrumb trail: ancestor links, then the current page bold.
		// Raw post_title throughout — never the_title — so the bw-dev Title
		// Override's long headline can't bloat the trail.
		$sep = '<span class="bw-subnav__crumb-sep" aria-hidden="true">' . $chevron_svg . '</span>';

		$out .= '<div class="bw-subnav__links bw-subnav__crumbs">';
		$first = true;
		foreach ( array_reverse( get_post_ancestors( $current ) ) as $ancestor_id ) { // root first
			$ancestor = get_post( $ancestor_id );
			if ( ! $ancestor instanceof WP_Post ) {
				continue;
			}
			if ( ! $first ) {
				$out .= $sep;
			}
			$first = false;
			$out .= '<a href="' . esc_url( get_permalink( $ancestor ) ) . '" '
				. 'class="bw-subnav__link menu-sub-page-link">'
				. esc_html( wptexturize( $ancestor->post_title ) ) . '</a>';
		}
		if ( ! $first ) {
			$out .= $sep;
		}
		$out .= '<span class="bw-subnav__link sub-page-active" aria-current="page">'
			. esc_html( wptexturize( $current->post_title ) ) . '</span>';
		$out .= '</div></div>';
	} else {
		// The current page and its ancestors stay highlighted.
		$active_ids   = get_post_ancestors( $current );
		$active_ids[] = $current->ID;
		$current_url  = untrailingslashit( (string) get_permalink( $current ) );

		$out .= '<div class="bw-subnav__links">';
		foreach ( $items as $item ) {
			$is_current = false;
			$is_active  = false;
			if ( 'post_type' === $item->type && ! empty( $item->object_id ) ) {
				$is_current = (int) $item->object_id === $current->ID;
				$is_active  = $is_current || in_array( (int) $item->object_id, $active_ids, true );
			} elseif ( ! empty( $item->url ) ) {
				$is_current = untrailingslashit( $item->url ) === $current_url;
				$is_active  = $is_current;
			}
			$target = ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) . '" rel="noopener"' : '';
			$out .= '<a href="' . esc_url( $item->url ) . '" '
				. 'class="bw-subnav__link menu-sub-page-link'
				. ( $is_active ? ' sub-page-active' : '' ) . '"'
				. ( $is_current ? ' aria-current="page"' : '' ) . $target . '>'
				. esc_html( bw_subnav_item_label( $item ) ) . '</a>';
		}
		$out .= '</div></div>';
	}

	// Auto-top: pin the bar to the bottom edge of #masthead so it clears
	// transparent/sticky Kadence headers. Emitted once per page render.
	static $printed_script = false;
	if ( $auto_top && ! $printed_script ) {
		$printed_script = true;
		$out .= '<script id="bw-subnav-autotop">(function(){'
			. 'var bars=document.querySelectorAll(".bw-subnav[data-autotop]");'
			. 'if(!bars.length)return;'
			. 'function update(){'
			. 'var m=document.getElementById("masthead"),t=0;'
			. 'if(m){t=Math.max(0,m.getBoundingClientRect().bottom);}'
			. 'bars.forEach(function(b){b.style.top=t+"px";});'
			. '}'
			. 'var ticking=false;'
			. 'function queue(){if(!ticking){ticking=true;'
			. 'requestAnimationFrame(function(){ticking=false;update();});}}'
			. 'window.addEventListener("scroll",queue,{passive:true});'
			. 'window.addEventListener("resize",queue);'
			. 'window.addEventListener("load",update);'
			. 'update();'
			. '})();</script>';
	}

	return $style . $out;
}
add_shortcode( 'bw_subnav', 'bw_subnav_shortcode' );
