<?php
/**
 * Compatibility with YITH WooCommerce Role Based Prices
 *
 * @package YITH WooCommerce Dynamic Pricing & Discounts Premium
 * @since   1.0.0
 * @version 1.6.0
 * @author  YITH <plugins@yithemes.com>
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}
/**
 * Add the integration with Role Based Plugin
 *
 * @class   YITH_YWDPD_Role_Based_Prices_Integration
 * @package YITH WooCommerce Dynamic Pricing & Discounts
 * @since   1.0.0
 */
if ( ! class_exists( 'YITH_YWDPD_Role_Based_Prices_Integration' ) ) {

	/**
	 * Class YITH_YWDPD_Role_Based_Prices_Integration
	 */
	class YITH_YWDPD_Role_Based_Prices_Integration {

		/**
		 * The role based instance
		 *
		 * @var YITH_Role_Based_Prices_Product
		 */
		protected $rolebased;
		/**
		 * The dynamic frontend instance
		 *
		 * @var YWDPD_Frontend
		 */
		protected $dynamic_frontend;


		/**
		 * The role based helper from 2.0
		 *
		 * @var YITH_WCRBP_Price_Rule_Helper
		 */
		protected $role_helper;

		/**
		 * Constructor
		 *
		 * Initialize class and registers actions and filters to be used
		 *
		 * @since  3.0.0
		 */
		public function __construct() {

			$this->rolebased        = YITH_Role_Based_Prices_Product();
			$this->dynamic_frontend = ywdpd_dynamic_pricing_discounts()->get_frontend_manager();

			if ( version_compare( YWCRBP_VERSION, '2.0.0', '>=' ) ) {
				$this->role_helper = yith_wcrbp_price_rule_helper();
				add_filter( 'ywdpd_change_base_price', array( $this, 'use_rolebased_price' ), 20, 2 );
				add_filter( 'ywcrbp_pre_get_your_price_html_args', array( $this, 'get_product_price_for_role_html' ), 10, 7 );
				add_filter( 'ywcrbp_pre_get_regular_price_html', array( $this, 'get_regular_price_html' ), 10, 2 );
				add_filter( 'ywcrbp_pre_get_sale_price_html', array( $this, 'get_sale_price_html' ), 10, 2 );
				add_filter( 'ywdpd_product_price_classes', array( $this, 'change_product_price_class' ) );
			} else {
				add_filter( 'ywdpd_change_base_price', array( $this, 'set_rolebased_as_base_price' ), 20, 2 );
				add_filter( 'ywdpd_get_new_price_html', array( $this, 'get_new_price_html' ), 20, 4 );
				add_filter( 'ywdpd_get_variable_price_html', array( $this, 'get_variable_price_html' ), 20, 6 );
				add_filter( 'ywdpd_cart_item_display_price', array( $this, 'set_role_based_price' ), 20, 2 );
			}
		}

		/**
		 * Change the default price in to role based prices
		 *
		 * @param float      $price The original price.
		 * @param WC_Product $product The product.
		 *
		 * @return float
		 * @since 4.0.0
		 */
		public function use_rolebased_price( $price, $product ) {

			$role_price = $this->role_helper->get_current_product_price( $product, true );

			if ( 'no_price' !== $role_price ) {
				$price = $role_price;
			} else {
				$type_rule = get_option( 'ywcrbp_apply_rule', 'regular' );

				if ( 'on_sale' === $type_rule && $product->is_on_sale() ) {
					$price = $product->get_sale_price();
				} else {
					$price = $product->get_regular_price();
				}
			}

			return $price;
		}

		/**
		 * Return the right product price to show in the product page
		 *
		 * @param array      $args The template args.
		 * @param string     $your_price_html price html.
		 * @param float      $role_price The new price.
		 * @param float      $display_role_price The new price for display.
		 * @param WC_Product $product The product.
		 * @param bool       $display_price Show price for display.
		 * @param string     $message The message.
		 *
		 * @return array
		 */
		public function get_product_price_for_role_html( $args, $your_price_html, $role_price, $display_role_price, $product, $display_price, $message ) {
			$dynamic_price = $this->dynamic_frontend->get_dynamic_price( $role_price, $product );

			if ( $dynamic_price !== $role_price ) {
				$discount         = $this->rolebased->calculate_total_discount( $product, $dynamic_price );
				$args['discount'] = $discount;
				if ( ! empty( $message ) ) {
					$message         = $this->rolebased->get_total_discount_markup_formatted( $product, $discount );
					$args['message'] = $message;
				}
				if ( $display_price ) {
					$dynamic_price = wc_get_price_to_display(
						$product,
						array(
							'qty'   => 1,
							'price' => $dynamic_price,
						)
					);
				}

				$your_price_html = wc_format_sale_price( $display_role_price, $dynamic_price ) . $this->rolebased->get_price_suffix( $product, $dynamic_price );
				$args['price']   = $your_price_html;
			}

			return $args;
		}

		/**
		 * Return the dynamic regular price of the product to be displayed
		 *
		 * @param float      $regular_price The regular price of the product.
		 * @param WC_Product $product The current product.
		 * @return float
		 */
		public function get_regular_price_html( $regular_price, $product ) {
			$dynamic_price = $this->dynamic_frontend->get_dynamic_price( $regular_price, $product );
			return $regular_price !== $dynamic_price ? $dynamic_price : $regular_price;
		}

		/**
		 * Return the dynamic sale price of the product to be displayed
		 *
		 * @param float      $sale_price The sale price of the product.
		 * @param WC_Product $product The current product.
		 * @return float
		 */
		public function get_sale_price_html( $sale_price, $product ) {
			$dynamic_price = $this->dynamic_frontend->get_dynamic_price( $sale_price, $product );
			return $sale_price !== $dynamic_price ? $dynamic_price : $sale_price;
		}

		/**
		 * Change the css class for the quantity table
		 *
		 * @return string
		 */
		public function change_product_price_class() {
			return '.ywcrbp-role-price-rule.single-product .role-price .price';
		}

		/**
		 * Remove the role based hooks
		 *
		 * @since 3.0.0
		 */
		protected function remove_rolebased_hooks() {
			remove_filter( 'woocommerce_get_price_html', array( $this->rolebased, 'get_price_html' ), 11 );
			remove_filter( 'woocommerce_get_variation_price_html', array( $this->rolebased, 'get_price_html' ), 11 );
		}

		/**
		 * Remove the role based hooks
		 *
		 * @since 3.0.0
		 */
		protected function add_rolebased_hooks() {
			add_filter( 'woocommerce_get_price_html', array( $this->rolebased, 'get_price_html' ), 11, 2 );
			add_filter( 'woocommerce_get_variation_price_html', array( $this->rolebased, 'get_price_html' ), 11, 2 );
		}

		/**
		 * Change the default price in to role based prices
		 *
		 * @param float      $price The original price.
		 * @param WC_Product $product The product.
		 *
		 * @return float
		 * @since 3.0.0
		 */
		public function set_rolebased_as_base_price( $price, $product ) {

			$role_price = $this->rolebased->get_role_based_price( $product );
			if ( 'no_price' !== $role_price ) {
				$price = $role_price;
			} else {
				$type_rule = get_option( 'ywcrbp_apply_rule', 'regular' );

				if ( 'on_sale' === $type_rule && $product->is_on_sale() ) {
					$price = $product->get_sale_price();
				} else {
					$price = $product->get_regular_price();
				}
			}

			return $price;
		}

		/**
		 * Show the price with the role based format
		 *
		 * @param string     $price_html The price html.
		 * @param float      $old_price The old price.
		 * @param float      $new_price The new price.
		 * @param WC_Product $product The product.
		 *
		 * @return string
		 * @since 3.0.0
		 */
		public function get_new_price_html( $price_html, $old_price, $new_price, $product ) {
			$this->remove_rolebased_hooks();
			$has_role_price = false;

			if ( 'variable' !== $product->get_type() ) {
				$role_price = $this->rolebased->get_role_based_price( $product );

				$this->rolebased->init_user_info();
				$regular_price      = $product->get_regular_price();
				$sale_price         = $product->get_sale_price();
				$show_regular_price = $this->rolebased->user_role['show_regular_price'];
				$show_on_sale_price = $this->rolebased->user_role['show_on_sale_price'];
				$show_your_price    = $this->rolebased->user_role['show_your_price'];

				$regular_price_html = '';
				$sale_price_html    = '';

				if ( 'no_price' === $role_price && $show_your_price ) {
					return $price_html;
				}
				if ( $show_regular_price ) {
					if ( 'no_price' !== $role_price ) {
						$regular_price_html = $this->rolebased->get_regular_price_html( $product, $regular_price );
						$show_del           = ( $show_on_sale_price && $product->is_on_sale( 'edit' ) && ( $regular_price !== $sale_price ) ) || ( $show_your_price && 'no_price' !== $role_price && ( floatval( $regular_price ) !== floatval( $role_price ) ) );
						$regular_price_html = $this->rolebased->get_formatted_price_html( $regular_price_html, $show_del, 'regular' );
					} else {
						$regular_prefix = get_option( 'ywcrbp_regular_price_txt' );

						if ( $show_on_sale_price && $product->is_on_sale() ) {

							$regular_price_html = $this->rolebased->get_regular_price_html( $product, $regular_price );
							$regular_price_html = $this->rolebased->get_formatted_price_html( $regular_price_html, true, 'regular' );
						} else {
							$regular_price_html = $regular_prefix . ' ' . $price_html;

						}
					}
				}

				if ( $show_on_sale_price && $product->is_on_sale( 'edit' ) ) {

					$sale_price_html = $this->rolebased->get_sale_price_html( $product, $sale_price );

					$show_del = ( $show_your_price && ( 'no_price' !== $role_price && $sale_price !== $role_price ) ) || 'no_price' === $role_price;

					$sale_price_html = $this->rolebased->get_formatted_price_html( $sale_price_html, $show_del, 'sale' );

					if ( 'no_price' === $role_price ) {
						$sale_price_html .= $price_html;
					}
				}

				$their_price_html = $this->rolebased->get_formatted_price_html( $this->rolebased->get_their_price_html( $product ), false, 'their' );

				if ( 'no_price' === $role_price ) {
					$price_html = $regular_price_html . $sale_price_html . $their_price_html;

				} else {
					$display_old_price = wc_get_price_to_display(
						$product,
						array(
							'qty'   => 1,
							'price' => $old_price,
						)
					);
					$display_new_price = wc_get_price_to_display(
						$product,
						array(
							'qty'   => 1,
							'price' => $new_price,
						)
					);
					$role_price_html   = wc_format_sale_price( $display_old_price, $display_new_price ) . $this->rolebased->get_price_suffix( $product, $new_price );
					$price_html        = $regular_price_html . $sale_price_html . get_option( 'ywcrbp_your_price_txt' ) . ' ' . $role_price_html . ' ' . $their_price_html;
				}

				$has_role_price = 'no_price' !== $role_price;
				$price_html     = apply_filters( 'ywdpd_role_based_price_product', $price_html, $has_role_price, $product );
			}

			add_filter( 'yith_wcrbp_return_original_price', '__return_true' );
			if ( $has_role_price ) {
				$this->add_rolebased_hooks();
			}

			return $price_html;
		}

		/**
		 * Show the variable price with the role based format
		 *
		 * @param string              $price_html The price html.
		 * @param float               $min_price The min price.
		 * @param float               $max_price The max price.
		 * @param float               $min_dynamic_price The min dynamic price.
		 * @param float               $max_dynamic_price The max dynamic price.
		 * @param WC_Product_Variable $product The product.
		 *
		 * @return string
		 * @since 3.0.0
		 */
		public function get_variable_price_html( $price_html, $min_price, $max_price, $min_dynamic_price, $max_dynamic_price, $product ) {
			$this->remove_rolebased_hooks();
			$role_prices        = $this->rolebased->get_variation_new_prices( $product, true );
			$min_role_price     = current( $role_prices );
			$max_role_price     = end( $role_prices );
			$min_regular_price  = $product->get_variation_regular_price( 'min', true );
			$max_regular_price  = $product->get_variation_regular_price( 'max', true );
			$min_sale_price     = $product->get_variation_sale_price( 'min', true );
			$max_sale_price     = $product->get_variation_sale_price( 'max', true );
			$show_regular_price = $this->rolebased->user_role['show_regular_price'];
			$show_on_sale_price = $this->rolebased->user_role['show_on_sale_price'];
			$show_your_price    = $this->rolebased->user_role['show_your_price'];

			$has_role_price     = count( $role_prices ) > 0;
			$regular_price_html = '';
			$sale_price_html    = '';
			if ( $show_regular_price ) {
				$regular_price_txt  = get_option( 'ywcrbp_regular_price_txt' );
				$regular_price_html = $regular_price_txt . ' ' . $this->rolebased->get_regular_price_html( $product, $min_regular_price );
				if ( $min_regular_price !== $max_regular_price ) {
					$max_regular_price_html = $this->rolebased->get_regular_price_html( $product, $max_regular_price );
					$regular_price_html     = ywcrbp_get_format_price_from_to( $product, $regular_price_html, $max_regular_price_html );
				}

				if ( (float) $min_regular_price === (float) $min_dynamic_price && (float) $max_dynamic_price === (float) $max_regular_price ) {
					$regular_price_html = '';
				} else {
					$show_del           = ( ! empty( $min_sale_price ) && $show_on_sale_price ) || ( $min_role_price !== $min_dynamic_price );
					$regular_price_html = $this->rolebased->get_formatted_price_html( $regular_price_html, $show_del, 'regular' );
					$regular_price_html = apply_filters( 'ywcrbp_variable_regular_price_html', $regular_price_html, $product, $min_regular_price, $max_regular_price );
				}
			}

			if ( '' !== $min_sale_price && $show_on_sale_price && $min_regular_price !== $min_sale_price ) {
				$sale_price_txt = get_option( 'ywcrbp_sale_price_txt' );

				if ( ! $has_role_price ) {
					$price_html = $sale_price_txt . ' ' . $price_html;
				} else {
					$sale_price_html = $sale_price_txt . ' ' . $this->rolebased->get_sale_price_html( $product, $min_sale_price );

					if ( $min_sale_price !== $max_sale_price ) {

						$max_sale_price_html = $this->rolebased->get_sale_price_html( $product, $max_sale_price );

						$sale_price_html = ywcrbp_get_format_price_from_to( $product, $sale_price_html, $max_sale_price_html );
					}

					$show_del = ( $show_your_price && $has_role_price );

					$sale_price_html = $this->rolebased->get_formatted_price_html( $sale_price_html, $show_del, 'sale' );
					$sale_price_html = apply_filters( 'ywcrbp_variable_sale_price_html', $sale_price_html, $product, $min_sale_price, $max_sale_price );
				}
			}

			$their_price_html = $this->rolebased->get_formatted_price_html( $this->rolebased->get_their_variable_price_html( $product ), false, 'their' );

			if ( $has_role_price ) {

				$your_price_html = $this->rolebased->get_your_price_html( $product, $min_role_price );

				if ( $min_role_price !== $max_role_price ) {
					$max_your_price_html = $this->rolebased->get_your_price_html( $product, $max_role_price );
					$your_price_html     = ywcrbp_get_format_price_from_to( $product, $your_price_html, $max_your_price_html );
				}

				$your_price_html = $this->rolebased->get_formatted_price_html( $your_price_html, true );
				$your_price_html = apply_filters( 'ywcrbp_variable_your_price_html', $your_price_html, $product, $min_role_price, $max_role_price );

				if ( $min_dynamic_price !== $max_dynamic_price ) {
					$price_html = wc_format_price_range( $min_dynamic_price, $max_dynamic_price );
				} else {
					$price_html = wc_price( $min_dynamic_price );
				}
				$price_html = get_option( 'ywcrbp_your_price_txt' ) . ' ' . $your_price_html . ' ' . $price_html;
			} else {

				if ( $min_dynamic_price !== $max_dynamic_price ) {
					$price_html = wc_format_price_range( $min_dynamic_price, $max_dynamic_price );
				} else {
					$price_html = wc_price( $min_dynamic_price );
				}

				$price_html = apply_filters( 'ywdpd_role_based_price_variable_product', $price_html, $has_role_price, $product );
			}
			if ( $has_role_price ) {
				$this->add_rolebased_hooks();
			}

			return $regular_price_html . ' ' . $sale_price_html . ' ' . $price_html . $their_price_html;
		}

		/**
		 * Set the role price in the cart
		 *
		 * @param float $price The product price.
		 * @param array $cart_item The cart item.
		 *
		 * @return float
		 */
		public function set_role_based_price( $price, $cart_item ) {

			$role_price = $this->rolebased->get_role_based_price( $cart_item['data'] );

			return 'no_price' !== $role_price ? $role_price : $price;
		}
	}
}
