<?php
namespace TotalTheme\Integration\WooCommerce;

use TotalTheme\Theme_Icons;

defined( 'ABSPATH' ) || exit;

/**
 * Perform all main WooCommerce configurations for this theme.
 *
 * @package TotalTheme
 * @subpackage Integration/WooCommerce
 * @version 5.5
 */
final class WooCommerce_Advanced {

	/**
	 * Instance.
	 */
	private static $instance;

	/**
	 * Create or retrieve the instance of WooCommerce_Advanced.
	 */
	public static function instance() {
		if ( is_null( static::$instance ) ) {
			static::$instance = new self();
			static::$instance->define_constants();
			static::$instance->include_functions();
			static::$instance->initiate_classes();
			static::$instance->init_hooks();
		}

		return static::$instance;
	}

	/**
	 * Define constants.
	 */
	public function define_constants() {
		define( 'WPEX_WOO_CONFIG_DIR', WPEX_INC_DIR . 'integration/woocommerce/' );
	}

	/**
	 * Include functions.
	 */
	public function include_functions() {
		require_once WPEX_WOO_CONFIG_DIR . 'actions.php';
		require_once WPEX_WOO_CONFIG_DIR . 'function-overrides.php';
		require_once WPEX_WOO_CONFIG_DIR . 'menu-cart.php';
	}

	/**
	 * Initiate classes.
	 */
	public function initiate_classes() {
		if ( apply_filters( 'wpex_woocommerce_maybe_modify_product_entry', true ) ) {
			Product_Entry::instance();
		}

		if ( apply_filters( 'wpex_woocommerce_maybe_modify_product_gallery', true ) ) {
			Product_Gallery::instance();
		}

		if ( ! get_theme_mod( 'woo_dynamic_image_resizing', false ) ) {
			Thumbnails::instance();
		}
	}

