<?php
namespace SabaiApps\Directories\Component\WordPress\Helper;

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Exception;

/**
 * ShortcodesHelper provides methods to register and render WordPress shortcodes for SabaiApps components.
 */
class ShortcodesHelper {

	/**
	 * Returns all available shortcodes for SabaiApps components.
	 *
	 * @param Application $application
	 * @return array
	 */
	public function help( Application $application ) {
		if ( ! $shortcodes = $application->getPlatform()->getCache( 'wordpress_shortcodes' ) ) {
			$shortcodes = array();
			$slugs      = $application->System_Slugs( null, null, false );
			foreach ( array_keys( $slugs ) as $component_name ) {
				foreach ( $slugs[ $component_name ] as $slug_name => $slug_info ) {
					if ( isset( $slug_info['wp_shortcode'] )
						&& ! is_array( $slug_info['wp_shortcode'] ) // array meaning using an existing shortcode, so no need to register here
					) {
						$shortcodes[ $slug_info['wp_shortcode'] ] = array(
							'component' => $component_name,
							'slug'      => $slug_name,
							'path'      => null,
						);
					}
				}
			}
			$shortcodes = $application->Filter( 'wordpress_shortcodes', $shortcodes );
			$application->getPlatform()->setCache( $shortcodes, 'wordpress_shortcodes', 0 );
		}

		return $shortcodes;
	}

