<?php
/**
 * Front end script class.
 *
 * @package HBFWC
 */

namespace HBFWC;

use Automattic\Jetpack\Constants;
use HBFWC_WC_Product_Accommodation;

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

/**
 * Class front-end scripts.
 */
class Frontend_Scripts {
	/**
	 * Contains an array of script handles registered by HBFWC.
	 *
	 * @var array
	 */
	private static $scripts = array();

	/**
	 * Contains an array of script handles registered by HBFWC.
	 *
	 * @var array
	 */
	private static $styles = array();

	/**
	 * Contains an array of script handles localized by HBFWC.
	 *
	 * @var array
	 */
	private static $wp_localize_scripts = array();

	/**
	 * Hook in methods.
	 */
	public static function init() {
		add_action( 'init', array( __CLASS__, 'js_translatable' ) );
		add_action( 'wp_enqueue_scripts', array( __CLASS__, 'load_scripts' ) );
	}

	/**
	 * Register the js translateable file.
	 */
	public static function js_translatable() {
		wp_set_script_translations( 'hbfwc-filter', 'hotel-booking-for-woocommerce' );
	}

	/**
	 * Register a script for use.
	 *
	 * @uses   wp_register_script()
	 * @param  string   $handle    Name of the script. Should be unique.
	 * @param  string   $path      Full URL of the script, or path of the script relative to the WordPress root directory.
	 * @param  string[] $deps      An array of registered script handles this script depends on.
	 * @param  string   $version   String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
	 * @param  boolean  $in_footer Whether to enqueue the script before </body> instead of in the <head>. Default 'false'.
	 */
	private static function register_script( $handle, $path, $deps = array( 'jquery' ), $version = HBFWC_VERSION, $in_footer = array( 'strategy' => 'defer' ) ) {
		self::$scripts[] = $handle;
		wp_register_script( $handle, $path, $deps, $version, $in_footer );
	}

	/**
	 * Register and enqueue a script for use.
	 *
	 * @uses   wp_enqueue_script()
	 * @param  string   $handle    Name of the script. Should be unique.
	 * @param  string   $path      Full URL of the script, or path of the script relative to the WordPress root directory.
	 * @param  string[] $deps      An array of registered script handles this script depends on.
	 * @param  string   $version   String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
	 * @param  boolean  $in_footer Whether to enqueue the script before </body> instead of in the <head>. Default 'false'.
	 */
	private static function enqueue_script( $handle, $path = '', $deps = array( 'jquery' ), $version = HBFWC_VERSION, $in_footer = array( 'strategy' => 'defer' ) ) {
		if ( ! in_array( $handle, self::$scripts, true ) && $path ) {
			self::register_script( $handle, $path, $deps, $version, $in_footer );
		}
		wp_enqueue_script( $handle );
	}

	/**
	 * Register a style for use.
	 *
	 * @uses   wp_register_style()
	 * @param  string   $handle  Name of the stylesheet. Should be unique.
	 * @param  string   $path    Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
	 * @param  string[] $deps    An array of registered stylesheet handles this stylesheet depends on.
	 * @param  string   $version String specifying stylesheet version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
	 * @param  string   $media   The media for which this stylesheet has been defined. Accepts media types like 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
	 * @param  boolean  $has_rtl If has RTL version to load too.
	 */
	private static function register_style( $handle, $path, $deps = array(), $version = HBFWC_VERSION, $media = 'all', $has_rtl = false ) {
		self::$styles[] = $handle;
		wp_register_style( $handle, $path, $deps, $version, $media );

		if ( $has_rtl ) {
			wp_style_add_data( $handle, 'rtl', 'replace' );
		}
	}

	/**
	 * Register and enqueue a styles for use.
	 *
	 * @uses   wp_enqueue_style()
	 * @param  string   $handle  Name of the stylesheet. Should be unique.
	 * @param  string   $path    Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
	 * @param  string[] $deps    An array of registered stylesheet handles this stylesheet depends on.
	 * @param  string   $version String specifying stylesheet version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added.
	 * @param  string   $media   The media for which this stylesheet has been defined. Accepts media types like 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
	 * @param  boolean  $has_rtl If has RTL version to load too.
	 */
	private static function enqueue_style( $handle, $path = '', $deps = array(), $version = HBFWC_VERSION, $media = 'all', $has_rtl = false ) {
		if ( ! in_array( $handle, self::$styles, true ) && $path ) {
			self::register_style( $handle, $path, $deps, $version, $media, $has_rtl );
		}
		wp_enqueue_style( $handle );
	}

