<?php 
namespace WCQT\classes\com;

class Product
{
	var $quotable_product_cache;
	public function __construct()
	{
		if(is_admin())
		{
			add_action('wp_ajax_wcqt_get_products_list', array(&$this, 'ajax_get_products_partial_list'));
			add_action('wp_ajax_wcqt_get_product_categories_list', array(&$this, 'ajax_get_product_categories_partial_list'));
			add_action('wp_ajax_wcqt_get_attributes_list', array(&$this, 'ajax_get_product_attributes_partial_list'));
		}
	}
	public function quotable_variations($product) //This is used in case the user has selected specific variations
	{
		global $wcqt_product_model, $wcqt_option_model;
		$product = !is_object($product) ? wc_get_product($product) : $product;
		if(!$product)
			return false;
		
		$options = $wcqt_option_model->get_options();
		$is_variable = $product->is_type('variable');
		$quotable_products = $wcqt_product_model->get_quotable_products_list();
		$strategy = wcqt_get_value_if_set($options, array('exclusion', 'policy'), "include") == "exclude" ? "except" : "selected" ;
		
		if($is_variable) //In case only some variation are quotable
		{
			$children = $product->get_children();
			$result = array();
			if($strategy == "selected" && ($quotable_products == "always" || !in_array($product->get_id(), $quotable_products)))
			{
				foreach($children as $variation_id)
					if($quotable_products == "always" || in_array($variation_id, $quotable_products))
						$result[] = $variation_id;
			}
			else if($strategy == "except")
			{
				$children = $product->get_children();
				$selected_product = wcqt_get_value_if_set($options, array('exclusion', 'products'), array());
				
				if($quotable_products != "always" && array_intersect($children, $selected_product)) //If at least one variation has been selected
				{
					foreach($children as $variation_id)
						if(!in_array($variation_id, $selected_product))
							$result[] = $variation_id;
				}	
				else if($quotable_products == "always" || in_array($product->get_id(), $quotable_products))
				{
					foreach($product->get_children() as $variation_id)
						$result[] = $variation_id;
				}
			}
			return $result;
		}
		
		return false;
	}
	public function get_product_id($product)
	{
		return $product->get_id();
	}
	public function get_my_name($product_id)
	{
		$product = wc_get_product($product_id); 
		return  $product != null ? $product->get_title() : "";
	}
	public function get_variation_parent_name($variation_id)
	{
		return $this->get_my_name($variation_id);
	}
	public function get_product_meta($product_id, $key, $unique = true)
	{
		$product = wc_get_product($product_id);
		if($product == null)
			return "";
		return $product->get_meta( $key, $unique);
	}
	public function get_quotable_products_list($consider_current_user_role = true)
	{
		if(isset($this->quotable_product_cache))
			return $this->quotable_product_cache;
		
		global $wcqt_option_model, $wcqt_user_model, $wcqt_wpml_model;
		$options = $wcqt_option_model->get_options();
		
		$strategy = wcqt_get_value_if_set($options, array('exclusion', 'policy'), "include") == "exclude" ? "except" : "selected" ;
		$get_post_belonging_to_children_categories = wcqt_get_value_if_set($options, array('exclusion', 'exclude_sub_categories'), false) == "true" ? "selected_only" : "selected_and_children" ;
		$selected_categories = wcqt_get_value_if_set($options, array('exclusion', 'categories'), array());
		$selected_product = wcqt_get_value_if_set($options, array('exclusion', 'products'), array());
		$can_request_a_quote = $wcqt_user_model->can_request_a_quote();
		
		if(($consider_current_user_role && !$can_request_a_quote) || ($strategy == "except" && empty($selected_categories) && empty($selected_product)))
			return array();
		
		if(empty($selected_categories) && empty($selected_product))
			return "always";
		
		$found_by_categories =  !empty($selected_categories) ? $this->get_post_ids_using_categories("product_cat", $selected_categories, $get_post_belonging_to_children_categories, $strategy, $selected_product) : array();
		if($strategy == "selected")
		{
			$found = array_merge($selected_product, $found_by_categories);
		}
		else
		{
			if(!empty($found_by_categories))
				$found = $found_by_categories;
			else if(!empty($selected_product))
				$found = $this->get_complementry_ids($selected_product);
			else
				$found = array(-1); 
		}
		//WPML
		$translations = array();
		foreach($found as $product_id)
			if($product_id) //it could be -1
			{
				$translatated_ids = $wcqt_wpml_model->get_all_translation_ids($product_id);
				if($translatated_ids)
					foreach($translatated_ids as $translated_id )
						$found[] = $translated_id;
			}
		
		$this->quotable_product_cache = $found;
		
		return $this->quotable_product_cache;
	}
	private function get_post_ids_using_categories($category_type_name, $selected_categories, $get_post_belonging_to_children_categories, $strategy, $product_to_exclude = array())
	{
		/* 
			$category_type_name: 							"product_cat"
			$selected_categories:  						 categories ids for which products ids have to be retrieved
			$get_post_belonging_to_children_categories : "selected_only" || "selected_and_children"
			$strategy:									 selected || except
		
		*/
		//
		global $wpdb, $wcqt_wpml_model;
		$not_suffix = $strategy == "selected" ? "  " : "NOT ";
		$results = $additional_categories_ids = array();
		$wcqt_wpml_model->switch_to_default_language();
		
		//Retrieve children categories id
		if($get_post_belonging_to_children_categories == 'selected_and_children')
		{
			foreach($selected_categories as $current_category)
			{
				$args = array(
						'type'                     => 'product',
						'post_status'              => 'publish',
						'child_of'                 => $current_category,
						'parent'                   => '',
						'orderby'                  => 'name',
						'order'                    => 'ASC',
						'hide_empty'               => 1,
						'hierarchical'             => 1,
						'exclude'                  => '',
						'include'                  => '',
						'number'                   => '',
						'taxonomy'                 => $category_type_name,
						'pad_counts'               => false,
						'suppress_filters' 		   => false
						/* 'suppress_filter' 		   => false */

					); 

					$categories = get_categories( $args );
					foreach($categories as $result)
					{
						if(!is_array($result))
							$additional_categories_ids[] = (int)$result->term_id;
					}
			}
		}
		if(!empty($additional_categories_ids))
			$selected_categories = array_merge($selected_categories, $additional_categories_ids);
		
	//Get products
	$args = array('suppress_filters' => false, //default: true.
				  'post_type' => array('product'), //product_variation have not category associated
				  'numberposts' => -1,
				  'fields' => 'ids',
				  'post_status' => $this->get_selectable_post_statuses_query_string(), //add others? as option? -> get_post_statuses();
				  'post__not_in' => $product_to_exclude,
				  'tax_query'             => array(
												array(
													'taxonomy'      => 'product_cat',
													'terms'         => $selected_categories,
													'field'         => 'id',
													'operator'      => 'IN'
													)
									  
											)
				);
		$products = get_posts($args);
		//Get variations (if any)
		$variations = array();
		if(!empty($products))
		{
			$args = array('suppress_filters' => false, //default: true.
						  'post_type' => array('product', 'product_variation'),
						  'numberposts' => -1,
						  'fields' => 'ids',
						  'post_parent__in' => $products,
						  'post_status' => $this->get_selectable_post_statuses_query_string()
						 );
			$variations = get_posts($args);
		}
		$products = array_merge($products, $variations);
		
		//Get complementary 
		if($strategy != 'selected')
		{
			$args = array('suppress_filters' => false, 
					  'post_type' => array('product', 'product_variation'), 
					  'numberposts' => -1,
					  'fields' => 'ids',
					  'post_status' => $this->get_selectable_post_statuses_query_string(), 
					  'post__not_in' => $products
					);
			$products = get_posts($args);		
		}
		return $products;
	}
	
