<?php
/**
 * Header Extras functionality.
 *
 * @package BricksExtras
 */

namespace BricksExtras;

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

if ( ! class_exists( 'BricksExtrasHelpers' ) ) {
	require_once 'BricksExtrasHelpers.php';
}

/**
 * Header Extras class for managing sticky and overlay header functionality.
 */
class HeaderExtras {

	/**
	 * Initialize header extras functionality.
	 *
	 * @return void
	 */
	public function init() {

		/* header */
		add_filter( 'bricks/header/attributes', array( $this, 'extras_header_attributes' ) );
		add_filter( 'builder/settings/page/controls_data', array( $this, 'extras_page_options' ) );
		add_filter( 'builder/settings/template/controls_data', array( $this, 'extras_template_options' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'extras_header' ) );
	}

	/**
	 * Add header extras options to page settings.
	 *
	 * @param array $data Page settings data.
	 * @return array Modified settings data.
	 */
	public function extras_page_options( $data ) {

		if ( null !== \Bricks\Templates::get_template_type() && 'content' !== \Bricks\Templates::get_template_type() ) {
			return $data;
		}

		return self::extras_header_builder_options( $data );
	}

	/**
	 * Add header extras options to template settings.
	 *
	 * @param array $data Template settings data.
	 * @return array Modified settings data.
	 */
	public function extras_template_options( $data ) {

		if ( \Bricks\Templates::get_template_type() === 'footer' ||
			\Bricks\Templates::get_template_type() === 'popup' ) {
			return $data;
		}

		return self::extras_header_builder_options( $data );
	}