	/**
	 * Get styles for the frontend.
	 *
	 * @return array
	 */
	public static function get_styles() {
		$version = Constants::get_constant( 'HBFWC_VERSION' );

		/**
		 * Filter list of HBFWC styles to enqueue.
		 */
		$styles = apply_filters(
			'hbfwc_enqueue_styles',
			array(
				'hbfwc' => array(
					'src'     => self::get_asset_url( 'assets/css/hbfwc.css' ),
					'deps'    => array( 'daterangepicker', 'hbfwc-fontawesome-6', 'hbfwc-fontawesome-6-brands', 'hbfwc-ionicons', 'hbfwc-themify' ),
					'version' => $version,
					'media'   => 'all',
					'has_rtl' => false,
				),
			)
		);
		return is_array( $styles ) ? array_filter( $styles ) : array();
	}

	/**
	 * Return asset URL.
	 *
	 * @param string $path Assets path.
	 * @return string
	 */
	private static function get_asset_url( $path ) {
		return apply_filters( 'hbfwc_get_asset_url', plugins_url( $path, HBFWC_FILE ), $path );
	}

	/**
	 * Register all HBFWC styles.
	 */
	private static function register_styles() {
		$version = Constants::get_constant( 'HBFWC_VERSION' );

		$register_styles = array(
			'hbfwc-fontawesome-6'        => array(
				'src'     => self::get_asset_url( 'assets/css/libs/font-awesome-6.min.css' ),
				'deps'    => array(),
				'version' => $version,
				'has_rtl' => false,
			),
			'hbfwc-fontawesome-6-brands' => array(
				'src'     => self::get_asset_url( 'assets/css/libs/font-awesome-6-brands.min.css' ),
				'deps'    => array(),
				'version' => $version,
				'has_rtl' => false,
			),
			'hbfwc-ionicons'             => array(
				'src'     => self::get_asset_url( 'assets/css/libs/ionicons.min.css' ),
				'deps'    => array(),
				'version' => $version,
				'has_rtl' => false,
			),
			'hbfwc-themify'              => array(
				'src'     => self::get_asset_url( 'assets/css/libs/themify-icons.min.css' ),
				'deps'    => array(),
				'version' => $version,
				'has_rtl' => false,
			),
			'daterangepicker'            => array(
				'src'     => self::get_asset_url( 'assets/css/daterangepicker.css' ),
				'deps'    => array(),
				'version' => $version,
				'has_rtl' => false,
			),
			'hbfwc-cart'                 => array(
				'src'     => self::get_asset_url( 'assets/client/blocks/cart.css' ),
				'deps'    => array(),
				'version' => $version,
				'has_rtl' => false,
			),
		);
		foreach ( $register_styles as $name => $props ) {
			self::register_style( $name, $props['src'], $props['deps'], $props['version'], 'all', $props['has_rtl'] );
		}
	}

	/**
	 * Register all HBFWC scripts.
	 */
	private static function register_scripts() {
		$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
		$version = Constants::get_constant( 'HBFWC_VERSION' );

		$register_scripts = array(
			'hbfwc-daterangepicker' => array(
				'src'     => self::get_asset_url( 'assets/js/daterangepicker' . $suffix . '.js' ),
				'deps'    => array( 'jquery', 'moment' ),
				'version' => '3.1.0.hbfwc-' . $version,
			),
			'hbfwc-booking'         => array(
				'src'     => self::get_asset_url( 'assets/js/hbfwc.js' ),
				'deps'    => array( 'jquery', 'moment', 'hbfwc-daterangepicker', 'wc-blocks-data-store', 'wp-i18n' ),
				'version' => 'hbfwc-' . $version,
				'args'    => array( 'in_footer' => true ),
			),
			'hbfwc-filter'          => array(
				'src'     => self::get_asset_url( 'assets/js/hbfwc-filter.js' ),
				'deps'    => array( 'jquery', 'moment', 'hbfwc-daterangepicker', 'flexslider', 'wc-blocks-data-store', 'wp-i18n' ),
				'version' => 'hbfwc-' . $version,
				'args'    => array( 'in_footer' => true ),
			),
		);
		foreach ( $register_scripts as $name => $props ) {
			self::register_script( $name, $props['src'], $props['deps'], $props['version'], ( $props['args'] ?? [] ) );
		}
	}

