<?php
/**
 * The public-facing functionality of the plugin.
 *
 * @link       https://personalizewp.com
 * @since      1.0.0
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Public
 */

namespace PersonalizeWP;

use PersonalizeWP\Traits\SingletonTrait;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

/**
 * The public-facing functionality of the plugin. Sets up styles and scripts, with inline vars.
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Public
 */
class PublicFacing {

	use SingletonTrait;

	/**
	 * Holds Instance of plugin object
	 *
	 * @var PersonalizeWP
	 */
	private $plugin;

	/**
	 * Initialize the class and set its properties.
	 *
	 * @since 1.0.0
	 * @since 1.2.0 Switch to single plugin param
	 * @since 2.5.0 Remove param
	 */
	public function __construct() {
		$this->plugin = \personalizewp();
	}

	/**
	 * Setup public hooks
	 *
	 * @since 2.5.0
	 *
	 * @return void
	 */
	public function setup() {
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_styles' ] );
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
	}

	/**
	 * Register the stylesheets for the public-facing side of the site.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_styles() {

		if ( is_admin() ) {
			return;
		}

		$handle  = $this->plugin->get_personalizewp();
		$suffix  = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
		$version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? time() : $this->plugin->get_version();
		wp_enqueue_style(
			$handle,
			$this->plugin->plugin_url( "public/css/pwp{$suffix}.css" ),
			array(),
			$version
		);
	}

	/**
	 * Register the JavaScript for the public-facing side of the site.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_scripts() {

		if ( is_admin() ) {
			return;
		}

		// Handle prefix for all scripts
		$handle = $this->plugin->get_personalizewp();

		$properties = require $this->plugin->plugin_path( 'public/js/pwp.asset.php' );
		$js_version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? $properties['version'] : $this->plugin->get_version();
		wp_enqueue_script(
			$handle,
			$this->plugin->plugin_url( 'public/js/pwp.js' ),
			$properties['dependencies'],
			$js_version,
			[ 'strategy' => 'defer' ]
		);

		/**
		 * Changes the settings used by the frontend PersonalizeWP JS.
		 *
		 * @since 3.1.0
		 *
		 * @param array[] $pwp_settings {
		 *     String indexed array of PersonalizeWP settings for the core JS.
		 *
		 *     @type array ...$0 {
		 *         An associative array of the variables.
		 *
		 *         @type string $root          URL root for all PersonalizeWP REST requests.
		 *         @type string $nonceEndpoint URL endpoint for JS to retrieve a new nonce when visitor is logged in.
		 *         @type bool   $isLoggedIn    Flag which triggers sending a 'X-WP-Nonce' header with REST calls to ensure no CSRF for users. Default false.
		 *         @type bool   $delayInit     Flag to indicate the PersonalizeWP JavaScript should delay itself until some user interaction has occurred. Default false.
		 *         @type string $apiToken      Token to restrict API responses to known domains, i.e. CSP authorisation.
		 *     }
		 * }
		 */
		$pwp_settings = apply_filters(
			'personalizewp_js_settings',
			array(
				'root'          => sanitize_url( get_rest_url() ), // phpcs:ignore WordPress.WP.DeprecatedFunctions.sanitize_url -- 5.9 un-deprecated this
				'nonceEndpoint' => admin_url( 'admin-ajax.php?action=rest-nonce' ),
				'isLoggedIn'    => is_user_logged_in(),
				'delayInit'     => (bool) $this->plugin->get_setting( 'performance_delay_initialisation' ),
				'apiToken'      => $this->plugin->api->get_api_auth_token( get_home_url() ),
			)
		);
		wp_add_inline_script(
			$handle,
			'window.pwpSettings = ' . wp_json_encode( $pwp_settings ) . ';',
			'before'
		);

		// Automatically break cache when building.
		$properties = require $this->plugin->plugin_path( 'public/js/tracking.asset.php' );
		wp_enqueue_script(
			"{$handle}/tracking",
			$this->plugin->plugin_url( 'public/js/tracking.js' ),
			array_merge( [ 'personalizewp' ], $properties['dependencies'] ),
			$properties['version'],
			[ 'strategy' => 'defer' ]
		);
		wp_add_inline_script(
			"{$handle}/tracking",
			'window.pwpTrack = ' . wp_json_encode( $this->get_tracking_vars() ) . ';',
			'before'
		);

