<?php
namespace BricksUltimate;

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

use BricksUltimate\{Plugin,Helpers};
use BricksUltimate\ElementConditions\WooConditions;

class WooCommerce {
	public static $free_shipping_class = false;
	public function __construct() {
		$this->init_element_controls();
		
		add_action( 'wp_loaded', [$this, 'bu_wp_loadded'] );
		add_action( 'wp_loaded', [ $this, 'buwoo_cart_action' ], 20 );
		add_action( 'woocommerce_add_to_cart', [$this, 'addToCart'] );
		add_action( 'save_post', [$this, 'bu_clear_swatches_cache'] );
		add_action( 'woocommerce_after_product_object_save', [$this, 'bu_clear_swatches_cache_on_product'] );
		add_filter( 'woocommerce_add_to_cart_fragments', array( __CLASS__, 'buwoo_cart_fragment' ), 100 );
		add_filter( 'woocommerce_locate_template', [ __CLASS__, 'buwoo_woocommerce_locate_template' ], 999, 3 );
		add_filter( 'woocommerce_available_variation', [ $this, 'buwoo_available_variation'], 10, 3 );
		add_filter( 'body_class', [ $this, 'set_body_class' ], 10, 1 ); 
		add_filter( 'woocommerce_post_class', [ $this, 'bu_product_in_cart_class' ], 99, 2 );

		if( empty( Plugin::$bu_settings['recently_viewed_cookie'] ) || Plugin::$bu_settings['recently_viewed_cookie'] !== 'enabled' ) {
			add_action( 'template_redirect', [ $this, 'buwoo_track_product_view' ], 20 );
		}

		if( ! empty( Plugin::$bu_settings['cc_image_size'] ) ) {
			add_action( 'woocommerce_before_mini_cart_contents', [ $this, 'buwoo_cart_content_image_size' ] );
			add_action( 'woocommerce_after_mini_cart', function() {
				remove_filter( 'woocommerce_cart_item_thumbnail', [$this, 'buwoo_cart_item_thumbnail'], 10, 3 );
			} );
		}

		if( ! empty( Plugin::$bu_settings['free_shipping'] ) && Plugin::$bu_settings['free_shipping'] == 'enabled' ) {
			add_action( 'woocommerce_shipping_zone_method_added', [$this, 'bu_delete_cache'], 10, 3 );
			add_action( 'woocommerce_shipping_zone_method_deleted', [$this, 'bu_delete_cache'], 10, 3 );
			add_filter( 'woocommerce_package_rates', [ $this, 'bu_hide_shipping_when_free_is_available' ], 100 );
		}

		if( ! empty( Plugin::$bu_settings['local_pickup'] ) && Plugin::$bu_settings['local_pickup'] == 'enabled' ) {
			add_filter( 'woocommerce_package_rates', [ $this, 'bu_keep_local_pickup_when_free_is_available' ], 100 );
		}

		if( ! is_admin() && in_array( 'checkout', Plugin::$woo_elements ) ) {
			new \BricksUltimate\WooCommerce\Checkout();
		}

		//* Remove My Account navigation links
		if( ! empty( Plugin::$bu_settings['myaccount_default_nav'] ) 
			&& Plugin::$bu_settings['myaccount_default_nav'] == 'enabled' ) {
	        remove_action( 'woocommerce_account_navigation', 'woocommerce_account_navigation' );
		}

		//* Custom endpoints
		if( ! empty( Plugin::$bu_settings['myaccount_custom_ep'] ) 
			&& Plugin::$bu_settings['myaccount_custom_ep'] == 'enabled' ) 
		{
			new \BricksUltimate\WooCommerce\MyAccountEndpoint();

		} //* Custom endpoints end

        if( ! empty( Plugin::$bu_settings['orderbumps'] ) 
        	&& Plugin::$bu_settings['orderbumps'] == 'enabled' ) {
        	new \BricksUltimate\WooCommerce\WooOrderBumps();
        }

        if( ! empty( Plugin::$bu_settings['linked_variation'] ) 
        	&& Plugin::$bu_settings['linked_variation'] == 'enabled' ) {
        	new \BricksUltimate\WooCommerce\WooLinkedProducts();
        }

        new \BricksUltimate\WooCommerce\WooEmails();

        //* removes the variations from the product title
        add_filter('woocommerce_order_item_name', function($product_name, $item, $is_visible) {
			// Only modify for product variations
			if ($item->get_type() === 'line_item') {
				$product = $item->get_product();
				if ($product && $product->is_type('variation')) {
					// Get the parent product's title (without variation attributes)
					$parent_product = wc_get_product($product->get_parent_id());
					if ($parent_product) {
						$product_name = $parent_product->get_name();
					}
				}
			}
			return $product_name;
		}, 10, 3);
	}

	public function buwoo_cart_content_image_size() {
		add_filter( 'woocommerce_cart_item_thumbnail', [$this, 'buwoo_cart_item_thumbnail'], 10, 3 );
	}