	/**
	 * Register/queue frontend scripts.
	 */
	public static function load_scripts() {
		global $post, $product;

		if ( ! did_action( 'before_woocommerce_init' ) ) {
			return;
		}

		self::register_styles();
		self::register_scripts();

		$disabled_css = apply_filters( 'woocommerce_hbfwc_disabled_frontend_css', false );

		if ( is_product() && ! is_object( $product ) ) {
			$product = \wc_get_product( get_the_ID() );
		}

		if ( $product instanceof HBFWC_WC_Product_Accommodation ) {
			self::enqueue_script( 'hbfwc-booking' );
			$b_params = array(
				'invalid_dates' => $product->get_invalid_dates(),
				'cal_string'    => self::get_translation_cal(),
			);
			wp_localize_script( 'hbfwc-booking', 'hbfwc', $b_params );
		}

		if ( is_cart() || is_checkout() || is_account_page() ) {
			if ( ! $disabled_css ) {
				self::enqueue_style( 'hbfwc-cart' );
			}
		}

		if ( ( ! empty( $post->post_content ) && strstr( $post->post_content, '[hbfwc_' ) ) || has_block( 'hbfwc/search-form', $post ) || has_block( 'hbfwc/availability', $post ) ) {
			self::enqueue_script( 'hbfwc-filter' );
			$params = array(
				'ajax_url'         => admin_url( 'admin-ajax.php' ),
				'rest_add_cart'    => get_rest_url( null, '/wc/store/v1/cart/add-item' ),
				'rest_remove_item' => get_rest_url( null, '/wc/store/v1/cart/remove-item' ),
				'rest_update_item' => get_rest_url( null, '/wc/store/v1/cart/update-item' ),
				'rest_nonce'       => wp_create_nonce( 'wc_store_api' ),
				'cal_string'       => self::get_translation_cal(),
			);
			wp_localize_script( 'hbfwc-filter', 'hbfwc', $params );

			$all_addon_posts = \hbfwc_get_available_booking_addon();
			$room_ids_key    = apply_filters( 'hbfwc_booking_addon_room_ids_key', 'room_ids' );
			$addon_perbook   = apply_filters( 'hbfwc_booking_addon_perbook_key', 'booking' );

			$addons = array_filter( array_map( function( $addon ) use ( $room_ids_key, $addon_perbook ) {
				if ( get_post_meta( $addon->ID, '_addon_type', true ) === 'fixed' &&
					get_post_meta( $addon->ID, 'sub_type', true ) === $addon_perbook ) {
					return null;
				}

				$ids = get_post_meta( $addon->ID, $room_ids_key, true );
				$ids = ! is_array( $ids ) ? [] : $ids;
				if ( count( $ids ) === 1 && 0 === intval($ids[0]) ) {
					$ids = [];
				}
				return [
					'id'          => $addon->ID,
					'sub_type'    => get_post_meta( $addon->ID, 'sub_type', true ),
					'title'       => get_the_title( $addon ),
					'description' => get_post_meta( $addon->ID, 'description', true ),
					'price'       => \hbfwc_price_to_float( get_post_meta( $addon->ID, 'price', true ) ),
					'price_html'  => wc_price( \hbfwc_price_to_float( get_post_meta( $addon->ID, 'price', true ) ) ),
					'type'        => get_post_meta( $addon->ID, '_addon_type', true ),
					'unit'        => get_post_meta( $addon->ID, 'unit', true ),
					'min'         => absint( get_post_meta( $addon->ID, 'min', true ) ),
					'max'         => absint( get_post_meta( $addon->ID, 'max', true ) ),
					'by_guests'   => false,
					'by_nights'   => false,
					'required'    => ( get_post_meta( $addon->ID, 'required', true ) === 'yes' ? true : false ),
					'room_ids'    => $ids
				];
			}, $all_addon_posts ) );
			$addon_localize_script = apply_filters( 'hbfwc_booking_addon_localize_script', array_values( $addons ), $all_addon_posts );

			wp_localize_script( 'hbfwc-filter', 'hbfwcAddons', $addon_localize_script );
		}

		$enqueue_styles = self::get_styles();
		if ( $enqueue_styles && ! $disabled_css ) {
			foreach ( $enqueue_styles as $handle => $args ) {
				if ( ! isset( $args['has_rtl'] ) ) {
					$args['has_rtl'] = false;
				}

				self::enqueue_style( $handle, $args['src'], $args['deps'], $args['version'], $args['media'], $args['has_rtl'] );
			}

			wp_add_inline_style(
				'hbfwc',
				':root{--hbfwc-cart-room-label:' . wp_json_encode( _x( 'room(s)', 'Cart quantity label for a single accommodation item', 'hotel-booking-for-woocommerce' ) ) . ';}'
			);
		}
	}