	//Misc
	public function has_attribute_value($product_id, $attribute_id)
	{
		global $wpdb;
		$wc_product = wc_get_product($product_id);
		$query_string = "SELECT product_attributes.term_id as id, product_attributes.name as attribute_name, product_attributes.slug as slug, tax.taxonomy as taxonomy
							 FROM {$wpdb->terms} AS product_attributes
							 LEFT JOIN {$wpdb->term_taxonomy} AS tax ON tax.term_id = product_attributes.term_id 							 						 	 
							 WHERE product_attributes.term_id  = {$attribute_id}
							";
			
		$query_string .=  " GROUP BY product_attributes.term_id ";
		$result = $wpdb->get_results($query_string ) ;
		
		$product_attributes = $wc_product->get_attributes();
		$product_attributes = wcqt_get_value_if_set($product_attributes, $result[0]->taxonomy, "");
		if(is_a($product_attributes, 'WC_Product_Attribute')) //in case of simple product with attributes assocaited with it
		{
			$available_options = $product_attributes->get_options();
			if(in_array($result[0]->id, $available_options))
				$product_attributes  = $result[0]->slug;
		}
		
		if($product_attributes && $result && $product_attributes  == $result[0]->slug)
			return true;
		return false;
	}
	public function get_attribute_name($attribute_id, $default = false)
	{
		global $wpdb, $wcqt_wpml_model;
		$taxonomy_slug =  $taxonomy_labels = array();
		
		foreach(wc_get_attribute_taxonomies() as $attribute_data)
			{
					$taxonomy_slug[] = "pa_".$attribute_data->attribute_name;
					$taxonomy_slug["pa_".$attribute_data->attribute_name] = $attribute_data->attribute_label;
			}
		$to_return = "N/A";
		$query_string = "SELECT product_attributes.term_id as id, product_attributes.name as attribute_name, tax.taxonomy as taxonomy
							 FROM {$wpdb->terms} AS product_attributes
							 LEFT JOIN {$wpdb->term_taxonomy} AS tax ON tax.term_id = product_attributes.term_id 							 						 	 
							 WHERE product_attributes.term_id  = {$attribute_id}
							";
			
		$query_string .=  " GROUP BY product_attributes.term_id ";
		$result = $wpdb->get_results($query_string ) ;
		
		if($result)
		{
			$to_return =  "[".$taxonomy_slug[$result[0]->taxonomy]."] ".$result[0]->attribute_name;
		}
		return $to_return;
	}
	public function get_product_category_name($category_id, $default = false)
	{
		global $wcqt_wpml_model;
		$category_id = $wcqt_wpml_model->get_main_language_id($category_id, 'product_cat');
		$category = get_term( $category_id, 'product_cat' );
		return isset($category) ? $category->name : $default;
	}
	public function get_product_name($product_id, $default = false)
	{
		global $wcqt_wpml_model;
		$product_id = $wcqt_wpml_model->get_main_language_id($product_id, 'product');
		$readable_name  = $default;
		
		if($this->is_variation($product_id))
		{
			$readable_name = $this->get_variation_complete_name($product_id);
			$readable_name = isset($readable_name) && $readable_name != "" && $readable_name!= " " ? "#".$product_id." - ".$readable_name  : $default;
		}
		else
		{
			try{
			    $product = wc_get_product($product_id);
			    $readable_name = isset($product) && is_object($product) ? $product->get_formatted_name() : $default;
		    }catch (Exception $e){}
		}
		return $readable_name; 
	}
	 public function ajax_get_products_partial_list()
	 {
		 $products = $this->get_product_list($_GET['product']);
		 echo json_encode( $products);
		 wp_die();
	 }
	  public function ajax_get_product_categories_partial_list()
	 {
		  $product_categories = $this->get_product_taxonomy_list('product_cat', $_GET['product_category']);
		 echo json_encode( $product_categories);
		 wp_die();
	 }
	 public function ajax_get_product_attributes_partial_list()
	 {
		  $product_categories = $this->get_product_attribute_list($_GET['product_attribute']);
		 echo json_encode( $product_categories);
		 wp_die();
	 }
	 
