<?php // phpcs:ignore WordPress.Files.FileName
/**
 * The Price Rule base class.
 * this class will be extended to manage the prices rule type.
 *
 * @class   YWDPD_Price_Rule
 * @version 3.0.0
 * @package YITH WooCommerce Dynamic Prcing and Discounts\Abstracts
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Abstract Dynamic Price Rule class.
 *
 * @since   3.0.0
 * @package YITH WooCommerce Dynamic Prcing and Discounts\Abstracts
 */
abstract class YWDPD_Price_Rule extends YWDPD_Rule {

	/**
	 * Stores price rule data.
	 *
	 * @var array the common data
	 */
	protected $data = array(
		'key'                                       => '',
		'name'                                      => '',
		'active'                                    => 'yes',
		'priority'                                  => 1,
		'schedule_discount_mode'                    => array(
			'schedule_type' => 'no_schedule',
		),
		'discount_mode'                             => 'bulk',
		'user_rules'                                => 'everyone',
		'user_rules_customers_list'                 => array(),
		'user_rules_role_list'                      => array(),
		'enable_user_rule_exclude'                  => 'no',
		'user_rule_exclude'                         => 'specific_customers',
		'user_rules_customers_list_excluded'        => array(),
		'user_rules_role_list_excluded'             => array(),
		'disable_rule'                              => array(
			'disable_on_sale',
			'disable_with_other_coupon',
		),
		'show_table_note_apply_to'                  => 'no',
		'table_note_apply_to'                       => '',
		'rule_for'                                  => 'all_products',
		'rule_for_products_list'                    => array(),
		'rule_for_categories_list'                  => array(),
		'rule_for_tags_list'                        => array(),
		'active_exclude'                            => 'no',
		'exclude_rule_for'                          => 'specific_products',
		'exclude_rule_for_products_list'            => array(),
		'exclude_rule_for_categories_list'          => array(),
		'exclude_rule_for_tags_list'                => array(),
		'quantity_based'                            => 'cart_line',
		'active_apply_discount_to'                  => 'no',
		'rule_apply_adjustment_discount_for'        => 'all_products',
		'apply_adjustment_products_list'            => array(),
		'apply_adjustment_categories_list'          => array(),
		'apply_adjustment_tags_list'                => array(),
		'active_apply_adjustment_to_exclude'        => 'no',
		'exclude_apply_adjustment_rule_for'         => 'specific_products',
		'apply_adjustment_products_list_excluded'   => array(),
		'apply_adjustment_categories_list_excluded' => array(),
		'apply_adjustment_tags_list_excluded'       => array(),
		'show_note_adjustment_to'                   => 'no',
		'table_note_adjustment_to'                  => '',
		'no_apply_with_other_rules'                 => true,
	);
	/**
	 * This is the name of this object type.
	 *
	 * @since 3.0.0
	 * @var string
	 */
	protected $object_type = 'price_rule';

	/**
	 * Set if apply rule with other rules.
	 *
	 * @param string $no_apply_with_other_rules Set if apply rule with other rules.
	 *
	 * @since 3.0.0
	 */
	public function set_no_apply_with_other_rules( $no_apply_with_other_rules ) {
		$this->set_prop( 'no_apply_with_other_rules', $no_apply_with_other_rules );
	}

	/**
	 * Set the user exclusion list that can't get the rule discount.
	 *
	 * @param array $user_rules_customers_list_excluded The customer ids.
	 *
	 * @since 3.0.0
	 */
	public function set_user_rules_customers_list_excluded( $user_rules_customers_list_excluded ) {
		$this->set_prop( 'user_rules_customers_list_excluded', $user_rules_customers_list_excluded );
	}

	/**
	 * Set the user role exclude list that can't get the rule discount.
	 *
	 * @param array $user_rules_role_list_excluded The role slug list.
	 *
	 * @since 3.0.0
	 */
	public function set_user_rules_role_list_excluded( $user_rules_role_list_excluded ) {
		$this->set_prop( 'user_rules_role_list_excluded', $user_rules_role_list_excluded );
	}

	/**
	 * Set if exclude customers for this rule.
	 *
	 * @param string $enable_user_rule_exclude Can be yes or not.
	 *
	 * @since 3.0.0
	 */
	public function set_enable_user_rule_exclude( $enable_user_rule_exclude ) {
		$this->set_prop( 'enable_user_rule_exclude', $enable_user_rule_exclude );
	}

	/**
	 * Set the user exclusion type.
	 *
	 * @param string $user_rule_exclude The exclusion type.
	 *
	 * @since 3.0.0
	 */
	public function set_user_rule_exclude( $user_rule_exclude ) {
		$this->set_prop( 'user_rule_exclude', $user_rule_exclude );
	}

	/**
	 * Set the user list that can get the rule discount.
	 *
	 * @param array $user_rules_customers_list The customer ids.
	 *
	 * @since 3.0.0
	 */
	public function set_user_rules_customers_list( $user_rules_customers_list ) {
		$this->set_prop( 'user_rules_customers_list', $user_rules_customers_list );
	}

	/**
	 * Set the user role list that can get the rule discount.
	 *
	 * @param array $user_rules_role_list The role slug list.
	 *
	 * @since 3.0.0
	 */
	public function set_user_rules_role_list( $user_rules_role_list ) {
		$this->set_prop( 'user_rules_role_list', $user_rules_role_list );
	}

	/**
	 * Set what are the user that  could see the price rule.
	 *
	 * @param string $user_rules The type of the user.
	 *
	 * @since 3.0.0
	 */
	public function set_user_rules( $user_rules ) {
		$this->set_prop( 'user_rules', $user_rules );
	}

	/**
	 * Set the disable rule field
	 *
	 * @param array $disable_rule The disable rule configuration.
	 *
	 * @return void
	 */
	public function set_disable_rule( $disable_rule ) {
		$this->set_prop( 'disable_rule', $disable_rule );
	}