		$properties = require $this->plugin->plugin_path( 'public/js/visitor-data.asset.php' );
		wp_enqueue_script(
			"{$handle}/visitor-data",
			$this->plugin->plugin_url( 'public/js/visitor-data.js' ),
			array_merge( [ 'personalizewp' ], $properties['dependencies'] ),
			$properties['version'],
			[ 'strategy' => 'defer' ]
		);

		$properties = require $this->plugin->locations['dir'] . 'public/js/content-variations.asset.php';
		wp_enqueue_script(
			"{$handle}/content-variations",
			$this->plugin->locations['url'] . 'public/js/content-variations.js',
			array_merge( [ 'personalizewp' ], $properties['dependencies'] ),
			$properties['version'],
			[ 'strategy' => 'defer' ]
		);

		$properties = include $this->plugin->plugin_path( 'public/js/pwd-blocks.asset.php' );
		wp_enqueue_script(
			"{$handle}/pwd-blocks",
			$this->plugin->plugin_url( 'public/js/pwd-blocks.js' ),
			array_merge( [ 'personalizewp' ], $properties['dependencies'] ),
			$properties['version'],
			[ 'strategy' => 'defer' ]
		);

		if ( ! empty( $this->plugin->get_setting( 'performance_legacy_blocks' ) ) ) {
			// Support legacy blocks with hardcoded dependancy on main script.
			$properties = require $this->plugin->plugin_path( 'public/js/wp-dxp.asset.php' );
			$js_version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? $properties['version'] : $this->plugin->get_version();
			wp_enqueue_script(
				"{$handle}/legacy",
				$this->plugin->plugin_url( 'public/js/wp-dxp.js' ),
				array_merge( [ $handle ], $properties['dependencies'] ),
				$js_version,
				[ 'strategy' => 'defer' ]
			);
		}
	}

	/**
	 * Return the variables used for Activity Tracking, to be added to inline JS.
	 *
	 * @since 3.2.0
	 *
	 * @return array
	 */
	protected function get_tracking_vars() {
		global $wp_query;

		// Setup extra data to pass through to frontend for the JS to send back.
		// We do this as the JS data will be part of the cached HTML.
		$args = array(
			'trackAnon'   => $this->plugin->should_track_anonymous_users(),
			'userIsKnown' => is_user_logged_in(), // Frontend should not be cached and will be known.
			'type'        => 'misc',
			'obj'         => null,
		);
		if ( is_home() || is_front_page() ) {
			$args['type'] = 'home';

		} elseif ( is_singular() ) {
			$args['obj']  = $wp_query->get_queried_object_id();
			$args['type'] = 'post';

		} elseif ( is_post_type_archive() ) {
			// Mark as a page, but don't record an ID
			$args['type'] = 'post';

		} elseif ( is_archive() ) {
			$term = $wp_query->get_queried_object();
			if ( isset( $term->term_id ) ) {
				$args['obj']  = $term->term_id;
				$args['type'] = 'tax';
			}
		} elseif ( is_search() ) {
			$args['type'] = 'search';

		} elseif ( is_404() ) {
			$args['type'] = 'error404';

		}
		// Cover additional WooCommmerce Areas
		if ( function_exists( 'is_woocommerce' ) && is_shop() ) {
			$args['obj']  = wc_get_page_id( 'shop' );
			$args['type'] = 'post';
		}

		/**
		 * Filters tracking arguments to be added to the HTML output of every page.
		 *
		 * Allows passing backend known variables to the frontend for JS to use.
		 *
		 * @since 3.3.0
		 *
		 * @param array[] $args {
		 *     JS variables to pass to the PWP Tracking module.
		 *
		 *     @type array ...$0 {
		 *         An associative array of the variables.
		 *
		 *         @type bool     $trackAnon   Flag to indicate to tracking JS if anonymous users should be tracked or not. Default false.
		 *         @type bool     $userIsKnown Flag to indicate current visitor is known to the site. Default false.
		 *         @type string   $type        Type of event being tracked.
		 *         @type int|null $obj         Object ID of current CPT or Taxonomy, default to null.
		 *     }
		 * }
		 */
		return apply_filters( 'personalizewp_get_tracking_variables', $args );
	}
}