	/**
	 * Build header extras control options for Bricks builder.
	 *
	 * @param array $data Builder control data.
	 * @return array Modified control data with header extras options.
	 */
	public static function extras_header_builder_options( $data ) {

		$data['controlGroups']['xHeaderGroup'] = array(
			'title' => 'Header Extras',
		);

		$data['controls']['xOverlayHeaderSep'] = array(
			'group'       => 'xHeaderGroup',
			'type'        => 'separator',
			'label'       => esc_html__( 'Overlay Header', 'bricksextras' ),
			'description' => esc_html__( 'Position the header over the top of the first section and remove header row background colors', 'bricksextras' ),
		);

		$breakpoint_options = array();

		foreach ( \Bricks\Breakpoints::$breakpoints as $breakpoint ) {
			$breakpoint_options[ $breakpoint['width'] ] = $breakpoint['label'] . ' ( > ' . ( intval( $breakpoint['width'] ) + 1 ) . 'px )';
		}

		$breakpoint_options['none']   = esc_html__( 'None', 'bricks' );
		$breakpoint_options['always'] = esc_html__( 'Always', 'bricks' );

		$data['controls']['xOverlayHeader'] = array(
			'group'       => 'xHeaderGroup',
			'type'        => 'select',
			'label'       => esc_html__( 'Breakpoint', 'bricks' ),
			'inline'      => true,
			'options'     => $breakpoint_options,
			'placeholder' => 'Default',
		);

		/* sticky header */

		$data['controls']['xHeaderZindex'] = array(
			'tab'    => 'content',
			'label'  => 'z-index',
			'type'   => 'number',
			'group'  => 'xHeaderGroup',
			'min'    => 0,
			'max'    => 1000,
			'inline' => true,
		);

		$data['controls']['xStickyHeaderSep'] = array(
			'group' => 'xHeaderGroup',
			'type'  => 'separator',
			'label' => esc_html__( 'Sticky header', 'bricks' ),
		);

		$data['controls']['xStickyHeaderScroll'] = array(
			'group'   => 'xHeaderGroup',
			'type'    => 'select',
			'inline'  => true,
			'small'   => true,
			'options' => array(
				'true'  => esc_html__( 'Enable', 'bricks' ),
				'false' => esc_html__( 'Disable', 'bricks' ),
			),
			'label'   => esc_html__( 'Enable', 'bricks' ),
		);

		$data['controls']['xStickyHeaderAbove'] = array(
			'group'       => 'xHeaderGroup',
			'type'        => 'select',
			'label'       => esc_html__( 'Breakpoint', 'bricks' ),
			'options'     => $breakpoint_options,
			'inline'      => true,
			'placeholder' => 'None',
			'required'    => array( 'xStickyHeaderScroll', '=', 'true' ),
		);

		$data['controls']['xStickyHeaderScrollDistance'] = array(
			'group'    => 'xHeaderGroup',
			'type'     => 'number',
			'label'    => esc_html__( 'Scroll distance', 'bricksextras' ) . ' (px)',
			'info'     => esc_html__( 'Distance scrolled down the page before header becomes sticky', 'bricksextras' ),
			'required' => array( 'xStickyHeaderScroll', '=', 'true' ),
		);

		$data['controls']['xStickyHeaderZindex'] = array(
			'group'       => 'xHeaderGroup',
			'type'        => 'number',
			'units'       => true,
			'label'       => esc_html__( 'Sticky z-index', 'bricks' ),
			'required'    => array( 'xStickyHeaderScroll', '=', 'true' ),
			'placeholder' => '999',
		);

			$data['controls']['xStickyHeaderFadeDuration'] = array(
				'group'    => 'xHeaderGroup',
				'type'     => 'number',
				'units'    => true,
				'label'    => esc_html__( 'Duration', 'bricks' ) . ' (' . esc_html__( 'Header', 'bricks' ) . ')',
				'required' => array( 'xStickyHeaderScroll', '=', 'true' ),
			);

			$data['controls']['xStickyHeaderTransitionDuration'] = array(
				'group'    => 'xHeaderGroup',
				'type'     => 'number',
				'units'    => true,
				'label'    => esc_html__( 'Duration', 'bricks' ) . ' (' . esc_html__( 'Header row', 'bricksextras' ) . ')',
				'required' => array( 'xStickyHeaderScroll', '=', 'true' ),
			);

			$data['controls']['xHideHeaderSep'] = array(
				'group'       => 'xHeaderGroup',
				'type'        => 'separator',
				'label'       => esc_html__( 'Hide Header', 'bricksextras' ),
				'description' => esc_html__( 'Hide the sticky header after scrolling a certain distance', 'bricksextras' ),
			);

			$data['controls']['xStickyHeaderHide'] = array(
				'group'   => 'xHeaderGroup',
				'type'    => 'select',
				'inline'  => true,
				'small'   => true,
				'options' => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'label'   => esc_html__( 'Hide header after scrolling', 'bricksextras' ),
			);

			$data['controls']['xStickyHeaderHideEffect'] = array(
				'group'    => 'xHeaderGroup',
				'type'     => 'select',
				'inline'   => true,
				'small'    => true,
				'options'  => array(
					'fade'    => esc_html__( 'Fade', 'bricks' ),
					'slideUp' => esc_html__( 'Slide up', 'bricksextras' ),
				),
				'label'    => esc_html__( 'Animation', 'bricks' ),
				'required' => array( 'xStickyHeaderHide', '=', 'true' ),
			);

			$data['controls']['xStickyHeaderHideDistance'] = array(
				'group'    => 'xHeaderGroup',
				'type'     => 'number',
				'label'    => esc_html__( 'Scroll distance', 'bricksextras' ) . ' (px)',
				'required' => array(
					array( 'xStickyHeaderHide', '=', 'true' ),
				),
			);

			$data['controls']['xStickyHeaderHideTollerance'] = array(
				'group'    => 'xHeaderGroup',
				'type'     => 'number',
				'label'    => esc_html__( 'Tolerance', 'bricksextras' ) . ' (px)',
				'required' => array(
					array( 'xStickyHeaderHide', '=', 'true' ),
				),
			);

			$data['controls']['xOverlayHeaderApply'] = array(
				'group'  => 'xHeaderGroup',
				'type'   => 'apply',
				'reload' => true,
				'label'  => esc_html__( 'Apply', 'bricks' ),
			);

			return $data;
	}

	/**
	 * Enqueue header extras styles and scripts.
	 *
	 * @return void
	 */
	public function extras_header() {

		/* overlay header */

		$breakpoint             = (bool) self::get_current_template_setting( 'xOverlayHeader' ) ? self::get_current_template_setting( 'xOverlayHeader' ) : 'none';
		$animation_transition   = (bool) self::get_current_template_setting( 'xStickyHeaderTransitionDuration' ) ? intval( self::get_current_template_setting( 'xStickyHeaderTransitionDuration' ) ) . 'ms' : '0';
		$fade_transition        = (bool) self::get_current_template_setting( 'xStickyHeaderFadeDuration' ) ? intval( self::get_current_template_setting( 'xStickyHeaderFadeDuration' ) ) . 'ms' : '0';
		$x_header_zindex        = (bool) self::get_current_template_setting( 'xHeaderZindex' ) ? intval( self::get_current_template_setting( 'xHeaderZindex' ) ) : '';
		$x_sticky_header_zindex = (bool) self::get_current_template_setting( 'xStickyHeaderZindex' ) ? intval( self::get_current_template_setting( 'xStickyHeaderZindex' ) ) : '999';

		$header_styles = '
			#brx-header {
				--x-header-transition: ' . $animation_transition . ';
				--x-header-fade-transition: ' . $fade_transition . ';
			}