	/**
	 * Set the discount mode of this price rule.
	 *
	 * @param string $discount_mode The type of this price rule.
	 *
	 * @since 3.0.0
	 */
	public function set_discount_mode( $discount_mode ) {
		$this->set_prop( 'discount_mode', $discount_mode );
	}


	/**
	 * Set if is possible show the message for this rule.
	 *
	 * @param string $show_table_note_apply_to Yes or no.
	 *
	 * @since 4.0.0
	 */
	public function set_show_table_note_apply_to( $show_table_note_apply_to ) {
		$this->set_prop( 'show_table_note_apply_to', $show_table_note_apply_to );
	}

	/**
	 * Set the message to show for this rule.
	 *
	 * @param string $table_note_apply_to The message.
	 *
	 * @since 3.0.0
	 */
	public function set_table_note_apply_to( $table_note_apply_to ) {
		$this->set_prop( 'table_note_apply_to', $table_note_apply_to );
	}

	/**
	 * Set if the rule is valid for all products or not.
	 *
	 * @param string $rule_for Where the rule will be applied.
	 *
	 * @since 3.0.0
	 */
	public function set_rule_for( $rule_for ) {
		$this->set_prop( 'rule_for', $rule_for );
	}

	/**
	 * Set the product ids where apply the rule
	 *
	 * @param array $product_list The products ids.
	 *
	 * @since 3.0.0
	 */
	public function set_rule_for_product_list( $product_list ) {
		$this->set_prop( 'rule_for_products_list', $product_list );
	}

	/**
	 * Set the product category ids where apply the rule
	 *
	 * @param array $catgory_list The product category ids.
	 *
	 * @since 3.0.0
	 */
	public function set_rule_for_categories_list( $catgory_list ) {
		$this->set_prop( 'rule_for_categories_list', $catgory_list );
	}

	/**
	 * Set the product tag ids where apply the rule
	 *
	 * @param array $tag_list The tag ids.
	 *
	 * @since 3.0.0
	 */
	public function set_rule_for_tags_list( $tag_list ) {
		$this->set_prop( 'rule_for_tags_list', $tag_list );
	}

	/**
	 * Set if exclude product or not.
	 *
	 * @param string $exclude Yes or no.
	 *
	 * @since 3.0.0
	 */
	public function set_active_exclude( $exclude ) {
		$this->set_prop( 'active_exclude', $exclude );
	}

	/**
	 * Set what exclude from the rule.
	 *
	 * @param string $exclude_for The exclusion type.
	 *
	 * @since 3.0.0
	 */
	public function set_exclude_rule_for( $exclude_for ) {
		$this->set_prop( 'exclude_rule_for', $exclude_for );
	}

	/**
	 * Set the product ids to exclude.
	 *
	 * @param array $product_list the product ids list.
	 *
	 * @since 3.0.0
	 */
	public function set_exclude_rule_for_products_list( $product_list ) {
		$this->set_prop( 'exclude_rule_for_products_list', $product_list );
	}

	/**
	 * Set the product category ids to exclude.
	 *
	 * @param array $category_list the category ids list.
	 *
	 * @since 3.0.0
	 */
	public function set_exclude_rule_for_categories_list( $category_list ) {
		$this->set_prop( 'exclude_rule_for_categories_list', $category_list );
	}

	/**
	 * Set the product tag ids to exclude.
	 *
	 * @param array $tag_list the tag ids list.
	 *
	 * @since 3.0.0
	 */
	public function set_exclude_rule_for_tags_list( $tag_list ) {
		$this->set_prop( 'exclude_rule_for_tags_list', $tag_list );
	}

	/**
	 * Set the quantity mode for this rule.
	 *
	 * @param string $quantity_based The quantity mode.
	 *
	 * @since 3.0.0
	 */
	public function set_quantity_based( $quantity_based ) {
		$this->set_prop( 'quantity_based', $quantity_based );
	}

	/**
	 * Set if apply discount to a diffent products.
	 *
	 * @param string $active_apply_discount_to Yes or no.
	 *
	 * @since 3.0.0
	 */
	public function set_active_apply_discount_to( $active_apply_discount_to ) {
		$this->set_prop( 'active_apply_discount_to', $active_apply_discount_to );
	}

	/**
	 * Set where apply the Rule.
	 *
	 * @param string $apply_to_for Where applyu the rule (I.E specific products ).
	 */
	public function set_rule_apply_adjustment_discount_for( $apply_to_for ) {
		$this->set_prop( 'rule_apply_adjustment_discount_for', $apply_to_for );
	}

	/**
	 * Set the product ids where apply the rule
	 *
	 * @param array $adjustment_product_list The product ids.
	 *
	 * @since 3.0.0
	 */
	public function set_apply_adjustment_products_list( $adjustment_product_list ) {
		$this->set_prop( 'apply_adjustment_products_list', $adjustment_product_list );
	}

	/**
	 * Set the product category ids where apply the rule
	 *
	 * @param array $adjustment_category_list The product category ids.
	 *
	 * @since 3.0.0
	 */
	public function set_apply_adjustment_categories_list( $adjustment_category_list ) {
		$this->set_prop( 'apply_adjustment_categories_list', $adjustment_category_list );
	}

	/**
	 * Set the product tag ids where apply the rule
	 *
	 * @param array $adjustment_tag_list The product tag ids.
	 *
	 * @since 3.0.0
	 */
	public function set_apply_adjustment_tags_list( $adjustment_tag_list ) {
		$this->set_prop( 'apply_adjustment_tags_list', $adjustment_tag_list );
	}

	/**
	 * Set if exclude product or not in adjustment.
	 *
	 * @param string $exclude Yes or no.
	 *
	 * @since 3.0.0
	 */
	public function set_active_apply_adjustment_to_exclude( $exclude ) {
		$this->set_prop( 'active_apply_adjustment_to_exclude', $exclude );
	}