	public function buwoo_cart_item_thumbnail( $image, $cart_item, $cart_item_key ) {
		return $cart_item['data']->get_image( Plugin::$bu_settings['cc_image_size']??'woocommerce_thumbnail' );
	}

	public function bu_wp_loadded() {
		self::$free_shipping_class = $this->getFreeShippingClass();

		if( ! empty( Plugin::$bu_settings['couponform'] ) && Plugin::$bu_settings['couponform'] == 'enabled' ) {
			remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
		}

		if( ! empty( Plugin::$bu_settings['loginform'] ) && Plugin::$bu_settings['loginform'] == 'enabled' ) {
			remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_login_form', 10 );
		}

		if( ! empty( Plugin::$bu_settings['wc_payment'] ) && Plugin::$bu_settings['wc_payment'] == 'enabled' ) {
			add_filter( 'woocommerce_subscription_needs_payment', function( $needs_payment, $subscription ){
				return false;
			}, 10, 2 );

			add_filter( 'woocommerce_cart_needs_payment', function( $needs_payment, $cart ){
				return false;
			}, 10, 2 );
		}
	}

	public function buwoo_available_variation( $atts, $variable, $variation ) {
		$ean = $variation->get_global_unique_id( 'view' ) ?? false;

		if( $ean ) {
			$atts['variation_unique_id'] = esc_attr( $ean );
		}

		return $atts;
	}

	public function init_element_controls() {
		if( ! empty( Plugin::$bu_settings['product_atc'] ) && Plugin::$bu_settings['product_atc'] == 'enabled' ) {
			new \BricksUltimate\ElementControls\ProductAddToCart();
		}

		if( ! empty( Plugin::$bu_settings['product_el'] ) && Plugin::$bu_settings['product_el'] == 'enabled' ) {
			new \BricksUltimate\ElementControls\ProductsElement();
		}

		if( ! empty( Plugin::$bu_settings['product_filter'] ) && Plugin::$bu_settings['product_filter'] == 'enabled' ) {
			new \BricksUltimate\ElementControls\ProductsFilter();
		}

		if( ! empty( Plugin::$bu_settings['related_prds'] ) && Plugin::$bu_settings['related_prds'] == 'enabled' ) {
			new \BricksUltimate\ElementControls\RelatedProducts();
		}

		if( ! empty( Plugin::$bu_settings['upcross_sells'] ) && Plugin::$bu_settings['upcross_sells'] == 'enabled' ) {
			new \BricksUltimate\ElementControls\ProductUpCrossSells();
		}

		if( ! empty( Plugin::$bu_settings['cart_items'] ) && Plugin::$bu_settings['cart_items'] == 'enabled' ) {
			new \BricksUltimate\ElementControls\CartItems();
			new \BricksUltimate\ElementControls\CartTotals();

			$file = __DIR__ . '/Elements/UltimateCartItems.php';

			if( file_exists( $file ) && class_exists('\Bricks\Woocommerce_Cart_Items') ) {
				\Bricks\Elements::register_element( $file );
			}
		}

		if( ! empty( Plugin::$bu_settings['fsn'] ) && Plugin::$bu_settings['fsn'] == 'enabled' ) {
			foreach( [ 'div', 'block' ] as $element ) {
				add_filter( "bricks/elements/$element/control_groups", array( $this, 'add_fsn_control_groups' ) );
				add_filter( "bricks/elements/$element/controls", [ $this, 'add_fsn_controls' ] );
			}
		}

		if( in_array( 'wsl', Plugin::$general_elements ) ) {
			new \BricksUltimate\ElementControls\Wishlist();
			new \BricksUltimate\ElementControls\Compare();
		}
		
		//* register condition
		new WooConditions();

		//* Enabling the brand feature
		if( ! empty( Plugin::$bu_settings['wc_brand'] ) && Plugin::$bu_settings['wc_brand'] == 'enabled' ) {
			update_option( 'wc_feature_woocommerce_brands_enabled', 'no' );
		} else {
			update_option( 'wc_feature_woocommerce_brands_enabled', 'yes' );
			update_option( 'woocommerce_remote_variant_assignment', 2 );
		}
	}

	/**
	 * Adds free shipping notice groups under style tab
	 * 
	 * @param array $control_groups
	 * @return array $control_groups
	 */
	public function add_fsn_control_groups( $control_groups ) {
		$control_groups['bufsn'] = [
				'tab'      => 'style',
				'title'    => esc_html__( 'Free Shipping Notice Wrapper', 'bricksultimate' ),
		];

		return $control_groups;
	}