	private static function get_translation_cal() {
		$month_names = [ __( 'January', 'hotel-booking-for-woocommerce' ), __( 'February', 'hotel-booking-for-woocommerce' ), __( 'March', 'hotel-booking-for-woocommerce' ), __( 'April', 'hotel-booking-for-woocommerce' ), __( 'May', 'hotel-booking-for-woocommerce' ), __( 'June', 'hotel-booking-for-woocommerce' ), __( 'July', 'hotel-booking-for-woocommerce' ), __( 'August', 'hotel-booking-for-woocommerce' ), __( 'September', 'hotel-booking-for-woocommerce' ), __( 'October', 'hotel-booking-for-woocommerce' ), __( 'November', 'hotel-booking-for-woocommerce' ), __( 'December', 'hotel-booking-for-woocommerce' ) ];

		return [
			'date_l' => [ __( 'Sunday', 'hotel-booking-for-woocommerce' ), __( 'Monday', 'hotel-booking-for-woocommerce' ), __( 'Tuesday', 'hotel-booking-for-woocommerce' ), __( 'Wednesday', 'hotel-booking-for-woocommerce' ), __( 'Thursday', 'hotel-booking-for-woocommerce' ), __( 'Friday', 'hotel-booking-for-woocommerce'), __( 'Saturday', 'hotel-booking-for-woocommerce' ) ],
			'date_D' => [ __( 'Sun', 'hotel-booking-for-woocommerce' ), __( 'Mon', 'hotel-booking-for-woocommerce' ), __('Tue', 'hotel-booking-for-woocommerce' ), __( 'Wed', 'hotel-booking-for-woocommerce' ), __( 'Thr', 'hotel-booking-for-woocommerce' ), __( 'Fri', 'hotel-booking-for-woocommerce' ), __( 'Sat', 'hotel-booking-for-woocommerce' ) ],
			'date_F' => $month_names,
			'date_M' => [ __( 'Jan', 'hotel-booking-for-woocommerce' ), __( 'Feb', 'hotel-booking-for-woocommerce' ), __( 'Mar', 'hotel-booking-for-woocommerce' ), __( 'Apr', 'hotel-booking-for-woocommerce' ), __( 'May', 'hotel-booking-for-woocommerce' ), __( 'Jun', 'hotel-booking-for-woocommerce' ), __( 'Jul', 'hotel-booking-for-woocommerce' ), __( 'Aug', 'hotel-booking-for-woocommerce' ), __( 'Sep', 'hotel-booking-for-woocommerce' ), __( 'Oct', 'hotel-booking-for-woocommerce' ), __( 'Nov', 'hotel-booking-for-woocommerce' ), __( 'Dec', 'hotel-booking-for-woocommerce' ) ],
			'locale' => [
				'daysOfWeek' => [
					_x( 'Su', 'Abbreviations for the days of the week: Sunday', 'hotel-booking-for-woocommerce' ),
					_x( 'Mo', 'Abbreviations for the days of the week: Monday', 'hotel-booking-for-woocommerce' ),
					_x( 'Tu', 'Abbreviations for the days of the week: Tuesday', 'hotel-booking-for-woocommerce' ),
					_x( 'We', 'Abbreviations for the days of the week: Wednesday', 'hotel-booking-for-woocommerce' ),
					_x( 'Th', 'Abbreviations for the days of the week: Thursday', 'hotel-booking-for-woocommerce' ),
					_x( 'Fr', 'Abbreviations for the days of the week: Friday', 'hotel-booking-for-woocommerce' ),
					_x( 'Sa', 'Abbreviations for the days of the week: Saturday', 'hotel-booking-for-woocommerce' ),
				],
				'monthNames' => $month_names,
			],
		];
	}
}

Frontend_Scripts::init();
