<?php
/**
 * Functions to register client-side assets (scripts and stylesheets) for the
 * Nisje App
 *
 * @package Nisje
 */

declare( strict_types=1 );
namespace NisjeFrontend\ClientAssets;

use NisjeFrontend\I18n;
use Nisje\Nofications;

if ( ! defined( 'ABSPATH' ) ) {
	die( 'Silence is golden.' );
}

/**
 * Retrieves the root theme path.
 *
 * @return string Root path to the theme.
 */
function theme_path(): string {
	return \get_stylesheet_directory() . '/';
}

/**
 * Retrieves a URL to a file in the theme.
 *
 * @param  string $path Relative path of the desired file.
 * @return string       Fully qualified URL pointing to the desired file.
 */
function theme_url( string $path ): string {
	return get_stylesheet_directory_uri() . '/' . $path;
}

/**
 * Check if session is from the native app
 *
 * @return boolean Session is from the native app.
 */
function is_native_app() {
	$user_agent = filter_input( INPUT_SERVER, 'HTTP_USER_AGENT', FILTER_SANITIZE_STRING ) ?? '';
	return strpos( $user_agent, 'NisjeApp' ) !== false;
}

/**
 * Registers all the theme packages scripts that are in the standardized
 * `build/` location.
 */
function register_packages_scripts() {
	foreach ( glob( theme_path() . 'build/*/*.css' ) as $path ) {
		// Prefix `nisje-` to package directory to get script handle.
		// For example, `…/build/components/index.js` becomes `nisje-components`.
		$handle = 'nisje-' . basename( dirname( $path ) );

		$filename = basename( $path );
		if ( 'style.css' !== $filename ) {
			$handle .= '-' . str_replace( '.css', '', $filename );
		}

		// Replace `.css` extension with `.asset.php` to find the generated dependencies file.
		$asset_file   = substr( $path, 0, -4 ) . '.asset.php';
		$asset        = file_exists( $asset_file )
			? require $asset_file
			: null;
		$dependencies = isset( $asset['dependencies'] ) ? $asset['dependencies'] : [];
		$version      = isset( $asset['version'] ) ? $asset['version'] : filemtime( $path );

		// Get the path from directory as expected by `theme_url`.
		$theme_path = substr( $path, strlen( theme_path() ) );

		wp_register_style(
			$handle,
			theme_url( $theme_path ),
			$dependencies,
			$version
		);
	}

	foreach ( glob( theme_path() . 'build/*/index.js' ) as $path ) {
		// Prefix `nisje-` to package directory to get script handle.
		// For example, `…/build/components/index.js` becomes `nisje-components`.
		$handle = 'nisje-' . basename( dirname( $path ) );

		// Replace `.js` extension with `.asset.php` to find the generated dependencies file.
		$asset_file   = substr( $path, 0, -3 ) . '.asset.php';
		$asset        = file_exists( $asset_file )
			? require $asset_file
			: null;
		$dependencies = isset( $asset['dependencies'] ) ? $asset['dependencies'] : [];
		$version      = isset( $asset['version'] ) ? $asset['version'] : filemtime( $path );

		// Add dependencies that cannot be detected and generated by build tools.
		switch ( $handle ) {
			case 'nisje-src':
				array_push( $dependencies, 'wp-tinymce' );
				break;
		}

		// Get the path from directory as expected by `theme_url`.
		$theme_path = substr( $path, strlen( theme_path() ) );

		wp_register_script(
			$handle,
			theme_url( $theme_path ),
			$dependencies,
			$version,
			true
		);
	}
}
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\\register_packages_scripts' );
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\\register_packages_scripts' );

/**
 * Loads Locale Data.
 */
function load_locale_data() {
	// Prepare Jed locale data.
	$locale_data = I18n\get_jed_locale_data( 'nisje-theme' );

	if ( ! empty( $locale_data ) ) {
		wp_add_inline_script(
			'wp-i18n',
			'wp.i18n.setLocaleData( ' . wp_json_encode( $locale_data ) . ' );'
		);
	}
}

/**
 * Get url to font stylesheet
 *
 * @return string
 */
function get_font_stylesheet(): string {
	$font = get_theme_mod( 'nisje_font', 'circular' );
	return theme_url( 'assets/fonts/' . $font . '/style.css' );
}

/**
 * Enqueue files that all pages need
 */
function enqueue_styles_and_scripts() {
	wp_enqueue_style( 'nisje-sanitize' );
	wp_enqueue_style( 'nisje-settings' );
	wp_enqueue_style( 'nisje-wordpress' );
	wp_enqueue_style( 'nisje-font', get_font_stylesheet(), [], '1.0.1' );
}
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_styles_and_scripts' );