	/**
	 * Adds free shipping notice controls
	 * 
	 * @param array $controls
	 * @return array $controls
	 */
	public function add_fsn_controls( $controls ) {
		$controls['isfsnWrapper'] = [
			'tab' 		=> 'style',
			'group' 	=> 'bufsn',
			'type'  	=> 'checkbox',
			'label' 	=> esc_html__( 'Using as free shipping wrapper', 'bricksultimate' ),
			'reset' 	=> true
		];

		$controls['thresholdAmount'] = [
			'tab' 		=> 'style',
			'group' 	=> 'bufsn',
			'label' 	=> esc_html__( 'Threshold amount', 'bricksultimate' ),
			'info' 		=> esc_html__( 'Threshold amount after which notice should start appear. Do not enter the currency.', "bricksultimate" ),
			'type' 		=> 'text',
			'placeholder' => 50,
			'hasDynamicData' => false,
			'required' 	=> [ 'isfsnWrapper', '=', true ]
		];

		$controls['noticeSelector'] = [
			'tab' 		=> 'style',
			'group' 	=> 'bufsn',
			'type'  	=> 'text',
			'label' 	=> esc_html__( 'Free shipping notice selector', 'bricksultimate' ),
			'placeholder' => '.bu-fsn-text--notice',
			'required' 	=> [ 'isfsnWrapper', '=', true ]
		];

		$controls['fsnAction'] = [
			'tab' 		=> 'style',
			'group' 	=> 'bufsn',
			'type' 		=> 'select',
			'label' 	=> esc_html__( 'Action', 'bricksultimate' ),
			'info' 		=> esc_html__( 'When free shipping amount is reached.', "bricksultimate" ),
			'options' 	=> [
				'hide' 	=> __('Hide'),
				'msg' 	=> __('Show success message', 'bricksultimate')
			],
			'default' 	=> 'hide',
			'required' 	=> [ 'isfsnWrapper', '=', true ]
		];

		$controls['sucmsgSelector'] = [
			'tab' 		=> 'style',
			'group' 	=> 'bufsn',
			'type'  	=> 'text',
			'label' 	=> esc_html__( 'Success message selector', 'bricksultimate' ),
			'placeholder' => '.bu-fsn-text--success',
			'required' 	=> [ 'fsnAction', '=', 'msg' ]
		];

		return $controls;
	}

	/**
	 * Adding the custom class
	 *
	 * @author  Paul Chinmoy
	 * @since   1.6.9
	 *
	 * @return  void
	 */
	public function bu_product_in_cart_class( $classes, $product ) {
		if( ! is_null( WC()->cart ) && is_a( $product, '\WC_Product' ) ) {
			foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
				if ( $cart_item['product_id'] == $product->get_id() ) {
					$classes[] = 'added-to-cart' ;
					return $classes;
				}
			}
		}