	/**
	 * Set what exclude from the rule.
	 *
	 * @param string $exclude_for The exclusion type.
	 *
	 * @since 3.0.0
	 */
	public function set_exclude_apply_adjustment_rule_for( $exclude_for ) {
		$this->set_prop( 'exclude_apply_adjustment_rule_for', $exclude_for );
	}

	/**
	 * Set the product ids to exclude.
	 *
	 * @param array $product_list the product ids list.
	 *
	 * @since 3.0.0
	 */
	public function set_apply_adjustment_products_list_excluded( $product_list ) {
		$this->set_prop( 'apply_adjustment_products_list_excluded', $product_list );
	}

	/**
	 * Set the product category ids to exclude.
	 *
	 * @param array $category_list the category ids list.
	 *
	 * @since 3.0.0
	 */
	public function set_apply_adjustment_categories_list_excluded( $category_list ) {
		$this->set_prop( 'apply_adjustment_categories_list_excluded', $category_list );
	}

	/**
	 * Set the product tag ids to exclude.
	 *
	 * @param array $tag_list the tag ids list.
	 *
	 * @since 3.0.0
	 */
	public function set_apply_adjustment_tags_list_excluded( $tag_list ) {
		$this->set_prop( 'apply_adjustment_tags_list_excluded', $tag_list );
	}

	/**
	 * Set if is possible show the adjustment notes
	 *
	 * @param string $show_note_adjustment_to Yes or no.
	 *
	 * @since 4.0.0
	 */
	public function set_show_note_adjustment_to( $show_note_adjustment_to ) {
		$this->set_prop( 'show_note_adjustment_to', $show_note_adjustment_to );
	}

	/**
	 * The message for adjustment products
	 *
	 * @param string $message The message.
	 *
	 * @since 3.0.0
	 */
	public function set_table_note_adjustment_to( $message ) {
		$this->set_prop( 'table_note_adjustment_to', $message );
	}
	// THE GETTERS.

	/**
	 * Get if apply rule with other rules.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_no_apply_with_other_rules( $context = 'view' ) {
		return $this->get_prop( 'no_apply_with_other_rules', $context );
	}

	/**
	 * Get the user exclusion list that can't get the rule discount.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_user_rules_customers_list_excluded( $context = 'view' ) {
		return $this->get_prop( 'user_rules_customers_list_excluded', $context );
	}

	/**
	 * Get the user role exclude list that can't get the rule discount.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_user_rules_role_list_excluded( $context = 'view' ) {
		return $this->get_prop( 'user_rules_role_list_excluded', $context );
	}

	/**
	 * Get if exclude customers for this rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_enable_user_rule_exclude( $context = 'view' ) {
		return $this->get_prop( 'enable_user_rule_exclude', $context );
	}

	/**
	 * Get the user exclusion type.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_user_rule_exclude( $context = 'view' ) {
		return $this->get_prop( 'user_rule_exclude', $context );
	}

	/**
	 * Get the user list that can get the rule discount.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_user_rules_customers_list( $context = 'view' ) {
		return $this->get_prop( 'user_rules_customers_list', $context );
	}

	/**
	 * Get the user role list that can get the rule discount.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_user_rules_role_list( $context = 'view' ) {
		return $this->get_prop( 'user_rules_role_list', $context );
	}

	/**
	 * Get what are the user that could see the price rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_user_rules( $context = 'view' ) {
		return $this->get_prop( 'user_rules', $context );
	}

	/**
	 * Return the disable rule configuration
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 4.0.0
	 */
	public function get_disable_rule( $context = 'view' ) {
		return $this->get_prop( 'disable_rule', $context );
	}

	/**
	 * Get the discount mode of this price rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_discount_mode( $context = 'view' ) {
		return $this->get_prop( 'discount_mode', $context );
	}

	/**
	 * Get if the table note can be shown.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 4.0.0
	 */
	public function get_show_table_note_apply_to( $context = 'view' ) {
		return $this->get_prop( 'show_table_note_apply_to', $context );
	}

	/**
	 * Get the message to show for this rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_table_note_apply_to( $context = 'view' ) {
		return $this->get_prop( 'table_note_apply_to', $context );
	}

	/**
	 * Return the rule type ( Price or Cart )
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_type() {
		return 'price_rule';
	}

	/**
	 * Get if the rule is valid for all products or not.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_rule_for( $context = 'view' ) {
		return $this->get_prop( 'rule_for', $context );
	}

	/**
	 * Get the product ids where apply the rule
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_rule_for_product_list( $context = 'view' ) {
		return $this->get_prop( 'rule_for_products_list', $context );
	}

	/**
	 * Get the product category ids where apply the rule
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_rule_for_categories_list( $context = 'view' ) {
		return $this->get_prop( 'rule_for_categories_list', $context );
	}

	/**
	 * Get the product tag ids where apply the rule
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_rule_for_tags_list( $context = 'view' ) {
		return $this->get_prop( 'rule_for_tags_list', $context );
	}

	/**
	 * Get if exclude product or not.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_active_exclude( $context = 'view' ) {
		return $this->get_prop( 'active_exclude', $context );
	}

	/**
	 * Get what exclude from the rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_exclude_rule_for( $context = 'view' ) {
		return $this->get_prop( 'exclude_rule_for', $context );
	}

	/**
	 * Get the product ids to exclude.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @since 3.0.0
	 */
	public function get_exclude_rule_for_products_list( $context = 'view' ) {
		return $this->get_prop( 'exclude_rule_for_products_list', $context );
	}

