<?php
/**
 * The file contains definition of WLC_Algolia class
 *
 * @category Class file
 * @package WLC\Algolia
 * @author White Label Coders
 * @license TO DO
 * @link TO DO
 */

namespace wlc_algolia;

use wlc_algolia\Helpers as helper;

defined( 'ABSPATH' ) || die( 'Direct file access is forbidden' );

/**
 * Plugin instance class
 */
class WLC_Algolia {
	/**
	 * WLC_Algolia version.
	 *
	 * @var string
	 */
	public $version = '1.0.0';

	/**
	 * The single instance of the class.
	 *
	 * @var WLC_Algolia
	 * @since 2.1
	 */
	protected static $instance = null;

	/**
	 * Connection instance.
	 *
	 * @var Connection
	 */
	public $connection = null;

	/**
	 * Settings instance.
	 *
	 * @var Settings
	 */
	public $settings = null;

	/**
	 * Plugin configurations.
	 *
	 * @var array
	 */
	protected $configs = array();

	/**
	 *
	 * Assets instance.
	 *
	 * @var array
	 */
	protected $assets = array();

	/**
	 * Plugin enqueues.
	 *
	 * @var $enqueues
	 */
	protected $enqueues;

	/**
	 * Index.
	 *
	 * @var $metabox
	 */
	protected $metabox;

	/**
	 * Ajax.
	 *
	 * @var $algolia_ajax
	 */
	protected $algolia_ajax;

	/**
	 * Automatic Algolia sync on post save/delete.
	 *
	 * @var Algolia_Sync_Posts|null
	 */
	protected $sync_posts;

	/**
	 * Autocomplete.
	 *
	 * @var Autocomplete $autocomplete
	 */
	protected $autocomplete;

	/**
	 * Blocks.
	 *
	 * @var Algolia_Blocks $blocks
	 */
	protected $blocks;

	/**
	 * Admin Wizard.
	 *
	 * @var Admin_Wizard $wizard
	 */
	protected $wizard;

	/**
	 * Main WLC_Algolia Instance.
	 *
	 * Ensures only one instance of WLC_Algolia is loaded or can be loaded.
	 *
	 * @since 1.0.0
	 * @static
	 * @return WLC_Algolia - Main instance.
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * WLC_Algolia Constructor.
	 */
	public function __construct() {
		$this->includes();
		$this->init();
	}

	/**
	 * Include required core files used in admin and on the frontend.
	 */
	public function includes() {
		include_once WLC_ALGOLIA_PLUGIN_DIR_PATH . 'includes/helpers.php';

		/**
		 * Class autoloader.
		 */
		include_once WLC_ALGOLIA_PLUGIN_DIR_PATH . 'includes/classes/class-autoloader.php';
	}

	/**
	 * Init WLC_Algolia when WordPress Initialises.
	 */
	public function init() {
		$this->settings     = new Settings();
		$this->enqueues     = new Enqueues();
		$this->assets       = new Assets();
		$this->metabox      = new Algolia_Metabox();
		$this->algolia_ajax = new Algolia_Index_Ajax();
		$this->sync_posts   = new Algolia_Sync_Posts();
		$this->autocomplete = new Autocomplete();
		$this->blocks       = new Algolia_Blocks();
		$this->wizard       = new Admin_Wizard();

		$this->enqueues->hooks();
		$this->metabox->hooks();
		$this->algolia_ajax->hooks();
		$this->sync_posts->hooks();
		$this->autocomplete->init();
		$this->blocks->init();
		$this->wizard->hooks();

		// Prevent redirect for empty search query parameter (s=).
		add_action( 'template_redirect', array( $this, 'prevent_empty_search_redirect' ) );
	}

	/**
	 * Prevent redirect for empty search query parameter (s=).
	 * WordPress by default redirects empty search queries, but we want to allow them
	 * so that Algolia search blocks can handle the search on the frontend.
	 *
	 * @return void
	 */
	public function prevent_empty_search_redirect(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only checking if search param is empty for redirect logic.
		$search_query = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
		if ( '' === trim( $search_query ) ) {
			// Prevent WordPress from redirecting empty search queries.
			// This allows Algolia search blocks to handle the search on the frontend.
			add_filter( 'redirect_canonical', array( $this, 'disable_empty_search_redirect' ), 10, 2 );
		}
	}

	/**
	 * Disable redirect for empty search queries.
	 *
	 * @param string $redirect_url   The redirect URL.
	 * @param string $_requested_url The requested URL (unused; required by filter signature).
	 * @return string|false
	 */
	public function disable_empty_search_redirect( $redirect_url, $_requested_url ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only checking if search param is empty for redirect logic.
		$search_query = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
		if ( '' === trim( $search_query ) ) {
			return false;
		}
		return $redirect_url;
	}

	/**
	 * Gets plugin configuration.
	 *
	 * @param string $name Configuration name.
	 * @return array
	 */
	public function get_config( $name ) {
		if ( ! isset( $this->configs[ $name ] ) ) {
			$this->configs[ $name ] = array();

			$filepath = WLC_ALGOLIA_PLUGIN_DIR_PATH . 'includes/configs/' . helper\sanitize_slug( $name ) . '.php';

			if ( file_exists( $filepath ) ) {
				$this->configs[ $name ] = helper\merge_arrays( $this->configs[ $name ], include $filepath );
			}
		}

		return $this->configs[ $name ];
	}

	/**
	 * Get plugin version
	 */
	public function get_version() {
		return $this->version;
	}

	/**
	 * Get the plugin url.
	 *
	 * @return string
	 */
	public function plugin_url() {
		return untrailingslashit( WLC_ALGOLIA_PLUGIN_DIR_URL );
	}
}