		return $classes;
	}

	/**
	 * Hide shipping rates when free shipping is available.
	 * Updated to support WooCommerce 2.6 Shipping Zones.
	 *
	 * @param array $rates Array of rates found for the package.
	 * @return array
	 */
	function bu_hide_shipping_when_free_is_available( $rates ) {
		$free = [];
		foreach ( $rates as $rate_id => $rate ) {
			if ( 'free_shipping' === $rate->method_id ) {
				$free[ $rate_id ] = $rate;
				break;
			}
		}

		return ! empty( $free ) ? $free : $rates;
	}

	/**
	 * Hide shipping rates when free shipping is available, but keep "Local Pickup".
	 *
	 * @param array $rates Array of rates found for the package.
	 * @return array
	 */
	public function bu_keep_local_pickup_when_free_is_available( $rates ) {
		$new_rates = [];
		foreach ( $rates as $rate_id => $rate ) {
			if ( 'free_shipping' === $rate->method_id ) {
				$new_rates[ $rate_id ] = $rate;
				break;
			}
		}

		if ( ! empty( $new_rates ) ) {
			foreach ( $rates as $rate_id => $rate ) {
				if ('local_pickup' === $rate->method_id ) {
					$new_rates[ $rate_id ] = $rate;
					break;
				}
			}
		}

		return ! empty( $new_rates ) ? $new_rates : $rates;
	}

	/**
	 * Adding product to cart
	 * when clicking on the Buy Now button
	 * 
	 * @return void
	 */
	public function buwoo_cart_action() {
		if ( isset( $_GET['bu_empty_cart'] ) && 'yes' === esc_html( $_GET['bu_empty_cart'] ) ) {
			WC()->cart->empty_cart();

			//if( isset( $_GET['bu_redirect'] ) && 'yes' === esc_html( $_GET['bu_redirect'] ) ) {
				$referer  = esc_url( remove_query_arg( [ 'bu_empty_cart' ] ) );
				wp_safe_redirect( $referer ); 
				exit();
			//}
		}

		if( isset( $_GET['bu_buy_now'] ) && $_GET['bu_buy_now'] == 'yes' ) {
			if( isset( $_GET['keep_cart_items'] ) && $_GET['keep_cart_items'] == 'no' ) { WC()->cart->empty_cart(); }
			
			$product_id = absint( $_GET['add_to_cart'] );

			WC()->cart->add_to_cart( $product_id, 1 );

			$referer  = esc_url( remove_query_arg( [ 'add_to_cart', 'bu_buy_now', 'keep_cart_items' ] ) );
			wp_safe_redirect( $referer ); 
			exit();
		}

		if( isset( $_POST['bu_buy_now'] ) && $_POST['bu_buy_now'] == 'yes' ) {
			$flag 				= false;
			$keep_cart_items 	= isset( $_POST['keep_cart_items'] ) ? $_POST['keep_cart_items'] : 'no';
			$quantities 		= $_POST['quantity'];

			//* grouped product
			if( is_array( $quantities ) ) {
				
				$qtys = array_flip( $quantities );
				
				foreach( $qtys as $quantity => $product_id ) {
					if( ! empty( $quantity ) )  {
						if( $keep_cart_items == 'no' && $flag === false ) { WC()->cart->empty_cart(); }
						if( $keep_cart_items == 'no' ){ WC()->cart->add_to_cart( absint( $product_id ), absint( $quantity ) ); }
						$flag = true;
					}
				}

			} else {
				
				$flag = true;

				//* remove the existing cart items and add new item
				if( $keep_cart_items == 'no' )
					WC()->cart->empty_cart();
				
				$product_id = absint( $_POST['product_id'] );
				$quantity = absint( $_POST['quantity'] );

				if ( isset( $_POST['variation_id'] ) ) {
					$variation_id = absint( $_POST['variation_id'] );
					WC()->cart->add_to_cart( $product_id, $quantity, $variation_id );
				} else {
					WC()->cart->add_to_cart( $product_id, $quantity );
				}
			}

			if( $flag ) {
				//* clear the all notices
				wc_clear_notices();

				wp_safe_redirect( esc_url( $_POST['bu_redirect_url'] ) ); 
				exit();
			}
		}
	}

	/**
	 * Updates fragments data
	 */
	public static function buwoo_cart_fragment( $fragments ) {
		ob_start();
		?>
		<span class="bu-cart-counter cart-contents-count"><?php echo is_object( WC()->cart ) ? count( WC()->cart->get_cart_contents() ) : '0'; ?></span>
		<?php
		
		$fragments['span.cart-contents-count'] = ob_get_clean();

		ob_start();
		?>
		<span class="bu-cart-counter cart-items-quantities"><?php echo is_object( WC()->cart ) ? WC()->cart->get_cart_contents_count() : '0'; ?></span>
		<?php
		
		$fragments['span.cart-items-quantities'] = ob_get_clean();

		ob_start();
		?>
		<span class="bu-cart-subtotal"><?php echo self::calculate_cart_subtotal(); ?></span>
		<?php
		$fragments['span.bu-cart-subtotal'] = ob_get_clean();
		ob_start();
		?>
		<span class="bu-cart-total"><?php echo self::calculate_cart_total(); ?></span>
		<?php
		$fragments['span.bu-cart-total'] = ob_get_clean();
		$decimals 	= \wc_get_price_decimals() == 0 ? 2 : \wc_get_price_decimals();
		$fragments['span.bu-cart-price'] = number_format( self::get_customer_order_amount(), $decimals, wc_get_price_decimal_separator(), wc_get_price_thousand_separator() );
		if( wc_shipping_enabled() ) {
			$fragments['span.isFreeShippingAvailable'] = self::isFreeShippingAvailable();
			$fragments['span.freeShippingMinAmount'] = self::freeShippingMinAmount();
			$fragments['span.hasFreeShippingMethod'] = self::hasFreeShippingMethod();
			$fragments['span.bu-shipping-cost'] = self::getShippingCost();
		}
		ob_start();
		?>
		<span class="fsn-updated-price"><?php echo wc_price( self::freeShippingUpdatedAmount() ); ?></span>
		<?php
		$fragments['span.fsn-updated-price'] = ob_get_clean();
		ob_start();
		?>
		<span class="bu-cart-order-total"><?php echo is_object( WC()->cart ) ? WC()->cart->get_total() : wc_price( 0 ) ; ?></span>
		<?php
		$fragments['span.bu-cart-order-total'] = ob_get_clean();
		ob_start();
		?>
		<span class="bu-cart-order-total-no-tax"><?php echo is_object( WC()->cart ) ? wc_price( WC()->cart->get_total( 'edit' ) - WC()->cart->get_total_tax() ) : wc_price( 0 ) ; ?></span>
		<?php
		$fragments['span.bu-cart-order-total-no-tax'] = ob_get_clean();
		ob_start();
		?>
		<span class="bu-total-tax"><?php echo is_object( WC()->cart ) ? wc_price( WC()->cart->get_total_tax() ) : wc_price( 0 ) ; ?></span>
		<?php
		$fragments['span.bu-total-tax'] = ob_get_clean();
		if( ! empty( Plugin::$bu_settings['mctpl'] ) ) {
			foreach( (array) Plugin::$bu_settings['mctpl'] as $mctpl ) {
				ob_start();
				$tpl_post_id = explode("|", $mctpl );
				self::buwoo_minicart_content( $mctpl );
				$cartcontent = ob_get_clean();
				if( ! empty( $cartcontent ) ) $fragments['div.bu-minicart-' . $tpl_post_id[0]??$mctpl] = $cartcontent;
			}
		} 
		
		if( ! empty( Plugin::$bu_settings['wccntrsf'] ) ) {
			foreach( (array) Plugin::$bu_settings['wccntrsf'] as $cnt ) {
				$tpl_post_id = explode("|", $cnt );
				ob_start();
				self::buwoo_content_updater( $cnt );
				$content = ob_get_clean();
				if( ! empty( $content ) ) $fragments['div.bu-' . $tpl_post_id[0]] = $content;
			}
		}

		remove_filter( 'woocommerce_add_to_cart_fragments', array( __CLASS__, 'buwoo_cart_fragment' ), 100 );

		return $fragments;
	}

	public static function calculate_cart_subtotal($formated = true) {
		if( is_object( WC()->cart ) ) {
			$price = WC()->cart->get_displayed_subtotal();
		} else {
			$price = 0;
		}

		if( $formated )
			return wc_price( $price );
		else
			return $price;
	}

	public static function calculate_cart_total($formated = true) {
		if( is_object( WC()->cart ) ) {
			$price = WC()->cart->get_cart_contents_total();
		} else {
			$price = 0;
		}

		if( $formated )
			return wc_price( $price );
		else
			return $price;
	}

	public static function isFreeShippingAvailable() {
		if( self::$free_shipping_class ) {
			foreach( self::$free_shipping_class as $free_shipping ) {
				$shippingObj = new \WC_Shipping_Free_Shipping( $free_shipping->instance_id );

				if( $shippingObj->is_available([]) )
					return 'yes';
				else
					return 'no';
			}
		}

		return 'no';
	}

	public static function hasFreeShippingMethod() {
		if( self::$free_shipping_class )
			return 'yes';
		else
			return 'no';
	}

	public static function freeShippingMinAmount() {
		$min_amount = 0.00;
		if( self::$free_shipping_class ) {
			foreach( self::$free_shipping_class as $free_shipping ) {
				$shippingObj = new \WC_Shipping_Free_Shipping( $free_shipping->instance_id );
				$min_amount = $shippingObj->get_option( 'min_amount', 0.00);

				return ( strpos($min_amount, \wc_get_price_decimal_separator() ) !== false ) ? $min_amount : $min_amount . \wc_get_price_decimal_separator() . '00';
			}
		}

		return $min_amount;
	} 

	public static function freeShippingUpdatedAmount() {
		$decimals 	= \wc_get_price_decimals() == 0 ? 2 : \wc_get_price_decimals();
		$formattedTotal = number_format( self::get_customer_order_amount(), $decimals, wc_get_price_decimal_separator(), wc_get_price_thousand_separator() );
		$order_amount = str_replace( [ wc_get_price_decimal_separator(), wc_get_price_thousand_separator() ], '', $formattedTotal );
		$min_amount = str_replace( [ wc_get_price_decimal_separator(), wc_get_price_thousand_separator() ], '', self::freeShippingMinAmount() );
		$diff = ( absint( $min_amount ) - absint( $order_amount ) );

		if( $diff > 0 ) {
			return ( $diff / 100 );
		} else {
			return ( $min_amount / 100 );
		}
	}

	public static function get_customer_order_amount() {
		$total = 0;

		if( ! is_object( WC()->cart ) )
			return $total;

		$ignore_discounts = 'no';

		$total = WC()->cart->get_displayed_subtotal();

		if ( WC()->cart->display_prices_including_tax() ) {
			$total = $total - WC()->cart->get_discount_tax();
		}

		if( self::$free_shipping_class ) {
			foreach( self::$free_shipping_class as $free_shipping ) {
				$ignore_discounts = ( new \WC_Shipping_Free_Shipping( $free_shipping->instance_id ) )->get_option( 'ignore_discounts' );
			}
		}

		if ( 'no' === $ignore_discounts ) {
			$total = $total - WC()->cart->get_discount_total();
		}

		return \Automattic\WooCommerce\Utilities\NumberUtil::round( $total, \wc_get_price_decimals() );
	}

	public function getFreeShippingClass() {
		if( ! empty( Plugin::$bu_settings['fsn'] ) && Plugin::$bu_settings['fsn'] == 'enabled' ) {
			global $wpdb;

			$zoneId = $this->getUserSelectedZoneId();

			$fsn_query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_methods 
				WHERE method_id = %s AND is_enabled = %d AND zone_id = %d ORDER BY method_order ASC LIMIT 1", 
				'free_shipping', 
				1, 
				$zoneId
			);

			$cache_key = 'free_shipping_methods_' . $zoneId;
			$zone_data = wp_cache_get($cache_key);
			if (false === $zone_data) {
				$zone_data = $wpdb->get_results($fsn_query, OBJECT);
				wp_cache_set($cache_key, $zone_data, '', 3600);
			}

			if ( empty( $zone_data ) ) {
				return false;
			} else {
				return $zone_data;
			}
		}

		return false;
	}

	public function getUserSelectedZoneId() {
		global $woocommerce;

		$shipping_zone_id = false;

		if( isset( WC()->session ) ) {
			if( ( ! empty( WC()->session ) && is_array( WC()->session->get( 'chosen_shipping_methods' ) ) ) 
				|| ( isset( $_GET['wc-ajax'] ) && $_GET['wc-ajax'] == 'update_order_review') ) {

				if($shipping_zone_id === false) {
					$shipping_zone_id = $this->getUserSelectedZone();
				}
			}
		}

		if($shipping_zone_id === false || $shipping_zone_id <= 0 ) {
			$shipping_zone_id = $this->getGeoLocatedZone();
		}

		return $shipping_zone_id ;
	}

	private function getUserSelectedZone() {
		global $woocommerce;
		if( is_object( WC()->cart ) ) {
			$shipping_packages =  WC()->cart->get_shipping_packages();

			$shipping_zone = wc_get_shipping_zone( reset( $shipping_packages ) );

			if( is_object( $shipping_zone ) ) {
				return $shipping_zone->get_id();
			}
		}
		return false;
	}

	private function getGeoLocatedZone() {
		$destination = $this->ipBasedDestination();

		if(empty($destination['destination']['country'])) return false;

		$shipping_zone = \WC_Shipping_Zones::get_zone_matching_package( $destination );
		if( is_object($shipping_zone) ){
			return $shipping_zone->get_id();
		}

		return false;
	}

	private function ipBasedDestination() {
		$geo_instance  = new \WC_Geolocation();
		$user_ip  = $geo_instance->get_ip_address();
		$user_geodata = $geo_instance->geolocate_ip($user_ip);

		$destination['destination']['country'] =  $user_geodata['country'];
		$destination['destination']['state'] =  $user_geodata['state'];
		$destination['destination']['postcode'] = "";
		return $destination;
	}

	public static function getShippingCost( $echoHtml = true ) {
		$html = sprintf('<span class="bu-shipping-cost">%1$s</span>', wc_price( 0 ) );
		//if ( \WC()->cart->needs_shipping() && \WC()->cart->show_shipping() ) : endif;
		$total = 0;
		$packages = \WC()->shipping()->get_packages();

		if( $packages ) {
			foreach ( $packages as $i => $package ) {
				$chosen_method     = WC()->session->chosen_shipping_methods[ $i ] ?? '';
				$available_methods = empty( $package['rates'] ) ? array() : $package['rates'];

				foreach ( $available_methods as $method ) {
					if ( (string) $method->id !== (string) $chosen_method ) { 
						continue;
					}

					if ( 0 >= $method->cost ) {
						continue;
					}

					$total += $method->cost;

					if ( \WC()->cart->display_prices_including_tax() ) {
						$total += $method->get_shipping_tax();
					}
				}
			}
		}

		if( $echoHtml === true) {
			if ( 0 < $total ) {
				$html = sprintf('<span class="bu-shipping-cost">%1$s</span>', wc_price( $total ) );
			} else {
				$html = sprintf('<span class="bu-shipping-cost">%1$s</span>', esc_html__( 'Free', 'woocommerce' ) );
			}
		} else {
			if ( 0 < $total ) {
				$html = $total;
			} else {
				$html = 'free';
			}
		}

		return $html;
	}

	public static function appliedCoupons() {
		if( is_object( WC()->cart ) ) {
			foreach ( WC()->cart->get_coupons() as $code => $coupon ) :
				echo "<div class=\"cart-discount coupon-". esc_attr( sanitize_title( $code ) ) . "\">";
				echo "<span class=\"bu-coupon-code\">" . __( 'Discount:', 'woocommerce' ) . " <strong>" . $code . '</strong> <a href="' . esc_url( add_query_arg( 'remove_coupon', rawurlencode( $code ), \Automattic\Jetpack\Constants::is_defined( 'WOOCOMMERCE_CHECKOUT' ) ? wc_get_checkout_url() : wc_get_cart_url() ) ) . '" class="bu-remove-coupon" data-coupon="' . esc_attr( $code ) . '">' . __( '[Remove]', 'woocommerce' ) . "</a></span>";
				
				echo "<span class=\"cart-discount-value\">";
				
					if ( is_string( $coupon ) ) {
						$coupon = new \WC_Coupon( $coupon );
					}

					$discount_amount_html = '';

					$amount = WC()->cart->get_coupon_discount_amount( $coupon->get_code(), WC()->cart->display_cart_ex_tax );
					$discount_amount_html = '-' . wc_price( $amount );

					if ( $coupon->get_free_shipping() && empty( $amount ) ) {
						$discount_amount_html = __( 'Free shipping coupon', 'woocommerce' );
					}

					echo apply_filters( 'woocommerce_coupon_discount_amount_html', $discount_amount_html, $coupon );
				echo "</span>";

				echo "</div>";
			endforeach;
		}
	}

	public static function minCartQty($product, $cart_item, $item_key) {
		$quantity = $cart_item['quantity'] ?? 1;
		$args = [
			//'input_id'     => uniqid( 'quantity_' ),
			'input_name'   => 'quantity',
			'input_value'  => $quantity,
			'classes'      => apply_filters( 'woocommerce_quantity_input_classes', array( 'input-text', 'qty', 'text' ), $product ),
			'max_value'    => apply_filters( 'woocommerce_quantity_input_max', $product->get_max_purchase_quantity(), $product ),
			'min_value'    => apply_filters( 'woocommerce_quantity_input_min', $product->get_min_purchase_quantity(), $product ),
			'step'         => apply_filters( 'woocommerce_quantity_input_step', 1, $product ),
			'pattern'      => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
			'inputmode'    => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
			'product_name' => $product ? $product->get_title() : '',
			'placeholder'  => apply_filters( 'woocommerce_quantity_input_placeholder', '', $product ),
			'autocomplete' => apply_filters( 'woocommerce_quantity_input_autocomplete', 'off', $product ),
		];

		$args = apply_filters( 'woocommerce_quantity_input_args', $args, $product );
		$args['input_value'] = $quantity;

		// Apply sanity to min/max args - min cannot be lower than 0.
		$args['min_value'] = max( $args['min_value'], 0 );
		$args['max_value'] = 0 < $args['max_value'] ? $args['max_value'] : '';

		if( '' !== $args['max_value'] && $args['max_value'] == 1 )
			return;

		// Max cannot be lower than min if defined.
		if ( '' !== $args['max_value'] && $args['max_value'] < $args['min_value'] ) {
			$args['max_value'] = $args['min_value'];
		}
		
		if( class_exists( 'Morningtrain\WooAdvancedQTY\Plugin\Controllers\InputArgsController' ) ) {
			$advnargs = Morningtrain\WooAdvancedQTY\Plugin\Controllers\InputArgsController::applyArgs([], $cart_item['product_id'], true);
			if( isset( $advnargs['min_value'] ) && $advnargs['min_value'] > $args['min_value'] )
				$args['min_value'] = $advnargs['min_value'];
			
			if( isset( $advnargs['max_value'] ) && $advnargs['max_value'] > $args['max_value'] )
				$args['max_value'] = $advnargs['max_value'];
		}

		/* translators: %s: Quantity. */
		$label = ! empty( $args['product_name'] ) ? sprintf( esc_html__( '%s quantity', 'woocommerce' ), wp_strip_all_tags( $args['product_name'] ) ) : esc_html__( 'Quantity', 'woocommerce' );

		ob_start();
		?>
		<div class="quantity">
			<?php do_action( 'woocommerce_before_quantity_input_field' ); ?>
			<label class="screen-reader-text"><?php echo esc_attr( $label ); ?></label>
			<input
				type="number"
				class="<?php echo esc_attr( join( ' ', (array) $args['classes'] ) ); ?>"
				step="<?php echo esc_attr( $args['step'] ); ?>"
				min="<?php echo esc_attr( $args['min_value'] ); ?>"
				max="<?php echo esc_attr( 0 < $args['max_value'] ? $args['max_value'] : '' ); ?>"
				name="<?php echo esc_attr( $args['input_name'] ); ?>"
				value="<?php echo esc_attr( $args['input_value'] ); ?>"
				title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ); ?>"
				size="4"
				placeholder="<?php echo esc_attr( $args['placeholder'] ); ?>"
				inputmode="<?php echo esc_attr( $args['inputmode'] ); ?>"
				autocomplete="<?php echo esc_attr( isset( $args['autocomplete'] ) ? $args['autocomplete'] : 'on' ); ?>"
			/>
			<?php do_action( 'woocommerce_after_quantity_input_field' ); ?>
		</div>
		<?php

		return apply_filters( 'woocommerce_cart_item_quantity', ob_get_clean(), $item_key, $cart_item);
	}

	function addToCart() {
		add_action("wp_head", [$this, "addInlineScript"] );
	}
	
	function addInlineScript() {
    ?>
		<script>
			let BU_ADDED_TO_CART = true;
		</script>
    <?php
	}

	public static function buwoo_woocommerce_locate_template( $template, $template_name, $template_path ) {
		$root = Plugin::instance()->get_root_path();
		$new_template = false;

		if( ! empty( Plugin::$bu_settings['swatches'] ) && Plugin::$bu_settings['swatches'] == 'enabled' && $template_name === 'single-product/add-to-cart/variable.php' ) {

			$new_template = $root . 'templates/' . $template_name;

			if( file_exists( $new_template ) ) {
				wp_enqueue_script( 'bu-swatches' );
				return $new_template;
			}
		}

		if( $template_name === 'cart/mini-cart.php' && in_array( 'cartcontent', Plugin::$woo_elements ) ) {
			$new_template = $root . 'templates/' . $template_name;
		}

		if( $new_template !== false && file_exists( $new_template ) )
			return $new_template;

		return $template;
	}

	function bu_clear_swatches_cache( $post_id ) {
		$transient_name = 'bu_swatches_loop_cache_' . $post_id;
		delete_transient( $transient_name );

		return $post_id;
	}

	function bu_clear_swatches_cache_on_product( $data ) {
		$post_id = $data->get_id();
		$transient_name = 'bu_swatches_loop_cache_' . $post_id;
		delete_transient( $transient_name );
	}

	private function bu_delete_cache( $instance_id, $method_id, $zone_id ) {
		if ( $method_id == 'free_shipping' ) {
			$cache_key = 'free_shipping_methods_' . $zone_id;
			wp_cache_delete( $cache_key );
		}
	}

	/**
	 * Set the class in body tag
	 */
	public function set_body_class( $classes ) {
		if( empty( get_option( \BricksUltimate\Admin\License::API_EL_STATUS_FIELD ) ) )
			$classes[] = 'woocommerce-bricks-tpl';

		if( empty( \BricksUltimate\Admin\License::STORE_URL ) || \BricksUltimate\Admin\License::STORE_URL == '' )
			$classes[] = 'woocommerce-bricks-tpl';

		return $classes;
	}

	function buwoo_track_product_view() {
		if ( ! is_singular( 'product' ) ) {
			return;
		}

		global $post;

		if ( empty( $_COOKIE['woocommerce_recently_viewed'] ) ) {
			$viewed_products = [];
		} else {
			$viewed_products = wp_parse_id_list( (array) explode( '|', wp_unslash( $_COOKIE['woocommerce_recently_viewed'] ) ) );
		}

		$keys = array_flip( $viewed_products );

		if ( isset( $keys[ $post->ID ] ) ) {
			unset( $viewed_products[ $keys[ $post->ID ] ] );
		}

		$viewed_products[] = $post->ID;

		if ( count( $viewed_products ) > 15 ) {
			array_shift( $viewed_products );
		}

		// Store for session only.
		wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );
	}

	/**
	 * Has low stock
	 * 
	 * @param object $product WooCommerce product object
	 */
	public static function has_low_stock( $product ) {
		$stock_quantity = $product->get_stock_quantity();
		$low_stock_amount = $product->get_low_stock_amount();

		return ( $low_stock_amount && $stock_quantity <= $low_stock_amount );
	}

	public static function get_stock_quantity( $product ) {
		if ( ! $product->is_type('variable') ) {
			return $product->get_stock_quantity();
		}

		$stock_quantity = 0;

		if ( $product->is_type('variable') ) {
			foreach ( $product->get_visible_children() as $key => $variation_id ) {
				$variation = wc_get_product( $variation_id );
				$stock_quantity += $variation->get_stock_quantity();
			}
		}

		return $stock_quantity;
	}

	public static function buwoo_minicart_content( $element_id ) {
		if( empty( $element_id ) ) return;
	
		$output = '';
		if( class_exists( '\BricksUltimate\Elements\WooMiniCart' ) ) {
			$tpl_post_id = explode("|", $element_id );
			
			if( ! empty( $tpl_post_id[2] ) && $tpl_post_id[2] > 0 )
				\Bricks\Database::$active_templates['header'] = $tpl_post_id[2];

			$settings = \Bricks\Helpers::get_element_data( $tpl_post_id[1], $tpl_post_id[0]??$element_id );

			if( $settings ) {
				foreach ( $settings['elements'] as $element ) {
					\Bricks\Frontend::$elements[ $element['id'] ] = $element;
				}

				add_filter( 'bricks/element/render_attributes', [ '\BricksUltimate\Helpers', 'bu_add_attributes' ], 1000, 3 );
				add_filter( 'woocommerce_product_variation_title_include_attributes', '__return_false' );

				$element_instance = new \BricksUltimate\Elements\WooMiniCart( $settings['element'] );
				$output = "<{$element_instance->tag} class=\"bu-minicart-{$element_instance->id} bu-minicart-wrap\">";
				$output .= \Bricks\Frontend::render_children($element_instance);
				$output .= "<{$element_instance->tag}>";

				\wc_clear_notices();

				remove_filter( 'bricks/element/render_attributes', [ '\BricksUltimate\Helpers', 'bu_add_attributes' ], 1000, 3 );
			}
		}

		echo $output;
	}

	public static function buwoo_content_updater( $element_id ) {
		if( empty( $element_id ) ) return;
		$tpl_post_id = explode("|", $element_id );
		$output = '';

		if( class_exists( '\BricksUltimate\Elements\WooReviewOrder' ) ) {
			if( ! empty( $tpl_post_id[2] ) && $tpl_post_id[2] > 0 )
				\Bricks\Database::$active_templates['header'] = $tpl_post_id[2];

			$settings = \Bricks\Helpers::get_element_data( $tpl_post_id[1], $tpl_post_id[0] );
			if( $settings ) {
				foreach ( $settings['elements'] as $element ) {
					\Bricks\Frontend::$elements[ $element['id'] ] = $element;
				}

				$element_instance = new \BricksUltimate\Elements\WooReviewOrder( $settings['element'] );
				$element_instance->load();
				ob_start();
				$element_instance->init();
				echo \Bricks\Frontend::render_element($settings);
				$output .= ob_get_clean();
			}
		}

		echo $output;
	}
}