	/**
	 * Hook into actions and filters.
	 */
	public function init_hooks() {

		// Add theme support.
		add_action( 'after_setup_theme', array( $this, 'theme_support' ) );

		// Add Customizer settings.
		add_filter( 'wpex_customizer_panels', array( $this, 'customizer_settings' ) );

		// These filters/actions must run on init.
		add_action( 'init', array( $this, 'init' ) );

		// Disable WooCommerce main page title.
		add_filter( 'woocommerce_show_page_title', '__return_false' );

		// Remove Woo Styles.
		// Can be disabled by the filter or by disabling Advanced Integration via the Total theme panel.
		if ( $this->maybe_remove_styles() ) {
			add_action( 'woocommerce_enqueue_styles', array( $this, 'disable_styles' ), PHP_INT_MAX );
		}

		// Load customs scripts.
		add_action( 'wp_enqueue_scripts', array( $this, 'add_custom_scripts' ) );

		// Alter the sale tag.
		add_filter( 'woocommerce_sale_flash', array( $this, 'woocommerce_sale_flash' ), 10, 3 );

		// Alter shop posts per page.
		add_filter( 'loop_shop_per_page', array( $this, 'loop_shop_per_page' ), 20 );

		// Alter shop columns.
		add_filter( 'loop_shop_columns', array( $this, 'loop_shop_columns' ) );

		// Tweak Woo pagination args.
		add_filter( 'woocommerce_pagination_args', array( $this, 'pagination_args' ) );

		// Alter shop page redirect.
		add_filter( 'woocommerce_continue_shopping_redirect', array( $this, 'continue_shopping_redirect' ) );

		// Alter product tag cloud widget args
		add_filter( 'woocommerce_product_tag_cloud_widget_args', array( $this, 'tag_cloud_widget_args' ) );

		// Add new typography settings.
		add_filter( 'wpex_typography_settings', array( $this, 'typography_settings' ), 60 );

		// Alter the comment form args.
		add_filter( 'woocommerce_product_review_comment_form_args', array( $this, 'comment_form_args' ) );

		// Alter orders per-page on account page.
		add_filter( 'woocommerce_my_account_my_orders_query', array( $this, 'woocommerce_my_account_my_orders_query' ) );

		// Alter WooCommerce shop notice to add an SVG for the close icon.
		add_filter( 'woocommerce_demo_store', __CLASS__ . '::woocommerce_demo_store' );

		if ( '{{title}}' === get_theme_mod( 'woo_shop_single_title' ) && ! is_customize_preview() ) {
			remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );
		}

	} // End init_hooks

	/*-------------------------------------------------------------------------------*/
	/* - Start Class Functions
	/*-------------------------------------------------------------------------------*/

	/**
	 * Add theme support.
	 */
	public function theme_support() {
		add_theme_support( 'woocommerce' );
	}

	/**
	 * Adds Customizer settings for WooCommerce.
	 */
	public function customizer_settings( $panels ) {
		$branding = ( $branding = wpex_get_theme_branding() ) ? ' (' . $branding . ')' : '';
		$panels['woocommerce'] = array(
			'title'    => 'WooCommerce' . $branding,
			'settings' => WPEX_WOO_CONFIG_DIR . 'customize/advanced-settings.php'
		);
		return $panels;
	}

	/**
	 * Run actions on init.
	 */
	public function init() {
		$is_customize_preview = is_customize_preview();

		// Remove single meta.
		if ( ! $is_customize_preview && ! get_theme_mod( 'woo_product_meta', true ) ) {
			remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40 );
		}

		// Remove result count if disabled.
		if ( ! $is_customize_preview && ! get_theme_mod( 'woo_shop_result_count', true ) ) {
			remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
		}

		// Remove orderby if disabled.
		if ( ! $is_customize_preview && ! get_theme_mod( 'woo_shop_sort', true ) ) {
			remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
		}

		// Move tabs.
		// Add after meta which is set to 40.
		if ( 'right' === get_theme_mod( 'woo_product_tabs_position' ) ) {
			remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_product_data_tabs', 10 );
			add_action( 'woocommerce_single_product_summary', 'woocommerce_output_product_data_tabs', 41 );
		}

	}

	/**
	 * Add Custom scripts.
	 */
	public function add_custom_scripts() {

		if ( $this->maybe_remove_styles() ) {
			wp_enqueue_style(
				'wpex-woocommerce',
				wpex_asset_url( 'css/wpex-woocommerce.css' ),
				array(),
				WPEX_THEME_VERSION
			);
			wp_style_add_data( 'wpex-woocommerce', 'rtl', 'replace' );
		}

		if ( apply_filters( 'wpex_custom_woo_scripts', true ) ) {
			wp_enqueue_script(
				'wpex-wc-functions',
				wpex_asset_url( 'js/dynamic/woocommerce/wpex-wc-functions.min.js' ),
				array( 'jquery' ),
				WPEX_THEME_VERSION,
				true
			);

			$quantity_style = get_theme_mod( 'woo_quantity_buttons_style', 'vertical' );

			if ( 'disabled' !== $quantity_style || 'browser' !== $quantity_style ) {

				switch ( $quantity_style ) {
					case 'horizontal':
						$plus_icon = 'material/add';
						$minus_icon = 'material/remove';
						break;
					case 'vertical':
					default:
						$plus_icon = 'angle-up';
						$minus_icon = 'angle-down';
						break;
				}

				$plus_icon  = (string) apply_filters( 'wpex_woocommerce_quantity_button_plus_icon', $plus_icon );
				$minus_icon = (string) apply_filters( 'wpex_woocommerce_quantity_button_minus_icon', $minus_icon );

				$script_data = [
					'quantityButtons' => [
						'style'      => $quantity_style,
						'targets'    => 'div.quantity:not(.buttons_added), td.quantity:not(.buttons_added)',
						'plusIcon'   => wpex_get_theme_icon_html( $plus_icon, 'wpex-quantity-btns__icon' ),
						'minusIcon'  => wpex_get_theme_icon_html( $minus_icon, 'wpex-quantity-btns__icon' ),
						'minusLabel' => esc_attr__( 'remove 1', 'total' ),
						'plusLabel'  => esc_attr__( 'add 1', 'total' ),
					],
				];

			}

			if ( $this->has_added_to_cart_notice() ) {
				$notice = esc_html__( 'was added to your shopping cart.', 'total' );
				$script_data['addedToCartNotice'] = apply_filters( 'wpex_woocommerce_added_to_cart_notice', $notice );
			}

			wp_localize_script(
				'wpex-wc-functions',
				'wpex_wc_params',
				$script_data
			);
		}

	}

	/**
	 * Change onsale text.
	 */
	public function woocommerce_sale_flash( $text, $post, $_product ) {
		$text = wpex_get_translated_theme_mod( 'woo_sale_flash_text' );
		if ( ! $text ) {
			$text = esc_html__( 'Sale', 'total' );
		}
		return '<span class="onsale">' . esc_html( $text ) . '</span>';
	}

	/**
	 * Returns correct posts per page for the shop.
	 */
	public function loop_shop_per_page() {
		$posts_per_page = get_theme_mod( 'woo_shop_posts_per_page' );
		if ( ! $posts_per_page ) {
			$posts_per_page = '12';
		}
		return $posts_per_page;
	}

	/**
	 * Change products per row for the main shop.
	 */
	public function loop_shop_columns() {
		$columns = wpex_get_array_first_value( get_theme_mod( 'woocommerce_shop_columns', '4' ) );
		if ( ! $columns ) {
			$columns = '4'; // always needs a fallback.
		}
		return $columns;
	}

	/**
	 * Tweaks pagination arguments.
	 */
	public function pagination_args( $args ) {
		$arrow_style = get_theme_mod( 'pagination_arrow' ) ?: 'angle';
		$args['prev_text'] = Theme_Icons::get_icon( $arrow_style . '-left' );
		$args['next_text'] = Theme_Icons::get_icon( $arrow_style . '-right' );
		return $args;
	}

	/**
	 * Alter continue shoping URL.
	 */
	public function continue_shopping_redirect( $return_to ) {
		$shop_id = wc_get_page_id( 'shop' );
		if ( $shop_id ) {
			$shop_id = wpex_parse_obj_id( $shop_id, 'page' );
			$return_to = get_permalink( $shop_id );
		}
		return $return_to;
	}

	/**
	 * Alter product tag cloud widget args.
	 */
	public function tag_cloud_widget_args( $args ) {
		$args['largest']  = '1';
		$args['smallest'] = '1';
		$args['unit']     = 'em';
		return $args;
	}

	/**
	 * Add typography options for the WooCommerce product title.
	 */
	public function typography_settings( $settings ) {
		$settings['woo_entry_title'] = array(
			'label' => esc_html__( 'WooCommerce Entry Title', 'total' ),
			'target' => '.woocommerce ul.products li.product .woocommerce-loop-product__title,.woocommerce ul.products li.product .woocommerce-loop-category__title',
			'margin' => true,
		);
		$settings['woo_product_title'] = array(
			'label' => esc_html__( 'WooCommerce Product Title', 'total' ),
			'target' => '.woocommerce div.product .product_title',
			'margin' => true,
		);
		$settings['woo_upsells_related_title'] = array(
			'label' => esc_html__( 'WooCommerce Section Heading', 'total' ),
			'target' => '.up-sells > h2, .related.products > h2, .woocommerce-tabs .panel > h2',
			'margin' => true,
		);
		return $settings;
	}

	/**
	 * Tweak comment form args.
	 */
	public function comment_form_args( $args ) {
		$args['title_reply'] = esc_html__( 'Leave a customer review', 'total' );
		$args['title_reply_before'] = '<span id="reply-title" class="comment-reply-title wpex-heading wpex-text-lg">';
		return $args;
	}

	/**
	 * Alter orders per-page on account page.
	 */
	public function woocommerce_my_account_my_orders_query( $args ) {
		$args['limit'] = 20;
		return $args;
	}

	/**
	 * Check if we should remove the core WooCommerce styles.
	 */
	public function maybe_remove_styles() {
		return (bool) apply_filters( 'wpex_custom_woo_stylesheets', true ); // @todo rename filter
	}

	/**
	 * Check if the added to cart notice is enabled.
	 */
	public function has_added_to_cart_notice() {
		if ( get_theme_mod( 'woo_show_entry_add_to_cart', true )
			&& get_theme_mod( 'woo_added_to_cart_notice', true )
		) {
			return true;
		}
	}

	/**
	 * Disable WooCommerce Styles.
	 */
	public function disable_styles( $styles ) {
		if ( is_array( $styles ) ) {
			unset( $styles['woocommerce-general'] );
			unset( $styles['woocommerce-layout'] );
			unset( $styles['woocommerce-smallscreen'] );
		}
		return $styles;
	}

	/**
	 * Alter WooCommerce shop notice to add an SVG for the close icon.
	 */
	public static function woocommerce_demo_store( $notice ) {
		$notice = get_option( 'woocommerce_demo_store_notice' );
		if ( $notice ) {
			$notice_id = md5( $notice );
			$notice = '<p class="woocommerce-store-notice demo_store" data-notice-id="' . esc_attr( $notice_id ) . '" style="display:none;">' . wp_kses_post( $notice ) . '<a href="#" class="woocommerce-store-notice__dismiss-link"><span class="screen-reader-text">' . esc_html__( 'Dismiss', 'woocommerce' ) . '</span>' . wpex_get_svg( 'close', 20 ) . '</a></p>';
		}
		return $notice;
	}

}