			#brx-header.x-header_sticky-active {
				z-index: ' . $x_sticky_header_zindex . ';
			}
		';

		if ( '' !== $x_header_zindex ) {
			$header_styles .= '
				#brx-header {
					z-index: ' . $x_header_zindex . ';
				}
			';
		}

		wp_add_inline_style( 'bricks-frontend', $header_styles );

		$overlay_header_styles = "

			#brx-header {
				background: transparent;
				left: 0;
				right: 0;
				position: absolute;
				top: 0;
				--x-overlay-header-background: transparent;
				--x-header-position: overlay;
			}

			#brx-header[data-x-scroll='0']:not(.iframe #brx-header) {
				position: fixed;
			}

			#brx-header:not(.scrolling):not(.x-header_sticky-active) > .brxe-xheaderrow:not([data-x-sticky-active*=true]) {
				background: var(--x-overlay-header-background)!important;
			}

			#brx-header:not(.scrolling):not(.x-header_sticky-active) > .brxe-section {
				background: none!important;
			}

			.admin-bar #brx-header {
				top: var(--wp-admin--admin-bar--height);
			}

			#brx-header:not(.scrolling):not(.x-header_sticky-active) div.brxe-xheaderrow[data-x-overlay=hide]{
				display: none;
			}

			#brx-header .brxe-xheaderrow[data-x-overlay=show] {
				display: flex;
			}
		
		";

		/* apply at breakpoint */

		if ( (bool) $breakpoint && 'none' !== $breakpoint ) {

			$overlay_header_css  = '';
			$overlay_header_css .= 'always' !== $breakpoint ? ' @media only screen and (min-width: ' . ( intval( $breakpoint ) + 1 ) . 'px)  { ' : '';
			$overlay_header_css .= $overlay_header_styles;
			$overlay_header_css .= 'always' !== $breakpoint ? '}' : '';

			wp_add_inline_style( 'bricks-frontend', $overlay_header_css );

		}

		if ( 'true' === self::get_current_template_setting( 'xStickyHeaderScroll' ) ) {
			wp_enqueue_style( 'x-sticky-header', BRICKSEXTRAS_URL . 'components/assets/css/stickyheader.css', array(), '1.0.0' );
		}

		/* support boxed layouts */

		if ( 'true' === self::get_current_template_setting( 'xStickyHeaderScroll' ) || ( (bool) self::get_current_template_setting( 'xOverlayHeader' ) && 'none' !== self::get_current_template_setting( 'xOverlayHeader' ) ) ) {

			$boxed        = false;
			$header_width = '';

			$theme_site_layout = '';
			$theme_max_width   = '';

			if ( method_exists( '\Bricks\Theme_Styles', 'get_setting_by_key' ) ) {
				// Bricks 2.0+.
				$theme_site_layout = \Bricks\Theme_Styles::get_setting_by_key( 'general', 'siteLayout' );
				$theme_max_width   = \Bricks\Theme_Styles::get_setting_by_key( 'general', 'siteLayoutBoxedMaxWidth' );
			} elseif ( isset( \Bricks\Theme_Styles::$active_settings['general'] ) ) {
				// Bricks pre-2.0.
				$theme_site_layout = \Bricks\Theme_Styles::$active_settings['general']['siteLayout'] ?? '';
				$theme_max_width   = \Bricks\Theme_Styles::$active_settings['general']['siteLayoutBoxedMaxWidth'] ?? '';
			}

			if ( 'boxed' === $theme_site_layout ) {
				$boxed = true;
			}

			if ( ! empty( \Bricks\Database::$page_settings['siteLayout'] ) ) {
				if ( 'boxed' === \Bricks\Database::$page_settings['siteLayout'] ) {
					$boxed = true;
				} elseif ( 'wide' === \Bricks\Database::$page_settings['siteLayout'] ) {
					$boxed = false;
				}
			}

			if ( ! empty( $theme_max_width ) ) {
				$header_width = $theme_max_width;
			}

			if ( ! empty( \Bricks\Database::$page_settings['siteLayoutBoxedMaxWidth'] ) ) {
				$header_width = \Bricks\Database::$page_settings['siteLayoutBoxedMaxWidth'];
			}

			if ( is_numeric( $header_width ) ) {
				$header_width = $header_width . 'px';
			}

			if ( $boxed ) {

				echo '<style>
				.brx-boxed #brx-header,
				.brx-boxed #brx-header.x-header_sticky-active {
					left: auto;
					right: auto;
					max-width: ' . esc_attr( $header_width ) . ';
				}
				</style>';

			}
		}
	}

	/**
	 * Modify header attributes for sticky and overlay functionality.
	 *
	 * @param array $attributes Header element attributes.
	 * @return array Modified attributes.
	 */
	public function extras_header_attributes( $attributes ) {

		/* sticky header */

		if ( 'true' === self::get_current_template_setting( 'xStickyHeaderScroll' ) ) {

			// Add sticky header classes.
			if ( isset( $attributes['class'] ) && is_array( $attributes['class'] ) ) {
				$attributes['class'][] = 'x-header_sticky';
			} else {
				$attributes['class'] = array( 'x-header_sticky' );
			}

			$attributes['data-x-scroll']      = self::get_current_template_setting( 'xStickyHeaderScrollDistance' ) ? esc_attr( self::get_current_template_setting( 'xStickyHeaderScrollDistance' ) ) : 0;
			$attributes['data-x-break']       = self::get_current_template_setting( 'xStickyHeaderAbove' ) ? intval( self::get_current_template_setting( 'xStickyHeaderAbove' ) ) + 1 : 'none';
			$attributes['data-x-hide-effect'] = self::get_current_template_setting( 'xStickyHeaderHideEffect' ) ? esc_attr( self::get_current_template_setting( 'xStickyHeaderHideEffect' ) ) : 'slideUp';

			/* hide header */

			if ( 'true' === self::get_current_template_setting( 'xStickyHeaderHide' ) ) {

				$attributes['data-x-header-hide']       = self::get_current_template_setting( 'xStickyHeaderHideDistance' ) ? esc_attr( self::get_current_template_setting( 'xStickyHeaderHideDistance' ) ) : 0;
				$attributes['data-x-header-tollerance'] = self::get_current_template_setting( 'xStickyHeaderHideTollerance' ) ? esc_attr( self::get_current_template_setting( 'xStickyHeaderHideTollerance' ) ) : 0;
				wp_enqueue_script( 'x-headroom', BRICKSEXTRAS_URL . 'components/assets/js/headroom.min.js', array( 'bricks-scripts' ), '0.12.0', true );
				wp_enqueue_script( 'x-hide-header', BRICKSEXTRAS_URL . 'components/assets/js/' . Helpers::maybe_minify_scripts( 'hideheader' ) . '.js', array( 'x-headroom' ), \BricksExtras\Plugin::VERSION, true );

			}

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

		}

		$overlay_header_attr = (bool) self::get_current_template_setting( 'xOverlayHeader' ) ? self::get_current_template_setting( 'xOverlayHeader' ) : 'none';

		if ( is_numeric( $overlay_header_attr ) ) {
			++$overlay_header_attr;
		}

		$attributes['data-x-overlay'] = esc_attr( $overlay_header_attr );

		return $attributes;
	}

	/**
	 * Get most relevant setting from template settings or overriding page settings currently active
	 *
	 * @param string $key     Setting key to retrieve.
	 * @param mixed  $default_value Default value if not found.
	 * @return mixed Setting value or default.
	 */
	private static function get_current_template_setting( string $key, $default_value = false ) {

		$header_setting  = \Bricks\Database::$active_templates['header'] ? \Bricks\Helpers::get_template_setting( $key, \Bricks\Database::$active_templates['header'] ) : false;
		$content_setting = \Bricks\Database::$active_templates['content'] ? \Bricks\Helpers::get_template_setting( $key, \Bricks\Database::$active_templates['content'] ) : false;
		$page_setting    = \Bricks\Database::$page_settings[ $key ] ?? false;

		if ( isset( \Bricks\Database::$page_settings[ $key ] ) || array_key_exists( $key, \Bricks\Database::$page_settings ) ) {
			return $page_setting;
		} elseif ( (bool) $content_setting ) {
			return $content_setting;
		} elseif ( (bool) $header_setting ) {
			return $header_setting;
		} else {
			return $default_value;
		}
	}
}