	/**
	 * Get the product category ids to exclude.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_exclude_rule_for_categories_list( $context = 'view' ) {
		return $this->get_prop( 'exclude_rule_for_categories_list', $context );
	}

	/**
	 * Get the product tag ids to exclude.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_exclude_rule_for_tags_list( $context = 'view' ) {
		return $this->get_prop( 'exclude_rule_for_tags_list', $context );
	}

	/**
	 * Get the quantity mode for this rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_quantity_based( $context = 'view' ) {
		return $this->get_prop( 'quantity_based', $context );
	}

	/**
	 * Get if apply discount to a different products.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_active_apply_discount_to( $context = 'view' ) {
		return $this->get_prop( 'active_apply_discount_to', $context );
	}

	/**
	 * Get where apply the Rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_rule_apply_adjustment_discount_for( $context = 'view' ) {
		return $this->get_prop( 'rule_apply_adjustment_discount_for', $context );
	}

	/**
	 * Get the product ids where apply the rule
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_apply_adjustment_products_list( $context = 'view' ) {
		return $this->get_prop( 'apply_adjustment_products_list', $context );
	}

	/**
	 * Get the product category ids where apply the rule
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_apply_adjustment_categories_list( $context = 'view' ) {
		return $this->get_prop( 'apply_adjustment_categories_list', $context );
	}

	/**
	 * Get the product tag ids where apply the rule
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_apply_adjustment_tags_list( $context = 'view' ) {
		return $this->get_prop( 'apply_adjustment_tags_list', $context );
	}

	/**
	 * Get if exclude product or not in adjustment.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_active_apply_adjustment_to_exclude( $context = 'view' ) {
		return $this->get_prop( 'active_apply_adjustment_to_exclude', $context );
	}

	/**
	 * Get what exclude from the rule.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_exclude_apply_adjustment_rule_for( $context = 'view' ) {
		return $this->get_prop( 'exclude_apply_adjustment_rule_for', $context );
	}

	/**
	 * Get the product ids to exclude.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_apply_adjustment_products_list_excluded( $context = 'view' ) {
		return $this->get_prop( 'apply_adjustment_products_list_excluded', $context );
	}

	/**
	 * Get the product category ids to exclude.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_apply_adjustment_categories_list_excluded( $context = 'view' ) {
		return $this->get_prop( 'apply_adjustment_categories_list_excluded', $context );
	}

	/**
	 * Get the product tag ids to exclude.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return array
	 * @since 3.0.0
	 */
	public function get_apply_adjustment_tags_list_excluded( $context = 'view' ) {
		return $this->get_prop( 'apply_adjustment_tags_list_excluded', $context );
	}

	/**
	 * Get if possible show the adjustment notice.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 4.0.0
	 */
	public function get_show_note_adjustment_to( $context = 'view' ) {
		return $this->get_prop( 'show_note_adjustment_to', $context );
	}

	/**
	 * The message for adjustment products
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 * @since 3.0.0
	 */
	public function get_table_note_adjustment_to( $context = 'view' ) {
		return $this->get_prop( 'table_note_adjustment_to', $context );
	}

	// Conditional methods.