	 public function get_product_list($search_string = null)
	 {
		global $wpdb, $wcqt_wpml_model;
		 $query_string = "SELECT products.ID as id, products.post_parent as product_parent, products.post_title as product_name, product_meta.meta_value as product_sku
							 FROM {$wpdb->posts} AS products
							 LEFT JOIN {$wpdb->postmeta} AS product_meta ON product_meta.post_id = products.ID AND product_meta.meta_key = '_sku'
							 WHERE  (products.post_type = 'product' OR products.post_type = 'product_variation')
							";
		if($search_string)
				$query_string .=  " AND ( products.post_title LIKE '%{$search_string}%' OR product_meta.meta_value LIKE '%{$search_string}%' OR products.ID LIKE '%{$search_string}%' ) 
								   AND (products.post_type = 'product' OR products.post_type = 'product_variation') ";
		
		$query_string .=  " GROUP BY products.ID ";
		$result = $wpdb->get_results($query_string ) ;
		
		if(isset($result) && !empty($result))
			foreach($result as $index => $product)
				{
					if($product->product_parent != 0 )
					{
						$readable_name = $this->get_variation_complete_name($product->id);
						$result[$index]->product_name = $readable_name != false ? "<i>".esc_html__('Variation','woocommerce-files-upload')."</i> ".$readable_name : $result[$index]->product_name;
					}
				}
		
		
		//WPML
		if($wcqt_wpml_model->wpml_is_active())
		{
			$product_ids = $variation_ids = array();
			foreach($result as $product)
			{
				if($product->product_parent == 0 )
					$product_ids[] = $product;
				else
					$variation_ids[] = $product;
			}
			
			//Filter products
			if(!empty($product_ids))
				$product_ids = $wcqt_wpml_model->remove_translated_id($product_ids, 'product', true);
			
			//Filter variations
			if(!empty($variation_ids))
				$variation_ids = $wcqt_wpml_model->remove_translated_id($variation_ids, 'product', true);
			
			$result = array_merge($product_ids, $variation_ids);
		}
		
		return $result;
	 }
	 public function get_variation_complete_name($variation_id)
	 {
		$error = false;
		$variation = null;
		
		$variation = wc_get_product($variation_id);
			if($variation == null)
				return "";
			if($variation->is_type('simple'))
				return $variation->get_title();
		
		$product_name = $variation->get_title()." - ";	
		if($product_name == " - ")
			return false;
		$attributes_counter = 0;
		foreach($variation->get_variation_attributes( ) as $attribute_name => $value)
		{
			
			if($attributes_counter > 0)
				$product_name .= ", ";
			$meta_key = urldecode( str_replace( 'attribute_', '', $attribute_name ) ); 
			
			$product_name .= " ".wc_attribute_label($meta_key).": ".$value;
			$attributes_counter++;
		}
		return $product_name;
	 }
	 public function get_variation_attributes_names($variation_id)
	 {
		$variation = wc_get_product($variation_id);
		if($variation->is_type('simple'))
			return "";
		$attributes_counter = 0;
		
		$product_name = " - ";
		foreach($variation->get_variation_attributes( ) as $attribute_name => $value)
		{
			
			if($attributes_counter > 0)
				$product_name .= ", ";
			$meta_key = urldecode( str_replace( 'attribute_', '', $attribute_name ) ); 
			
			$value = is_array($value) ? implode(", " , $value) : $value; //This should NEVER happen
			$product_name .= " ".wc_attribute_label($meta_key, $variation).": ".$value;
			$attributes_counter++;
		}
		return $product_name;
	 }
	 public function get_variations($product_id)
	 {
		global $wpdb, $wcqt_wpml_model;
		
		if($wcqt_wpml_model->wpml_is_active())
			$product_id = $wcqt_wpml_model->get_main_language_id($product_id);
		 if(!isset($product_id))
			 return null; 
		 
		 $query = "SELECT *
		           FROM {$wpdb->posts} AS products 
				   WHERE  products.post_parent = {$product_id} "; 
		 $result =  $wpdb->get_results($query); 
		 return isset($result) ? $result : null;		 
	 }
	 public function is_variable($product_id)
	 {
		 if(!isset($product_id) || $product_id == 0)
			 return false;
		 
		 $variations = $this->get_variations($product_id ); //Check _product_attributes meta? or _min_variation_price?
		
		 return !isset( $variations ) || empty( $variations ) ? false : true;
	 }
	 public function is_variation($product_id)
	 {
		global $wpdb, $wcqt_wpml_model;
		if($wcqt_wpml_model->wpml_is_active())
			$product_id = $wcqt_wpml_model->get_main_language_id($product_id, 'product_variation');
		
		$product = wc_get_product($product_id);
			return $product == null || !$product->is_type('variation') ? false : true;
	 }
	 public function get_product_attribute_list($search_string = null)
	 {
		global $wpdb, $wcqt_wpml_model;
		$taxonomy_slug =  $taxonomy_labels = array();
		
		foreach(wc_get_attribute_taxonomies() as $attribute_data)
			 if(!$search_string || strpos(strtolower($attribute_data->attribute_label), strtolower($search_string)) !== false) 
				{
					$taxonomy_slug[] = "pa_".$attribute_data->attribute_name;
					$taxonomy_slug["pa_".$attribute_data->attribute_name] = $attribute_data->attribute_label;
				}

		  $query_string = "SELECT product_attributes.term_id as id, product_attributes.name as attribute_name, tax.taxonomy as taxonomy
							 FROM {$wpdb->terms} AS product_attributes
							 LEFT JOIN {$wpdb->term_taxonomy} AS tax ON tax.term_id = product_attributes.term_id 							 						 	 
							 WHERE tax.taxonomy IN ('".implode("','", $taxonomy_slug)."')
							";
			
		$query_string .=  " GROUP BY product_attributes.term_id ";
		$result = $wpdb->get_results($query_string ) ;
	
		//WPML
		if($wcqt_wpml_model->wpml_is_active())
		{
			$result = $wcqt_wpml_model->remove_attribute_translated_id($result, true);
		}   
		
		foreach($result as $key => $data)
				$result[$key]->attribute_name = "[".$taxonomy_slug[$data->taxonomy]."] ".$data->attribute_name;
		
		return $result;
	 }
	 public function get_product_taxonomy_list($taxonomy_name = 'product_cat', $search_string = null)
	 {
		 global $wpdb, $wcqt_wpml_model;
		 $query_string = "SELECT product_categories.term_id as id, product_categories.name as category_name
							 FROM {$wpdb->terms} AS product_categories
							 LEFT JOIN {$wpdb->term_taxonomy} AS tax ON tax.term_id = product_categories.term_id 							 						 	 
							 WHERE tax.taxonomy = '{$taxonomy_name}' 
							 AND product_categories.slug <> 'uncategorized' 
							";
		 if($search_string)
					$query_string .=  " AND ( product_categories.name LIKE '%{$search_string}%' )";
			
		$query_string .=  " GROUP BY product_categories.term_id ";
		$result = $wpdb->get_results($query_string ) ;
		//WPML
		if($wcqt_wpml_model->wpml_is_active())
		{
			$result = $wcqt_wpml_model->remove_translated_id($result, $taxonomy_name, true);
		} 
		
		return $result;
	 }
	
	private function get_complementry_ids($ids_to_exclude)
	{
		global $wpdb;
		$results = array();
		$query = "SELECT posts.ID 
				  FROM {$wpdb->posts} AS posts
				  WHERE posts.post_status IN({$this->get_selectable_post_statuses_query_string()}) 
				  AND (posts.post_type = 'product' || posts.post_type = 'product_variation')
				  AND posts.ID NOT IN('".implode("','",$ids_to_exclude)."') ";
		$ids = $wpdb->get_results($query, ARRAY_A);
		foreach($ids as $id)
			$results[] = $id['ID'];
		return $results;
	}
	public function get_selectable_post_statuses_query_string()
	{
		return "'publish','draft'";
	}
	
}
?>