/**
 * Registers register scripts and styles
 */
function register_registration_scripts_and_styles() {
	// Remove BuddyPress style.
	wp_dequeue_style( 'bp-nouveau' );
	wp_deregister_style( 'bp-nouveau' );
	wp_enqueue_style( 'dashicons' );
	wp_enqueue_style( 'wp-components' );
	wp_enqueue_style( 'nisje-wordpress-register' );
}

/**
 * Registers privacy scripts and styles
 */
function register_privacy_scripts_and_styles() {
	wp_enqueue_style( 'wp-components' );
	wp_enqueue_style( 'nisje-core' );
	wp_enqueue_style( 'nisje-components' );
	wp_enqueue_style( 'nisje-wordpress-privacy' );
}

/**
 * Registers scripts and styles
 */
function register_scripts_and_styles() {
	load_locale_data();

	$is_user_logged_in   = is_user_logged_in();
	$is_groups_activated = function_exists( '\bp_is_active' ) && \bp_is_active( 'groups' );

	if ( is_native_app() ) {
		wp_enqueue_script( 'nisje-mobile' );
	}

	wp_enqueue_script( 'nisje-src' );

	wp_enqueue_style( 'wp-components' );
	wp_enqueue_style( 'wp-block-library-theme' );
	wp_enqueue_style( 'nisje-interface' );
	wp_enqueue_style( 'nisje-plugin-wiki' );
	wp_enqueue_style( 'nisje-comments' );
	wp_enqueue_style( 'nisje-core' );
	wp_enqueue_style( 'nisje-src' );

	if ( $is_user_logged_in && function_exists( '\bp_is_active' ) && \bp_is_active( 'notifications' ) ) {
		wp_enqueue_script( 'nisje-notifications' );
		wp_enqueue_style( 'nisje-notifications' );
	}

	if ( $is_groups_activated ) {
		wp_enqueue_script( 'nisje-groups' );
		wp_enqueue_style( 'nisje-groups' );
	}

	$menus = [
		'primary'   => [],
		'shortcuts' => [],
	];

	$locations = get_nav_menu_locations();

	foreach ( $menus as $menu_key => $menu_value ) {
		$menu_id = 0;

		if ( $is_user_logged_in && function_exists( 'bp_get_member_type' ) ) {
			$member_types = bp_get_member_type( get_current_user_id(), false );
			if ( isset( $member_types[0] ) && isset( $locations[ $menu_key . '-' . $member_types[0] ] ) ) {
				$menu_id = (int) $locations[ $menu_key . '-' . $member_types[0] ];
			}
		}

		if ( ! $menu_id && isset( $locations[ $menu_key ] ) ) {
			$menu_id = (int) $locations[ $menu_key ];
		}

		$wp_menu_object = ( $menu_id ) ? wp_get_nav_menu_object( $menu_id ) : [];

		if ( $wp_menu_object ) {
			$menu_id = (int) $wp_menu_object->term_id;

			$wp_menu_items = wp_get_nav_menu_items( $menu_id );
			foreach ( $wp_menu_items as $menuitem ) {
				if ( $menuitem instanceof \WP_Post ) {
					$require_user = (bool) get_post_meta( $menuitem->ID, 'require_user', true );

					if ( ! $is_user_logged_in && $require_user ) {
						continue;
					}

					$menus[ $menu_key ][] = [
						'id'    => $menuitem->ID,
						'title' => $menuitem->title,
						'url'   => $menuitem->url,
						'icon'  => $menuitem->attr_title,
					];
				}
			}
		}
	}

	$options = [
		'base'              => '/',
		'homeUrl'           => home_url(),
		'restUrl'           => get_rest_url(),
		'fontStylesheetUrl' => get_font_stylesheet(),
		'isUserLoggedIn'    => $is_user_logged_in,
		'locale'            => I18n\get_current_locale(),
		'logoutUrl'         => wp_logout_url( home_url() ),
		'menus'             => $menus,
		'name'              => apply_filters( 'nisje_theme_name', get_bloginfo( 'name' ) ),
		'token'             => apply_filters( 'nisje_jwt_token', false ),
		'toolbarLogo'       => get_theme_mod( 'nisje_theme_images_toolbar_logo', false ),
		'isNativeApp'       => is_native_app(),
		'scraperApiUrl'     => nisje_get_dir( 'static-api/safe-image.php' ),
		'memberTypes'       => nisje_get_setting( 'member_types' ),
		'features'          => [
			'notificationsPing' => Nofications\is_ping_service_enabled(),
			'groups'            => $is_groups_activated,
		],
		'allowEmailChange'  => false,
	];

	// Logo.
	$logo = get_theme_mod( 'custom_logo' );
	if ( $logo ) {
		$options['logo'] = wp_get_attachment_url( $logo );
	}

	// Settings.
	$request             = new \WP_REST_Request( 'GET', '/nisje/v1/settings' );
	$response            = rest_do_request( $request );
	$server              = rest_get_server();
	$options['settings'] = $server->response_to_data( $response, false );

	if ( is_multisite() && ! is_subdomain_install() ) {
		$blog_details = get_blog_details();

		if ( $blog_details ) {
			$options['base'] = $blog_details->path;
		}
	}

	if ( ! $is_user_logged_in ) {
		$options['usersCanRegister'] = (bool) get_option( 'users_can_register' );
		$options['loginUrl']         = wp_login_url();
		$options['registrationUrl']  = wp_registration_url();
	} else {
		$user_id = \get_current_user_id();
		$user    = \get_userdata( $user_id );

		$options['userId']              = $user_id;
		$options['displayName']         = $user->display_name;
		$options['email']               = $user->user_email;
		$options['hidePasswordField']   = nisje_get_setting( 'hide_forgotten_password', 'general' );
		$options['unreadNotifications'] = (int) \get_user_meta( $user_id, 'notifications_unseen', true ) ?: 0;
		$options['adminUrl']            = \admin_url();
		$options['userCapabilities']    = [
			'edit'   => [],
			'create' => [],
		];

		/**
		 * Groups settings
		 */
		if ( $is_groups_activated ) {
			// Capabilities.
			$options['userCapabilities']['create']['group'] = \bp_user_can_create_groups();

			// Invites.
			$options['groupInvites'] = \groups_get_invited_to_group_ids( $user_id );

			// Types.
			$group_types          = bp_groups_get_group_types( [], 'objects' );
			$excluded_group_types = [];
			$group_filters        = [];
			$group_create_types   = [];

			if ( $group_types ) {
				foreach ( $group_types as $key => $group_type ) {
					if ( isset( $group_type->exclude_groups ) && $group_type->exclude_groups ) {
						$excluded_group_types[] = $key;
					} elseif ( $group_type->has_directory ) {
						$group_filters[] = [
							'name' => $group_type->labels['name'] ?: $key,
							'slug' => $key,
						];
					}

					if ( $group_type->show_in_create_screen ) {
						$group_create_types[] = [
							'name' => $group_type->labels['name'] ?: $key,
							'slug' => $key,
						];
					}
				}
			}

			$options['excludedGroupTypes'] = implode( ',', $excluded_group_types );
			$options['groupFilters']       = $group_filters;
			$options['groupCreateTypes']   = $group_create_types;

			// Main group.
			$main_group_id = function_exists( 'nisje_get_main_group' ) ? nisje_get_main_group( $user_id ) : 0;
			if ( $main_group_id ) {
				$main_group = \groups_get_group( $main_group_id );

				if ( $main_group->id ) {
					$options['mainGroup'] = [
						'id'   => $main_group->id,
						'name' => $main_group->name,
					];
				}
			}
		}
	}

	$options = apply_filters( 'nisje_frontend_options', $options );

	wp_add_inline_script(
		'nisje-settings',
		sprintf(
			'var nisjeClientAssetsPath = "%s"; var nisjeSettings = %s;',
			theme_url( '' ),
			wp_json_encode( $options )
		),
		'before'
	);
}

/**
 * Editor mods
 */
function editor_assets() {
	wp_enqueue_script( 'nisje-full-site-editing' );
	wp_enqueue_style( 'nisje-full-site-editing' );
	wp_enqueue_script( 'nisje-block-library-admin' );
	wp_enqueue_style( 'nisje-font', get_font_stylesheet(), [], '1.0.1' );
}
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\\editor_assets' );

/**
 * Fix skip link focus in IE11.
 *
 * This does not enqueue the script because it is tiny and because it is only for IE11.
 */
function skip_link_focus_fix() {
	?>
	<script>
	/(trident|msie)/i.test(navigator.userAgent)&&document.getElementById&&window.addEventListener&&window.addEventListener("hashchange",function(){var t,e=location.hash.substring(1);/^[A-z0-9_-]+$/.test(e)&&(t=document.getElementById(e))&&(/^(?:a|select|input|button|textarea)$/i.test(t.tagName)||(t.tabIndex=-1),t.focus())},!1);
	</script>
	<?php
}
add_action( 'wp_print_footer_scripts', __NAMESPACE__ . '\\skip_link_focus_fix' );