	/**
	 * Check if the user is excluded.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_user_excluded( $context = 'view' ) {

		$is_exclude_user_active = yith_plugin_fw_is_true( $this->get_enable_user_rule_exclude( $context ) );
		$is_in_exclusion        = false;
		if ( $is_exclude_user_active ) {

			$user           = is_user_logged_in() ? wp_get_current_user() : false;
			$user_roles     = $user instanceof WP_User ? $user->roles : array( 'guest' );
			$exclusion_type = $this->get_user_rule_exclude();
			if ( 'specific_customers' === $exclusion_type && $user instanceof WP_User ) {
				$customer_ids_excluded = $this->get_user_rules_customers_list_excluded( $context );
				if ( in_array( intval( $user->ID ), array_map( 'intval', $customer_ids_excluded ), true ) ) {
					$is_in_exclusion = true;
				}
			} elseif ( 'specific_roles' === $exclusion_type ) {
				$customer_roles_excluded = $this->get_user_rules_role_list_excluded( $context );
				if ( count( array_intersect( $user_roles, $customer_roles_excluded ) ) > 0 ) {
					$is_in_exclusion = true;
				}
			}
		}
		if ( 'view' === $context ) {
			/**
			 * APPLY_FILTERS: ywdpd_is_user_excluded
			 *
			 * With this filter is possible exclude or not a user.
			 *
			 * @param bool $is_in_exclusion The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$is_in_exclusion = apply_filters( 'ywdpd_is_user_excluded', $is_in_exclusion, $this );

		}

		return $is_in_exclusion;
	}

	/**
	 * Check if the rule is valid for the current user.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_valid_for_user( $context = 'view' ) {
		$value = false;

		if ( ! $this->is_user_excluded( $context ) ) {

			$user_type  = $this->get_user_rules( $context );
			$user       = is_user_logged_in() ? wp_get_current_user() : false;
			$user_roles = $user instanceof WP_User ? $user->roles : array( 'guest' );

			if ( 'everyone' === $user_type ) {
				$value = true;
			} elseif ( 'customers_list' === $user_type && $user instanceof WP_User ) {
				$customer_ids = $this->get_user_rules_customers_list( $context );

				if ( in_array( $user->ID, array_map( 'intval', $customer_ids ), true ) ) {
					$value = true;
				}
			} elseif ( 'role_list' === $user_type ) {
				$customer_roles = $this->get_user_rules_role_list( $context );

				if ( count( array_intersect( $user_roles, $customer_roles ) ) > 0 ) {
					$value = true;
				}
			}
		}

		if ( 'view' === $context ) {
			/**
			 * APPLY_FILTERS: yit_ywdpd_validate_user
			 *
			 * With this filter is possible validate a rule for a user.
			 *
			 * @param bool $value The value to filter.
			 * @param string $rule_type The type of the rule. everyone|customers_list|role_list
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 * @deprecated Deprecated since 3.0.0
			 */
			$value = apply_filters( 'yit_ywdpd_validate_user', $value, $this->get_user_rules( $context ), $this );
			/**
			 * APPLY_FILTERS: ywdpd_is_valid_for_user
			 *
			 * With this filter is possible validate a rule for a user.
			 *
			 * @param bool $value The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$value = apply_filters( 'ywdpd_is_valid_for_user', $value, $this );
		}

		return $value;
	}

	/**
	 * Check after this rule is applied, if is possible apply other rules with lower priority.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_possible_apply_other_rules( $context = 'view' ) {

		$value = ! yith_plugin_fw_is_true( $this->get_no_apply_with_other_rules( $context ) );

		if ( 'view' === $context ) {
			/**
			 * APPLY_FILTERS: ywdpd_can_apply_with_other_rules
			 *
			 * With this filter is possible set if a rule can be applied with other rules.
			 *
			 * @param bool $value The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$value = apply_filters( 'ywdpd_can_apply_with_other_rules', $value, $this );
		}

		return $value;
	}

	/**
	 * Check if this rule is disabled for on sale product.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_disabled_on_sale( $context = 'view' ) {
		$disable_rule = $this->get_disable_rule( $context );
		$value        = in_array( 'disable_on_sale', $disable_rule, true );
		if ( 'view' === $context ) {
			/**
			 * APPLY_FILTERS: ywdpd_is_disabled_on_sale
			 *
			 * With this filter is possible set if a rule can be applied with on-sale products.
			 *
			 * @param bool $value The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$value = apply_filters( 'ywdpd_is_disabled_on_sale', $value, $this );
		}

		return $value;
	}

	/**
	 * Check if this rule is disabled if there are coupons in cart.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_disabled_with_other_coupon( $context = 'view' ) {
		$disable_rule = $this->get_disable_rule( $context );
		$value        = in_array( 'disable_with_other_coupon', $disable_rule, true );

		if ( 'view' === $context ) {
			/**
			 * APPLY_FILTERS: ywdpd_is_disabled_with_other_coupon
			 *
			 * With this filter is possible set if a rule can be applied with other coupons.
			 *
			 * @param bool $value The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$value = apply_filters( 'ywdpd_is_disabled_with_other_coupon', $value, $this );
		}

		return $value;
	}

	/**
	 * Check if this rule is Valid.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_valid( $context = 'view' ) {

		return $this->is_enabled( $context ) && $this->is_valid_for_user( $context ) && $this->is_scheduled( $context );
	}

	/**
	 * Check if the rule is valid for apply discount.
	 *
	 * @param WC_Product $product The product object.
	 * @param bool $check_also_variation Check also the variation or not.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_valid_to_apply( $product, $check_also_variation = false ) {
		$type     = $this->get_rule_for();
		$is_valid = false;

		if ( ! $this->is_product_excluded_from_apply( $product, $check_also_variation ) ) {
			if ( 'all_products' === $type ) {
				$is_valid = true;
			} elseif ( 'specific_products' === $type ) {
				$list_ids = $this->get_rule_for_product_list();
				$is_valid = $this->is_product_in_list( $product, $list_ids, 'product', $check_also_variation );

			} elseif ( 'specific_categories' === $type ) {
				$list_ids = $this->get_rule_for_categories_list();
				$is_valid = $this->is_product_in_list( $product, $list_ids, 'product_cat' );
			} elseif ( 'specific_tag' === $type ) {
				$list_ids = $this->get_rule_for_tags_list();
				$is_valid = $this->is_product_in_list( $product, $list_ids, 'product_tag' );
			}
			/**
			 * APPLY_FILTERS: ywdpd_is_valid_to_apply
			 *
			 * With this filter is possible set if a rule is valid to apply.
			 *
			 * @param bool $is_valid The value to filter.
			 * @param string $type The valid type.
			 * @param WC_Product $product The product.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$is_valid = apply_filters( 'ywdpd_is_valid_to_apply', $is_valid, $type, $product, $this );
		}

		return $is_valid;

	}

	/**
	 * Check if the exclude option is enabled
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since  3.0.0
	 * @author YITH <plugins@yithemes.com>
	 */
	public function is_exclude_from_apply_enabled( $context = 'view' ) {
		$is_exclude_activated = yith_plugin_fw_is_true( $this->get_active_exclude( $context ) );

		return $is_exclude_activated;
	}