	/**
	 * Renders the output for a given shortcode.
	 *
	 * @param Application $application
	 * @param array       $atts
	 * @param string|null $content
	 * @param string      $tag
	 * @return string|null
	 */
	public function doShortcode( Application $application, $atts, $content, $tag ) {
		if ( defined( 'REST_REQUEST' ) && REST_REQUEST // prevent invalid response error in Gutenberg editor
			&& ! defined( 'DRTS_WORDPRESS_IS_RENDER_BLOCK' ) // make sure not rendering block
		) {
			return;
		}

		if ( ! is_array( $atts ) ) {
			$atts = array();
		}
		$shortcodes = $this->help( $application );
		if ( ! isset( $shortcodes[ $tag ] ) ) {
			return;
		}

		$shortcode = $shortcodes[ $tag ];
		if ( isset( $atts['component'] ) ) {
			$component = $atts['component'];
			unset( $atts['component'] );
		} else {
			$component = $shortcode['component'];
		}
		if ( ! $component
			|| ! $application->isComponentLoaded( $component )
		) {
			return;
		}

		$options = array();
		if ( isset( $atts['title'] ) ) {
			$options['title'] = empty( $atts['title'] ) ? false : $atts['title'];
			unset( $atts['title'] );
		}
		if ( isset( $atts['cache'] ) ) {
			$options['cache'] = empty( $atts['cache'] ) ? false : (int) $atts['cache'];
			unset( $atts['cache'] );
		}
		if ( isset( $atts['partial'] ) ) {
			$options['partial'] = empty( $atts['partial'] ) ? null : $atts['partial'];
			unset( $atts['partial'] );
		}
		if ( isset( $atts['group'] ) ) {
			$options['group'] = empty( $atts['group'] ) ? null : $atts['group'];
			unset( $atts['group'] );
		}
		if ( ! empty( $atts['hero'] ) ) {
			$hero                  = true;
			$hero_color            = $atts['hero_color'] ?? 'primary';
			$hero_inner            = ! empty( $atts['hero_inner'] );
			$hero_overflow_visible = ! empty( $atts['hero_overflow_visible'] );
			unset( $atts['hero'], $atts['hero_color'], $atts['hero_inner'], $atts['hero_overflow_visible'] );
		}
		if ( ! empty( $atts['nav_link_color'] ) ) {
			$nav_link_color = $atts['nav_link_color'];
			unset( $atts['nav_link_color'] );
		} else {
			$nav_link_color = 'primary';
		}
		if ( ! empty( $atts['nav_margin'] ) ) {
			$nav_margin = $atts['nav_margin'];
			unset( $atts['nav_margin'] );
		}
		try {
			$filtered = $application->Filter(
				'wordpress_do_shortcode',
				array(
					'atts'    => (array) $atts,
					'options' => $options,
				) + $shortcode,
				array( $tag, $component )
			);
			if ( is_string( $filtered ) ) {
				return $filtered;
			}

			$options = $filtered['options'];
			if ( isset( $filtered['path'] ) ) {
				$path = $filtered['path'];
			} elseif ( isset( $filtered['slug'] ) ) {
				$path = '/' . $application->getComponent( $component )->getSlug( $filtered['slug'] );
			} elseif ( isset( $filtered['content'] ) ) {
				return $filtered['content'];
			} else {
				throw new Exception\RuntimeException( 'Shortcode [' . $tag . ']: No path, slug, or content in shortcode.' );
			}
			foreach ( array( 'title', 'class' ) as $option ) {
				if ( isset( $filtered[ $option ] ) ) {
					$options[ $option ] = $filtered[ $option ];
				}
			}
		} catch ( Exception\IException $e ) {
			$application->logError( $e );
			return;
		}

		$load_dashicons = false;

		// It is possible that multiple shortcodes are rendered with different atts
		$ret   = array();
		$paths = is_array( $path ) ? $path : array( $path );
		if ( is_array( $paths[0] ) ) {
			$navs         = $nav_content = array();
			$container_id = $application->getPlatform()->getContainerId();
			foreach ( array_keys( $paths ) as $key ) {
				if ( ! isset( $paths[ $key ]['path'] ) ) {
					continue;
				}

				$icon = '';
				if ( isset( $paths[ $key ]['icon'] ) ) {
					if ( strpos( $paths[ $key ]['icon'], 'dashicons-' ) ) {
						$load_dashicons = true;
					}
					$icon = '<i class="' . $paths[ $key ]['icon'] . '"></i> ';
				}
				$navs[ $key ] = '<button type="button" class="' . DRTS_BS_PREFIX . 'nav-link ' . ( $key === 0 ? DRTS_BS_PREFIX . 'active' : '' ) . ' ' . DRTS_BS_PREFIX . 'ps-1 ' . DRTS_BS_PREFIX . 'pb-2"'
					. ' id="' . $container_id . '-tab-' . $key . '-nav" data-bs-toggle="tab" data-bs-target="#' . $container_id . '-tab-' . $key . '"'
					. ' role="tab" aria-controls="' . $container_id . '-tab-' . $key . '" aria-selected="' . ( $key === 0 ? 'true' : 'false' ) . '">'
					. $icon . ( $paths[ $key ]['title'] ?? 'Tab ' . ( $key + 1 ) )
					. '</button>';
				$_paths       = is_array( $paths[ $key ]['path'] ) ? $paths[ $key ]['path'] : array( $paths[ $key ]['path'] );
				$_nav_content = array();
				foreach ( array_keys( $_paths ) as $key2 ) {
					$_nav_content[ $key2 ] = $application->getPlatform()->render(
						$_paths[ $key2 ],
						array( $shortcode['atts_name'] ?? 'settings' => $filtered['atts'][ $key ][ $key2 ] ?? ( $filtered['atts'][ $key2 ] ?? $filtered['atts'] ) ),
						array( 'container_class' => true ) + ( $options[ $key ][ $key2 ] ?? ( $options[ $key2 ] ?? $options ) )
					);
				}
				$nav_content[ $key ] = '<div class="' . DRTS_BS_PREFIX . 'tab-pane ' . DRTS_BS_PREFIX . 'fade ' . ( $key === 0 ? DRTS_BS_PREFIX . 'active ' . DRTS_BS_PREFIX . 'show' : '' ) . '" id="' . $container_id . '-tab-' . $key . '" role="tabpanel" tabindex="0">'
					. implode( PHP_EOL, $_nav_content ) . '</div>';
			}
			if ( ! empty( $navs ) ) {
				$container_class = $application->getPlatform()->getContainerClass( $options['class'] ?? null );
				$ret[]           = '<div class="' . $container_class . '" id="' . $container_id . '">';
				$style           = '--bs-nav-link-color: var(--bs-' . $nav_link_color . '); --bs-nav-link-hover-color: var(--bs-' . $nav_link_color . ');';
				$margin          = empty( $nav_margin ) ? DRTS_BS_PREFIX . 'mb-1 ' . DRTS_BS_PREFIX . 'mb-md-0' : DRTS_BS_PREFIX . 'mb-' . $application->H( $nav_margin );
				$ret[]           = '<nav class="drts-wordpress-shortcode-navs ' . $margin . '" data-wordpress-shortcode="' . $application->H( $tag ) . '">'
					. '<div class="' . DRTS_BS_PREFIX . 'nav" id="' . $container_id . '-navs" role="tablist" style="' . $style . '">'
					. implode( PHP_EOL, $navs )
					. '</div></nav>';
				$ret[]           = '<div class="' . DRTS_BS_PREFIX . 'tab-content drts-wordpress-shortcode-tabs" id="' . $container_id . '-tabs">'
					. implode( PHP_EOL, $nav_content )
					. '</div>';
				$ret[]           = '</div>';
			}
		} else {
			foreach ( array_keys( $paths ) as $key ) {
				$ret[] = $application->getPlatform()->render(
					$paths[ $key ],
					array( $shortcode['atts_name'] ?? 'settings' => $filtered['atts'][ $key ] ?? $filtered['atts'] ),
					array( 'container_class' => empty( $hero ) ) + ( $options[ $key ] ?? $options )
				);
			}
		}

		if ( $load_dashicons ) {
			wp_enqueue_style( 'dashicons' );
		}

		$ret = implode( PHP_EOL, $ret );
		if ( ! empty( $hero ) ) {
			$hero_class = 'drts-hero ' . DRTS_BS_PREFIX . 'bg-' . $hero_color;
			if ( ! empty( $hero_overflow_visible ) ) {
				$hero_class .= ' ' . DRTS_BS_PREFIX . 'overflow-visible';
			}
			if ( ! empty( $hero_inner ) ) {
				$ret = '<div class="' . $application->H( $hero_class ) . '"><div class="drts-hero-inner">' . $ret . '</div></div>';
			} else {
				$ret = '<div class="' . $application->H( $hero_class ) . '">' . $ret . '</div>';
			}
			$ret = '<div class="' . $application->getPlatform()->getContainerClass() . '">' . $ret . '</div>';
		}
		return $ret;
	}
}
