<?php
/**
 * Spectra - Icon
 *
 * @since 2.12.5
 * @package UAGB
 */

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

if ( ! class_exists( 'Spectra_Icon' ) ) {

	/**
	 * Class Spectra_Icon.
	 * 
	 * @since 2.12.5
	 */
	final class Spectra_Icon {

		/**
		 * Member Variable
		 *
		 * @since 2.12.5
		 * @var Spectra_Icon
		 */
		private static $instance;

		/**
		 *  Initiator
		 *
		 * @since 2.12.5
		 * @return Spectra_Icon
		 */
		public static function get_instance() {
			if ( null === self::$instance ) {
				self::$instance = new self();
			}
			return self::$instance;
		}

		/**
		 * Constructor
		 * 
		 * @since 2.12.5
		 */
		public function __construct() {
			add_action( 'init', array( $this, 'register_icon' ) );
			
		}

		/**
		 * Registers the `icon` block on server.
		 *
		 * @since 2.12.5
		 * @return void
		 */
		public function register_icon() {
			// Check if the register function exists.
			if ( ! function_exists( 'register_block_type' ) ) {
				return;
			}

			$icon_border_attributes = array();
			$icon_border_attributes = UAGB_Block_Helper::uag_generate_php_border_attribute( 'icon' ); // @phpstan-ignore-line
				
			register_block_type(
				'uagb/icon',
				array(
					'attributes'      => array_merge(
						array(
							'icon'           => array(
								'type'    => 'string',
								'default' => 'circle-check',
							),
							// Size.
							'iconSize'       => array(
								'type'    => 'number',
								'default' => 40,
							),
							'iconSizeTablet' => array(
								'type' => 'number',
							),
							'iconSizeMobile' => array(
								'type' => 'number',
							),
							'iconSizeUnit'   => array(
								'type'    => 'string',
								'default' => 'px',
							),
						),
						// Alignment.
						array(
							'align'       => array(
								'type'    => 'string',
								'default' => 'center',
							),
							'alignTablet' => array(
								'type'    => 'string',
								'default' => '',
							),
							'alignMobile' => array(
								'type'    => 'string',
								'default' => '',
							),
						),
						// Color.
						array(
							'iconColor'                    => array(
								'type'    => 'string',
								'default' => '#333',
							),
							'iconBorderColor'              => array(
								'type'    => 'string',
								'default' => '',
							),
							'iconBackgroundColorType'      => array(
								'type'    => 'string',
								'default' => 'classic',
							),
							'iconBackgroundColor'          => array(
								'type'    => 'string',
								'default' => '',
							),
							'iconBackgroundGradientColor'  => array(
								'type'    => 'string',
								'default' => 'linear-gradient(90deg, rgb(155, 81, 224) 0%, rgb(6, 147, 227) 100%)',
							),
							'iconHoverColor'               => array(
								'type'    => 'string',
								'default' => '',
							),
							'iconHoverBackgroundColorType' => array(
								'type'    => 'string',
								'default' => 'classic',
							),
							'iconHoverBackgroundColor'     => array(
								'type' => 'string',
							),
							'iconHoverBackgroundGradientColor' => array(
								'type'    => 'string',
								'default' => 'linear-gradient(90deg, rgb(155, 81, 224) 0%, rgb(6, 147, 227) 100%)',
							),
						),
						// Rotation.
						array(
							'rotation'     => array(
								'type'    => 'number',
								'default' => 0,
							),
							'rotationUnit' => array(
								'type'    => 'string',
								'default' => 'deg',
							),
							'block_id'     => array(
								'type' => 'string',
							),
						),
						// Link related attributes.
						array(
							'link'                  => array(
								'type'    => 'string',
								'default' => '',
							),
							'target'                => array(
								'type'    => 'boolean',
								'default' => false,
							),
							'disableLink'           => array(
								'type'    => 'boolean',
								'default' => false,
							),
							'iconAccessabilityMode' => array(
								'type'    => 'string',
								'default' => 'svg',
							),
							'iconAccessabilityDesc' => array(
								'type'    => 'string',
								'default' => '',
							),
						),
						// Padding.
						array(
							'iconTopPadding'          => array(
								'type'    => 'number',
								'default' => 5,
							),
							'iconRightPadding'        => array(
								'type'    => 'number',
								'default' => 5,
							),
							'iconLeftPadding'         => array(
								'type'    => 'number',
								'default' => 5,
							),
							'iconBottomPadding'       => array(
								'type'    => 'number',
								'default' => 5,
							),
							'iconTopTabletPadding'    => array(
								'type' => 'number',
							),
							'iconRightTabletPadding'  => array(
								'type' => 'number',
							),
							'iconLeftTabletPadding'   => array(
								'type' => 'number',
							),
							'iconBottomTabletPadding' => array(
								'type' => 'number',
							),
							'iconTopMobilePadding'    => array(
								'type' => 'number',
							),
							'iconRightMobilePadding'  => array(
								'type' => 'number',
							),
							'iconLeftMobilePadding'   => array(
								'type' => 'number',
							),
							'iconBottomMobilePadding' => array(
								'type' => 'number',
							),
							'iconPaddingUnit'         => array(
								'type'    => 'string',
								'default' => 'px',
							),
							'iconTabletPaddingUnit'   => array(
								'type'    => 'string',
								'default' => 'px',
							),
							'iconMobilePaddingUnit'   => array(
								'type'    => 'string',
								'default' => 'px',
							),
							'iconPaddingLink'         => array(
								'type'    => 'boolean',
								'default' => false,
							),
						),
						// Margin.
						array(
							'iconTopMargin'              => array(
								'type' => 'number',
							),
							'iconRightMargin'            => array(
								'type' => 'number',
							),
							'iconLeftMargin'             => array(
								'type' => 'number',
							),
							'iconBottomMargin'           => array(
								'type' => 'number',
							),
							'iconTopTabletMargin'        => array(
								'type' => 'number',
							),
							'iconRightTabletMargin'      => array(
								'type' => 'number',
							),
							'iconLeftTabletMargin'       => array(
								'type' => 'number',
							),
							'iconBottomTabletMargin'     => array(
								'type' => 'number',
							),
							'iconTopMobileMargin'        => array(
								'type' => 'number',
							),
							'iconRightMobileMargin'      => array(
								'type' => 'number',
							),
							'iconLeftMobileMargin'       => array(
								'type' => 'number',
							),
							'iconBottomMobileMargin'     => array(
								'type' => 'number',
							),
							'iconMarginUnit'             => array(
								'type'    => 'string',
								'default' => 'px',
							),
							'iconTabletMarginUnit'       => array(
								'type'    => 'string',
								'default' => 'px',
							),
							'iconMobileMarginUnit'       => array(
								'type'    => 'string',
								'default' => 'px',
							),
							'iconMarginLink'             => array(
								'type'    => 'boolean',
								'default' => false,
							),
							'isPreview'                  => array(
								'type'    => 'boolean',
								'default' => false,
							),
							'iconBorderStyle'            => array(
								'type'    => 'string',
								'default' => 'default',
							),
							'useSeparateBoxShadows'      => array(
								'type'    => 'boolean',
								'default' => true,
							),
							'iconShadowColor'            => array(
								'type'    => 'string',
								'default' => '#00000070',
							),
							'iconShadowHOffset'          => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconShadowVOffset'          => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconShadowBlur'             => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconBoxShadowColor'         => array(
								'type'    => 'string',
								'default' => '#00000070',
							),
							'iconBoxShadowHOffset'       => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconBoxShadowVOffset'       => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconBoxShadowBlur'          => array(
								'type' => 'number',
							),
							'iconBoxShadowSpread'        => array(
								'type' => 'number',
							),
							'iconBoxShadowPosition'      => array(
								'type'    => 'string',
								'default' => 'outset',
							),
							'iconShadowColorHover'       => array(
								'type'    => 'string',
								'default' => '#00000070',
							),
							'iconShadowHOffsetHover'     => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconShadowVOffsetHover'     => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconShadowBlurHover'        => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconBoxShadowColorHover'    => array(
								'type' => 'string',
							),
							'iconBoxShadowHOffsetHover'  => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconBoxShadowVOffsetHover'  => array(
								'type'    => 'number',
								'default' => 0,
							),
							'iconBoxShadowBlurHover'     => array(
								'type' => 'number',
							),
							'iconBoxShadowSpreadHover'   => array(
								'type' => 'number',
							),
							'iconBoxShadowPositionHover' => array(
								'type'    => 'string',
								'default' => 'outset',
							),
						),
						// Responsive Borders.
						$icon_border_attributes
					),
					'render_callback' => array( $this, 'render_uagb_icon' ),
				)
			);
	  
			
		}

		/**
		 * Check if a URL has a protocol (http/https).
		 *
		 * @since 2.12.5
		 * 
		 * @param string $url The URL to check.
		 * @return bool Whether the URL has a protocol.
		 */
		public static function get_protocol( $url ) {
			$urlParts = wp_parse_url( $url );

			if ( is_array( $urlParts ) ) {
				return isset( $urlParts['scheme'] );
			}
			return false;
		}

		/**
		 * Prepend 'http://' to a URL if it doesn't have a protocol.
		 *
		 * @since 2.12.5
		 * 
		 * @param string $url The URL to prepend 'http://' to.
		 * @return string The modified URL.
		 */
		public static function prepend_http( $url ) {
			return ( ! empty( $url ) && ! self::get_protocol( $url ) ) ? 'http://' . $url : $url;
		}


		/**
		 * Renders the icon block.
		 *
		 * @param array $attributes Array of block attributes.
		 *
		 * @since 2.12.5
		 * @return string|false
		 */
		public function render_uagb_icon( $attributes ) {
			
			$block_id               = 'uagb-block-' . $attributes['block_id'];
			$iconBottomMargin       = isset( $attributes['iconBottomMargin'] ) ? $attributes['iconBottomMargin'] : '';
			$iconLeftMargin         = isset( $attributes['iconLeftMargin'] ) ? $attributes['iconLeftMargin'] : '';
			$iconRightMargin        = isset( $attributes['iconRightMargin'] ) ? $attributes['iconRightMargin'] : '';
			$iconTopMargin          = isset( $attributes['iconTopMargin'] ) ? $attributes['iconTopMargin'] : '';
			$iconBottomTabletMargin = isset( $attributes['iconBottomTabletMargin'] ) ? $attributes['iconBottomTabletMargin'] : '';
			$iconLeftTabletMargin   = isset( $attributes['iconLeftTabletMargin'] ) ? $attributes['iconLeftTabletMargin'] : '';
			$iconRightTabletMargin  = isset( $attributes['iconRightTabletMargin'] ) ? $attributes['iconRightTabletMargin'] : '';
			$iconTopTabletMargin    = isset( $attributes['iconTopTabletMargin'] ) ? $attributes['iconTopTabletMargin'] : '';
			$iconBottomMobileMargin = isset( $attributes['iconBottomMobileMargin'] ) ? $attributes['iconBottomMobileMargin'] : '';
			$iconLeftMobileMargin   = isset( $attributes['iconLeftMobileMargin'] ) ? $attributes['iconLeftMobileMargin'] : '';
			$iconRightMobileMargin  = isset( $attributes['iconRightMobileMargin'] ) ? $attributes['iconRightMobileMargin'] : '';
			$iconTopMobileMargin    = isset( $attributes['iconTopMobileMargin'] ) ? $attributes['iconTopMobileMargin'] : '';
			$margin_variables       = array( $iconBottomMargin, $iconLeftMargin, $iconRightMargin, $iconTopMargin, $iconBottomTabletMargin, $iconLeftTabletMargin, $iconRightTabletMargin, $iconTopTabletMargin, $iconBottomMobileMargin, $iconLeftMobileMargin, $iconRightMobileMargin, $iconTopMobileMargin );

			$desktop_class = '';
			$tab_class     = '';
			$mob_class     = '';

			if ( array_key_exists( 'UAGHideDesktop', $attributes ) || array_key_exists( 'UAGHideTab', $attributes ) || array_key_exists( 'UAGHideMob', $attributes ) ) {

				$desktop_class = ( isset( $attributes['UAGHideDesktop'] ) ) ? 'uag-hide-desktop' : '';

				$tab_class = ( isset( $attributes['UAGHideTab'] ) ) ? 'uag-hide-tab' : '';

				$mob_class = ( isset( $attributes['UAGHideMob'] ) ) ? 'uag-hide-mob' : '';
			}

			$zindex_desktop           = '';
			$zindex_tablet            = '';
			$zindex_mobile            = '';
			$zindex_wrap              = array();
			$zindex_extention_enabled = ( isset( $attributes['zIndex'] ) || isset( $attributes['zIndexTablet'] ) || isset( $attributes['zIndexMobile'] ) );

			if ( $zindex_extention_enabled ) {
				$zindex_desktop = ( isset( $attributes['zIndex'] ) ) ? '--z-index-desktop:' . $attributes['zIndex'] . ';' : false;
				$zindex_tablet  = ( isset( $attributes['zIndexTablet'] ) ) ? '--z-index-tablet:' . $attributes['zIndexTablet'] . ';' : false;
				$zindex_mobile  = ( isset( $attributes['zIndexMobile'] ) ) ? '--z-index-mobile:' . $attributes['zIndexMobile'] . ';' : false;

				if ( $zindex_desktop ) {
					array_push( $zindex_wrap, $zindex_desktop );
				}

				if ( $zindex_tablet ) {
					array_push( $zindex_wrap, $zindex_tablet );
				}

				if ( $zindex_mobile ) {
					array_push( $zindex_wrap, $zindex_mobile );
				}
			}

			$has_margin = false;
			foreach ( $margin_variables as $margin ) {
				if ( is_numeric( $margin ) ) {
					$has_margin = true;
					break;
				}
			}
			$margin_class = $has_margin ? 'wp-block-uagb-icon--has-margin' : '';
			$main_classes = array(
				'uagb-icon-wrapper',
				$block_id,
				( is_array( $attributes ) && isset( $attributes['className'] ) ) ? $attributes['className'] : '',
				$margin_class,
				$desktop_class,
				$tab_class,
				$mob_class,
				$zindex_extention_enabled ? 'uag-blocks-common-selector' : '',
			);
	
			$iconSvg     = isset( $attributes['icon'] ) ? $attributes['icon'] : 'circle-check';
			$link        = isset( $attributes['link'] ) ? $attributes['link'] : '';
			$target      = isset( $attributes['target'] ) ? $attributes['target'] : false;
			$disableLink = isset( $attributes['disableLink'] ) ? $attributes['disableLink'] : false;
			$linkUrl     = $disableLink ? $link : '#';
			$targetVal   = $target ? '_blank' : '_self';

			ob_start();
			$iconHtml = UAGB_Helper::render_svg_html( $iconSvg );
			$iconHtml = ob_get_clean();
	  
			if ( $iconHtml ) {

				$role_attr        = ( 'image' === $attributes['iconAccessabilityMode'] ) ? ' role="img"' : ( ( 'svg' === $attributes['iconAccessabilityMode'] ) ? ' role="graphics-symbol"' : '' );
				$aria_hidden_attr = ( 'presentation' === $attributes['iconAccessabilityMode'] ) ? 'true' : 'false';
				$aria_label_attr  = ( 'presentation' !== $attributes['iconAccessabilityMode'] ) ? ' aria-label="' . esc_attr( $attributes['iconAccessabilityDesc'] ) . '"' : '';
			
				$iconHtml = preg_replace(
					'/<svg(.*?)>/',
					'<svg$1' . $role_attr . ' aria-hidden="' . $aria_hidden_attr . '"' . $aria_label_attr . '>',
					$iconHtml
				);
			}
			

			$aria_label_attr = ( 'presentation' !== $attributes['iconAccessabilityMode'] ) ? ( empty( $attributes['iconAccessabilityDesc'] ) ? implode( '', str_split( $attributes['icon'] ) ) : $attributes['iconAccessabilityDesc'] ) : '';

			// Check and prepend the protocol if necessary.
			if ( '#' !== $linkUrl ) {
				$linkUrl = self::get_protocol( $linkUrl ) ? $linkUrl : self::prepend_http( $linkUrl );
			}
			
			if ( $iconHtml && $disableLink && $linkUrl ) {
				// Wrap the SVG content with an anchor tag.
				$iconHtml = preg_replace(
					'/<svg(.*?)>(.*?)<\/svg>/s',
					'<a rel="noopener noreferrer" href="' . esc_url( $linkUrl ) . '" target="' . esc_attr( $targetVal ) . '"><svg$1>$2</svg></a>',
					$iconHtml
				);
				
			}

			ob_start();
			?>      
			<div class="<?php echo esc_attr( implode( ' ', $main_classes ) ); ?>"
			style="<?php echo esc_attr( implode( '', $zindex_wrap ) ); ?>" >
				<?php if ( $has_margin ) : ?>
				<div class='uagb-icon-margin-wrapper'>
				<?php endif; ?>
					<span class="uagb-svg-wrapper" 
					<?php 
					if ( $aria_label_attr ) {
						echo ' aria-label="' . esc_attr( $aria_label_attr ) . '"';
					} 
					?>
					tabindex="0">		
						<?php echo $iconHtml; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Already escaped & sanitize inside render_svg_html(). ?>
					</span>
				<?php if ( $has_margin ) : ?>
				</div>
				<?php endif; ?>
			</div>
			<?php
			return ob_get_clean();

		}

		/**
		 * Renders Front-end Click Event.
		 *
		 * @param string $id             Block ID.
		 * @since 2.15.0
		 * @return string|false                The Output Buffer.
		 */
		public static function render_icon_click( $id ) {
			ob_start();
			?>
				window.addEventListener( 'DOMContentLoaded', () => {
					const blockScope = document.querySelector( '.uagb-block-<?php echo esc_html( $id ); ?>' );
					if ( ! blockScope ) {
						return;
					}

					const anchorElement = blockScope.querySelector('a');
					if (!anchorElement) {
						return;
					} 

					<?php // Add event listener for Enter and Space key presses. ?> 
					blockScope.addEventListener('keydown', (event) => {
						if ( 13 === event.keyCode || 32 === event.keyCode ) {
							event.preventDefault();
							<?php // Trigger the click event on the blockScope. ?> 
							anchorElement.click();	
						}
					} );
				} );
			<?php
			return ob_get_clean();
		}

	}

		
	/**
	 *  Prepare if class 'Spectra_Icon' exist.
	 *  Kicking this off by calling 'get_instance()' method
	 */
	Spectra_Icon::get_instance();
}