	/**
	 * Check if this product is excluded from this rule.
	 *
	 * @param WC_Product $product The product to check.
	 * @param bool $check_also_variation Check also the variation or not.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_product_excluded_from_apply( $product, $check_also_variation = false ) {

		$is_excluded = false;
		$type        = $this->get_exclude_rule_for();
		if ( $this->is_exclude_from_apply_enabled() ) {

			$list_ids      = array();
			$taxonomy_name = '';
			if ( 'specific_products' === $type ) {
				$list_ids      = $this->get_exclude_rule_for_products_list();
				$taxonomy_name = 'product';
			} elseif ( 'specific_categories' === $type ) {
				$list_ids      = $this->get_exclude_rule_for_categories_list();
				$taxonomy_name = 'product_cat';
			} elseif ( 'specific_tag' === $type ) {
				$list_ids      = $this->get_exclude_rule_for_tags_list();
				$taxonomy_name = 'product_tag';
			}

			if ( count( $list_ids ) > 0 && ! empty( $taxonomy_name ) ) {
				$is_excluded = $this->is_product_in_list( $product, $list_ids, $taxonomy_name, $check_also_variation );
			}
		}

		/**
		 * APPLY_FILTERS: ywdpd_is_product_excluded_from_apply
		 *
		 * With this filter is possible set if a product is excluded in the rule.
		 *
		 * @param bool $is_excluded The value to filter.
		 * @param string $type The valid type.
		 * @param WC_Product $product The product.
		 * @param YWDPD_Price_Rule $object The current object.
		 *
		 * @return bool
		 */
		return apply_filters( 'ywdpd_is_product_excluded_from_apply', $is_excluded, $type, $product, $this );
	}

	/**
	 * Check if the exclude option is enabled
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since  3.0.0
	 */
	public function is_exclude_adjustment_to_enabled( $context = 'view' ) {
		$is_exclude_activated = yith_plugin_fw_is_true( $this->get_active_apply_adjustment_to_exclude( $context ) );

		return $is_exclude_activated;
	}

	/**
	 * Check if this product is excluded from this rule.
	 *
	 * @param WC_Product $product The product to check.
	 * @param bool $check_also_variation Check also the variation or not.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_product_excluded_from_adjustment_to( $product, $check_also_variation = false ) {

		$is_exclude_activated = $this->is_exclude_adjustment_to_enabled();
		$is_excluded          = false;
		$list_ids             = array();
		if ( $is_exclude_activated ) {

			$type          = $this->get_exclude_apply_adjustment_rule_for();
			$taxonomy_name = '';
			if ( 'specific_products' === $type ) {
				$list_ids      = $this->get_apply_adjustment_products_list_excluded();
				$taxonomy_name = 'product';
			} elseif ( 'specific_categories' === $type ) {
				$list_ids      = $this->get_apply_adjustment_categories_list_excluded();
				$taxonomy_name = 'product_cat';
			} elseif ( 'specific_tag' === $type ) {
				$list_ids      = $this->get_apply_adjustment_tags_list_excluded();
				$taxonomy_name = 'product_tag';
			}

			if ( count( $list_ids ) > 0 && ! empty( $taxonomy_name ) ) {
				$is_excluded = $this->is_product_in_list( $product, $list_ids, $taxonomy_name, $check_also_variation );
			}
		}

		/**
		 * APPLY_FILTERS: ywdpd_is_product_excluded_from_adjustment_to
		 *
		 * With this filter is possible set if a product is excluded in the rule.
		 *
		 * @param bool $is_excluded The value to filter.
		 * @param string $type The valid type.
		 * @param WC_Product $product The product.
		 * @param YWDPD_Price_Rule $object The current object.
		 *
		 * @return bool
		 */
		return apply_filters( 'ywdpd_is_product_excluded_from_adjustment_to', $is_excluded, $product, $this );
	}

	/**
	 * Check if the product is in the list
	 *
	 * @param WC_Product $product The product to check.
	 * @param array $list_ids The list of term ids.
	 * @param string $taxonomy_to_check The taxonomy name.
	 * @param bool $check_also_variation Check also the variation or not.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_product_in_list( $product, $list_ids, $taxonomy_to_check = 'product_cat', $check_also_variation = false ) {

		$is_in_list = false;
		if ( ! is_array( $list_ids ) ) {
			return false;
		}
		if ( 'product' === $taxonomy_to_check && $product ) {

			$main_id      = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id();
			$ids_to_check = array( $main_id, $product->get_id() );
			/**
			 * APPLY_FILTERS: yith_ywdpd_valid_product_to_apply_other_variations
			 *
			 * With this filter is possible not allow variation checks.
			 *
			 * @param bool $with_other_variation The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 * @param WC_Product $product The product.
			 * @param bool $check_also_variation If needed check in the variations.
			 *
			 * @return bool
			 */
			if ( $check_also_variation && apply_filters( 'yith_ywdpd_valid_product_to_apply_other_variations', true, $this, $product, $check_also_variation ) ) {
				if ( $product->is_type( 'variation' ) ) {
					$parent = wc_get_product( $product->get_parent_id() );
					if ( $parent instanceof WC_Product_Variable ) {
						$ids_to_check = array_merge( $parent->get_children(), $ids_to_check );
					}
				} elseif ( $product->is_type( 'variable' ) ) {
					$ids_to_check = array_merge( $product->get_children(), $ids_to_check );
				}
			}

			$is_in_list = count( array_intersect( $list_ids, $ids_to_check ) ) > 0;

		} elseif ( 'product_cat' === $taxonomy_to_check ) {
			$terms      = YWDPD_Taxonomy::get_product_category_ids( $product );
			$is_in_list = count( array_intersect( $list_ids, $terms ) ) > 0;
		} elseif ( 'product_tag' === $taxonomy_to_check ) {
			$terms      = YWDPD_Taxonomy::get_product_tag_ids( $product );
			$is_in_list = count( array_intersect( $list_ids, $terms ) ) > 0;
		} else {
			$terms      = YWDPD_Taxonomy::get_product_term_ids( $product, $taxonomy_to_check );
			$is_in_list = count( array_intersect( $list_ids, $terms ) ) > 0;
		}

		/**
		 * APPLY_FILTERS: ywdpd_is_product_in_list
		 *
		 * Check if the product is in the list.
		 *
		 * @param bool $is_in_list The value to filter.
		 * @param WC_Product $product The product.
		 * @param array $list_ids The ids list.
		 * @param string $taxonomy_to_check The taxonomy: product_cat, product_tag,etc.
		 * @param YWDPD_Price_Rule $object The current object.
		 *
		 * @return bool
		 */
		return apply_filters( 'ywdpd_is_product_in_list', $is_in_list, $product, $list_ids, $taxonomy_to_check, $this );
	}

	/**
	 * Check if this rule is enabled the adjustment to mode
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_enabled_apply_adjustment_to( $context = 'view' ) {

		$value = yith_plugin_fw_is_true( $this->get_active_apply_discount_to( $context ) );
		if ( 'view' === $context ) {
			/**
			 * APPLY_FILTERS: ywdpd_is_enabled_apply_adjustment_to
			 *
			 * Rule is enabled for adjustment.
			 *
			 * @param bool $value The value to filter.
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$value = apply_filters( 'ywdpd_is_enabled_apply_adjustment_to', $value, $this );
		}

		return $value;
	}

	/**
	 * Check if the rule is valid for adjustment discount.
	 *
	 * @param WC_Product $product The product object.
	 * @param bool $check_also_variation Check also the variation or not.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function is_valid_to_adjust( $product, $check_also_variation = false ) {

		$is_active_adjust = $this->is_enabled_apply_adjustment_to();
		$is_valid         = false;
		$type             = $this->get_rule_apply_adjustment_discount_for();
		if ( $is_active_adjust ) {
			if ( ! $this->is_product_excluded_from_adjustment_to( $product, $check_also_variation ) ) {

				if ( 'all_products' === $type ) {
					$is_valid = true;
				} elseif ( 'specific_products' === $type ) {
					$list_ids = $this->get_apply_adjustment_products_list();
					$is_valid = $this->is_product_in_list( $product, $list_ids, 'product', $check_also_variation );
				} elseif ( 'specific_categories' === $type ) {
					$list_ids = $this->get_apply_adjustment_categories_list();
					$is_valid = $this->is_product_in_list( $product, $list_ids, 'product_cat' );
				} elseif ( 'specific_tag' === $type ) {
					$list_ids = $this->get_apply_adjustment_tags_list();
					$is_valid = $this->is_product_in_list( $product, $list_ids, 'product_tag' );
				}
			}
			/**
			 * APPLY_FILTERS: ywdpd_is_valid_to_adjust
			 *
			 * Rule is valid to adjustment.
			 *
			 * @param bool $is_valid The value to filter.
			 * @param string $type The type of check. ( all_products|specific_products|specific_categories|specific_tag )
			 * @param YWDPD_Price_Rule $object The current object.
			 *
			 * @return bool
			 */
			$is_valid = apply_filters( 'ywdpd_is_valid_to_adjust', $is_valid, $type, $product, $this );
		}

		return $is_valid;
	}

	/**
	 * Return the quantity to check
	 *
	 * @param array $cart_item The cart item.
	 *
	 * @return int;
	 * @since 3.0.0
	 */
	public function get_quantity( $cart_item ) {
		$quantity_mode = $this->get_quantity_based();
		$product       = $cart_item['data'];
		$product_id    = 'variation' === $product->get_type() ? $product->get_parent_id() : $product->get_id();
		$variation_id  = 'variation' === $product->get_type() ? $product->get_id() : false;
		if ( 'cart_line' === $quantity_mode ) {
			$q = $cart_item['quantity'];
		} elseif ( 'single_product' === $quantity_mode ) {
			$q = YWDPD_Counter::get_product_count( $product_id );
		} elseif ( 'single_variation_product' === $quantity_mode && $variation_id ) {
			$q = YWDPD_Counter::get_variation_count( $variation_id );
		} else {
			$q = $this->get_comulative_quantity();
		}

		return $q;
	}

	/**
	 * Return the comulative quantity to check
	 *
	 * @return int;
	 * @since 3.0.0
	 */
	public function get_comulative_quantity() {
		$qty_in   = 0;
		$qty_excl = 0;

		$type = $this->get_rule_for();

		$is_exclude_activated = $this->is_exclude_from_apply_enabled();

		if ( 'all_products' === $type ) {
			$qty_in = YWDPD_Counter::get_comulative_product_count();
		} elseif ( 'specific_products' === $type ) {
			$list_ids = $this->get_rule_for_product_list();
			$qty_in   = YWDPD_Counter::get_comulative_product_count( $list_ids );

		} elseif ( 'specific_categories' === $type ) {
			$list_ids = $this->get_rule_for_categories_list();
			$qty_in   = YWDPD_Counter::get_comulative_category_count( $list_ids );
		} elseif ( 'specific_tag' === $type ) {
			$list_ids = $this->get_rule_for_tags_list();
			$qty_in   = YWDPD_Counter::get_comulative_tag_count( $list_ids );
		}

		if ( $is_exclude_activated ) {
			$ex_type = $this->get_exclude_rule_for();
			if ( 'specific_products' === $ex_type ) {
				$list_ids = $this->get_exclude_rule_for_products_list();
				$qty_excl = YWDPD_Counter::get_comulative_product_count( $list_ids );
			} elseif ( 'specific_categories' === $ex_type ) {
				$list_ids = $this->get_exclude_rule_for_categories_list();
				$qty_excl = YWDPD_Counter::get_comulative_category_count( $list_ids );
			} elseif ( 'specific_tag' === $ex_type ) {
				$list_ids = $this->get_exclude_rule_for_tags_list();
				$qty_excl = YWDPD_Counter::get_comulative_tag_count( $list_ids );
			}
		}

		$qty_in -= $qty_excl;

		/**
		 * APPLY_FILTERS: ywdpd_get_comulative_quantity
		 *
		 * Change the comulative quantity.
		 *
		 * @param int $qty_in The value to filter.
		 * @param string $type The type of check. ( all_products|specific_products|specific_categories|specific_tag )
		 * @param YWDPD_Price_Rule $object The current object.
		 *
		 * @return int
		 */
		return apply_filters( 'ywdpd_get_comulative_quantity', $qty_in, $type, $this );
	}


	/**
	 * Return the new price
	 *
	 * @param float $price_to_discount The price to discount.
	 * @param int $quantity The quantity.
	 * @param WC_Product $product The product object.
	 *
	 * @return float
	 * @since 3.0.0
	 */
	abstract public function get_discounted_price( $price_to_discount, $quantity, $product );

	/**
	 * Return the price to discount
	 *
	 * @param array $cart_item The cart item.
	 * @param string $cart_item_key The cart item key.
	 *
	 * @return float|bool
	 * @since 3.0.0
	 */
	public function get_price_to_discount( $cart_item, $cart_item_key ) {
		$default_price = false;
		add_filter( 'yith_wcmcs_apply_currency_filters', '__return_false' );
		/**
		 * DO_ACTION: ywdpd_before_get_price_to_discount
		 *
		 * The action is triggered before get the price to discount.
		 *
		 * @param array $cart_item the cart item.
		 * @param string $cart_item_key the cart item key.
		 */
		do_action( 'ywdpd_before_get_price_to_discount', $cart_item, $cart_item_key );
		if ( isset( WC()->cart->cart_contents[ $cart_item_key ] ) ) {
			$is_ywgc = $cart_item['data'] instanceof WC_Product_Gift_Card;
			$product = $is_ywgc && isset( $cart_item['ywgc_product_as_present'] ) ? wc_get_product( $cart_item['ywgc_present_product_id'] ) : $cart_item['data'];

			if ( isset( WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts']['price_adjusted'] ) ) {

				$default_price = floatval( WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts']['price_adjusted'] );
			} else {

				$default_price = $is_ywgc && ! isset( $cart_item['ywgc_product_as_present'] ) && isset( $cart_item['ywgc_amount'] ) ? floatval( $cart_item['ywgc_amount'] ) : floatval( $product->get_price() );
			}
		}
		remove_filter( 'yith_wcmcs_apply_currency_filters', '__return_false' );
		/**
		 * DO_ACTION: ywdpd_after_get_price_to_discount
		 *
		 * The action is triggered after get the price to discount.
		 *
		 * @param array $cart_item the cart item.
		 * @param string $cart_item_key the cart item key.
		 */
		do_action( 'ywdpd_after_get_price_to_discount', $cart_item, $cart_item_key );

		/**
		 * APPLY_FILTERS: ywdpd_get_price_to_discount
		 *
		 * Filter the price to discount.
		 *
		 * @param float $default_price The value to filter.
		 * @param array $cart_item The cart item.
		 * @param string $cart_item_key The cart item key.
		 * @param YWDPD_Price_Rule $object The current object.
		 *
		 * @return float
		 */
		return apply_filters( 'ywdpd_get_price_to_discount', $default_price, $cart_item, $cart_item_key, $this );
	}

	/**
	 * Add the rule in the cart
	 *
	 * @param string $cart_item_key_to_apply The item key that allow the apply.
	 * @param string $cart_item_key_to_adjust the cart The item key where add the rule.
	 *
	 * @return bool
	 *
	 * @since 3.0.0
	 */
	abstract public function apply_rule_in_cart( $cart_item_key_to_apply, $cart_item_key_to_adjust );

	/**
	 * Save the discount rule in the cart.
	 *
	 * @param string $cart_item_key The item to add the discount.
	 * @param float $original_price The original price.
	 * @param float $discounted_price The new price.
	 *
	 * @return bool
	 * @since 3.0.0
	 */
	public function save_discount_in_cart( $cart_item_key, $original_price, $discounted_price ) {

		$result = false;

		if ( isset( WC()->cart->cart_contents[ $cart_item_key ] ) ) {
			/**
			 * APPLY_FILTERS: ywdpd_save_discount_in_cart
			 *
			 * Filter the price to discount.
			 *
			 * @param bool $save_discount_in_cart The value to filter.
			 * @param float $discounted_price The discounted price.
			 * @param float $original_price The original price.
			 *
			 * @return bool
			 */
			if ( apply_filters( 'ywdpd_save_discount_in_cart', $discounted_price !== $original_price, $discounted_price, $original_price ) ) {

				$product = WC()->cart->cart_contents[ $cart_item_key ]['data'];
				$result  = true;
				$product->update_meta_data( 'has_dynamic_price', true );

				$tax_mode = is_callable(
					array(
						WC()->cart,
						'get_tax_price_display_mode',
					)
				) ? WC()->cart->get_tax_price_display_mode() : WC()->cart->tax_display_cart;

				$display_price    = 'excl' === $tax_mode ? wc_get_price_excluding_tax( $product ) : wc_get_price_including_tax( $product );
				$discounted_price = apply_filters( 'ywdpd_get_discounted_price', $discounted_price );
				WC()->cart->cart_contents[ $cart_item_key ]['data']->set_price( $discounted_price );
				if ( ! isset( WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts'] ) ) {

					$discount_data                                                 = array(
						'by'                => array(
							$this->get_discount_mode(),
						),
						'set_id'            => $this->get_id(),
						'price_base'        => $original_price,
						'display_price'     => $display_price,
						'price_adjusted'    => $discounted_price,
						'applied_discounts' => array(
							array(
								'by'             => $this->get_discount_mode(),
								'set_id'         => $this->get_id(),
								'price_base'     => $original_price,
								'price_adjusted' => $discounted_price,
								'discount_mode'  => $this->get_discount_mode(),
							),
						),
					);
					WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts'] = $discount_data;
				} else {
					$existing     = WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts'];
					$rule_applied = array_search( $this->get_id(), array_column( $existing['applied_discounts'], 'set_id' ) ) !== false; // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
					if ( ! $rule_applied ) {
						$discount_data = array(
							'by'                => $existing['by'],
							'set_id'            => $this->get_id(),
							'price_base'        => $existing['price_base'],
							'display_price'     => $existing['display_price'],
							'price_adjusted'    => $discounted_price,
							'applied_discounts' => $existing['applied_discounts'],
						);

						WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts'] = $discount_data;

						array_push(
							WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts']['by'],
							array(
								$this->get_discount_mode(),
							)
						);
						WC()->cart->cart_contents[ $cart_item_key ]['ywdpd_discounts']['applied_discounts'][] = array(
							'by'             => $this->get_discount_mode(),
							'set_id'         => $this->get_id(),
							'price_base'     => $original_price,
							'price_adjusted' => $discounted_price,
							'discount_mode'  => $this->get_discount_mode(),
						);
					}
				}
			}
		}

		return $result;
	}

	/**
	 * Check if is possible show notice
	 *
	 * @return bool
	 * @since 4.0.0
	 */
	public function can_show_notice() {
		$option = $this->get_show_table_note_apply_to();

		return yith_plugin_fw_is_true( $option );
	}

	/**
	 * Check if is possible show adjustment notice
	 *
	 * @return bool
	 * @since 4.0.0
	 */
	public function can_show_adjustment_notice() {
		$option = $this->get_show_note_adjustment_to();

		return yith_plugin_fw_is_true( $option );
	}

	public function can_apply_rule( $cart_item ) {
		return ! isset( $cart_item['has_last_deals_applied'] );
	}
}
