<?php

if (!function_exists('array_column1')) {
	function array_column1($array,$column_name)
	{
	    return array_map(function($element) use($column_name){return $element[$column_name];}, $array);
	}
}

class ModelExtensionTotalPromotionTotal2 extends Model {
	private $grandTotal = 0;
	private $promotion_id = 0;
	private $user;

	private $conditionChecks = array();
	private $conditionProducts = array();
	private $actionProducts = array();

	public static $total = 0;
	public static $total_data = array();
	public static $ProductsIDS = array();

	//ModuleVariables
	private $modulePath;
	private $callModel;

	public function __construct($registry) {
		parent::__construct($registry);
		$this->config->load('isenselabs/promotion');

		$this->modulePath = $this->config->get('promotion_modulePath');
		$this->callModel = $this->config->get('promotion_callModel');

		$moduleSettings = $this->config->get('promotion');
		if(isset($moduleSettings['development_mode']) && $moduleSettings['development_mode'] == 'yes') {
			if(version_compare(VERSION, '2.2.0.0', '<')) {
				$this->load->library('user');
				$this->user = new User($registry);
			} else {
				$this->user = new Cart\User($registry);
			}
		}
	}

	private function getImageConfigs($name) {
		if(version_compare(VERSION, '2.2.0.0', '<')) {
			return $this->config->get($name);
		} else {
			if(strpos($name, 'config_image') !== false){
				$name = str_replace('config', '', $name);
				return $this->config->get($this->config->get('config_theme') . $name);
			}
		}	
	}

	public function getPromotionsFromProductID($product_id) {
		$data = $this->getPromotions();
		$promotions = array();
		$button = false;

		$modulePath = $this->config->get('promotion_modulePath');
		$this->load->model('tool/image');
		$this->load->model($this->config->get('promotion_modulePath'));

		$image_width = $this->getImageConfigs('config_image_related_width');
		$image_height = $this->getImageConfigs('config_image_related_height');

		foreach ($data as $promo) {
			$promo_data = array();
			$promo_data['module_id'] 	= $promo['module_id'];
			$promo_data['name'] 		= $promo['name'];

			if($promo['status'] == 'no' || !isset($promo['information_page']['status']) || $promo['information_page']['status'] == 'no') continue;

			if(!isset($promo['information_page']['link_promotion']) || $promo['information_page']['link_promotion'] == 'no') continue;

			if(isset($promo['information_page']['small_image_width'])) {
				$image_width = $promo['information_page']['small_image_width'];
			}

			if(isset($promo['information_page']['small_image_height'])) {
				$image_height = $promo['information_page']['small_image_height'];
			}

			if(!isset($promo['information_page']['button_link']) || $promo['information_page']['button_link'] == 'yes') {
				$button = true;
			}

			$promo_data['link']			= $this->url->link($modulePath.'/view', 'promotion_id='.$promo['module_id'], 'SSL');
			$promo_data['image'] 		= $this->model_tool_image->resize($promo['information_page']['image'] , $image_width, $image_height);

			$promo_data['description'] 	= $promo['information_page']['description'][$this->config->get('config_language')];


			foreach ($promo['conditions'] as $promo_cond) {
				switch ($promo_cond['condSelect']) {
					case 'product_name': 
						if($promo_cond['product_id'] == $product_id) {
							$promotions[] = $promo_data;
							break 2;
						} 
						break;
					case 'category_name': 
						$this->load->model('catalog/product');
						$this->load->model('catalog/category');
						$cats = $this->model_catalog_product->getCategories($product_id);
						$categories_ids = array();
						foreach ($cats as $key => $category) {
							$categories_ids[] = $category['category_id'];
							$parent_cats = $this->model_catalog_category->getCategories($category['category_id']);
							foreach ($parent_cats as $more_cats) {
								$categories_ids[] = $more_cats['category_id'];
							}		
						}
						if (in_array($promo_cond['category_id'], $categories_ids)) {
							$promotions[] = $promo_data;
							break 2;
						} 
						break;
					case 'manufac_name': 
						if( $this->{$this->callModel}->getManufacIDbyProdID($product_id) == $promo_cond['manufacturer_id']) {
							$promotions[] = $promo_data;
							break 2;
						} 
						break;
				}
			}
		}

		return array('promotions' => $promotions, 'button' => $button);
	}

	public function isCouponCodeValid($code) {
		$query = $this->db->query("SELECT module_id FROM " . DB_PREFIX . "module WHERE setting LIKE '%".$this->db->escape($code)."%'");
		if($query->num_rows > 0) {
			return true;
		}
		return false;
	}

	private function getPromotions(){
		$query = $this->db->query("SELECT setting,module_id FROM " . DB_PREFIX . "module WHERE code = 'promotion' ");

		$data = array();
		foreach ($query->rows as $key => $value) {

			if(version_compare(VERSION, '2.1.0.0', '<')) {
        		$data[$key] = unserialize($value['setting']);
        	} else {
        		$data[$key] = json_decode($value['setting'], true);
        	}

			$data[$key]['module_id'] = $value['module_id'];
		}
		
		usort($data, function($a, $b) {
			if ($a['general_settings']['sort_order'] == $b['general_settings']['sort_order']) {
	            return 0;
	        }
	        return ($a['general_settings']['sort_order'] > $b['general_settings']['sort_order']) ? +1 : -1;
		});

		usort($data, function($a, $b) {
			$var1 = ($a['general_settings']['stackable'] == 'no') ? 15000 :  $a['general_settings']['sort_order'];
			$var2 = ($b['general_settings']['stackable'] == 'no') ? 15000 :  $b['general_settings']['sort_order'];

			if ($var1 == $var2) {
				if ($a['general_settings']['sort_order'] == $b['general_settings']['sort_order']) {
	            	return 0;
	        	}
	        	return ($a['general_settings']['sort_order'] > $b['general_settings']['sort_order']) ? +1 : -1;
	        }

	        if($var1 == 15000 || $var2 == 15000) {
	        	return ($var1 < $var2) ? +1 : -1;
	        } else {
	        	return ($var1 > $var2) ? +1 : -1;
	        }

		});

		return $data;

	}

	private function getBasicPriorities($action){
		if($action == 'discount_products_from_conditions') return 1;
		elseif($action == 'discount_on_products') return 2;
		elseif ($action == 'discount_on_categories') return 3;
		elseif ($action == 'discount_cheapest') return 4;
		elseif ($action == 'discount_expensive') return 5;
		elseif ($action == 'order_discount_range') return 6;
		elseif ($action == 'order_discount') return 7;
		elseif ($action == 'free_shipping')	return 8;
		else return -1;
	}

	private function checkGeneralSetting($general_settings){

		//STARTDATE
		if(isset($general_settings['StartDate']) && !empty($general_settings['StartDate'])){
			if(strtotime($general_settings['StartDate']) > strtotime(date('Y-m-d'))){
				return false;
			}
		}
		//ENDDATE
		if(isset($general_settings['EndDate']) && !empty($general_settings['EndDate'])){
			if(strtotime($general_settings['EndDate']) < strtotime(date('Y-m-d'))){
				return false;
			}
		}

		//COUPON CODE
		if(isset($general_settings['PromotionType']) && $general_settings['PromotionType'] == 0){
			if(!isset($this->session->data['coupon_promotion_module'])) return false;
			if($this->session->data['coupon_promotion_module'] != $general_settings['CouponCode']) return false;
		}

		//TOTAL USES
		$this->load->model($this->modulePath);
		$uses = $this->{$this->callModel}->getTotalUses($this->promotion_id);
		if(isset($general_settings['TotalUses']) && $general_settings['TotalUses'] != 0){
			if($uses['total'] >= $general_settings['TotalUses']) return false;
			// TOTAL CUSTOMER USES
			if($this->getConditionValues('customer_name') != NULL && in_array($this->getConditionValues('customer_name'), $uses['customers'])){
				$count = array_count_values($uses['customers']);
				if($count[$this->getConditionValues('customer_name')] >= $general_settings['TotalUsesCustomer']) return false;
			}
		}

		//CUSTOMER GROUP
		if(!isset($general_settings['CustGroup'])) {
			$general_settings['CustGroup'] = array();
		}

		//NeedLOGIN
		if ($general_settings['need_login'] == 1) {
			if($this->getConditionValues('customer_group_id') == NULL) return false;
			if(!in_array($this->getConditionValues('customer_group_id'), $general_settings['CustGroup'])) return false;
		}

		//STORE
		if(isset($general_settings['Stores'])) {
			if(!in_array($this->config->get('config_store_id'), $general_settings['Stores'])) return false;
		}

		return true;
	}

	private function excludeProductFromActions($id, $quantity = 1){
		if(isset($this->conditionProducts[$id])) {
			$this->conditionProducts[$id] += $quantity;
		} else {
			$this->conditionProducts[$id] = $quantity;
		}
	}

	private function excludeProductsFromConditions($id, $quantity = 1) {
		if(isset($this->actionProducts[$id])) {
			$this->actionProducts[$id] += $quantity;
		} else {
			$this->actionProducts[$id] = $quantity;
		}
	}

	private function checkIfThePromotionCanBeAppliedAgain() {
		$used_products = array();
		foreach ($this->conditionProducts as $product_id => $quantity) {
			if(isset($used_products[$product_id])) {
				$used_products[$product_id] += $quantity;
			} else {
				$used_products[$product_id] = $quantity;
			}
		}

		foreach ($this->actionProducts as $product_id => $quantity) {
			if(isset($used_products[$product_id])) {
				$used_products[$product_id] += $quantity;
			} else {
				$used_products[$product_id] = $quantity;
			}
		}

		$count = array();
		foreach ($used_products as $product_id => $quantity) {
			$quantity_in_cart = $this->getProductInCartQuantity($product_id);
			$count[] = intval(($quantity_in_cart - $quantity) / $quantity);
		}

		return !empty($count) ? min($count) : 0;
	}

	public function getCategories($parent_id = 0) {
		$query = $this->db->query("SELECT c.category_id FROM " . DB_PREFIX . "category c LEFT JOIN " . DB_PREFIX . "category_description cd ON (c.category_id = cd.category_id) LEFT JOIN " . DB_PREFIX . "category_to_store c2s ON (c.category_id = c2s.category_id) WHERE c.parent_id = '" . (int)$parent_id . "' AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND c2s.store_id = '" . (int)$this->config->get('config_store_id') . "'  AND c.status = '1' ORDER BY c.sort_order, LCASE(cd.name)");

		$cats = array();
		foreach ($query->rows as $key => $value) {
			$cats[] = $value['category_id'];
		}

		return $cats;
	}
	public function getCategoryParent($category_id) {
		$query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id=".(int)$category_id);
		$cats = array();
		$last = 0;

		while($query->num_rows > 0) {
			$last = 0;
			foreach ($query->rows as $key => $value) {
				$cats[] = $value['parent_id'];
				$last = $value['parent_id'];
			}
			$query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id=".(int)$last);
		}
		return $cats;
	}



	private function checkConditions($conditions, $condition_rules){

		if(empty($conditions)){
			return true;
		}

		$this->conditionChecks = array();
		$condition_checks = array();

		foreach ($conditions as $key => $promo_cond) {
			
			switch ($promo_cond['condSelect']) {
				case 'product_name':
					if( $this->checkProductInCart($promo_cond['product_id'], $promo_cond['product_quantity']) ) {
						$condition_checks['product_name'.$key] = true;
						//Exclude product from action discounts
						$this->excludeProductFromActions($promo_cond['product_id'], $promo_cond['product_quantity']);
					} else {
						$condition_checks['product_name'.$key] = false;
					}
					break;
				case 'category_name':
					$categories = $this->getConditionValues($promo_cond['condSelect']);
					$count = 0;
					$this->load->model('catalog/category');

					$promo_cat_ids = array();
					$promo_cat_ids[] = $promo_cond['category_id'];

					//Child Categories
					if(isset($promo_cond['category_child']) && $promo_cond['category_child'] == 'yes') {
						$child_cats = $this->getCategories($promo_cond['category_id']);
						foreach ($child_cats as $category_id) {
							$promo_cat_ids[] = $category_id;
						}
					}

					//Parent Categories
					if(isset($promo_cond['category_parent']) && $promo_cond['category_parent'] == 'yes') {
						$parent_cats = $this->getCategoryParent($promo_cond['category_id']);
						foreach ($parent_cats as $category_id) {
							$promo_cat_ids[] = $category_id;
						}
					}

					$condition_checks['category_name'.$key] = false;
					foreach ($categories as $product_id => $cat_product) {
						$product_quantity = $this->getProductInCartQuantity($product_id);
						for ($i=1; $i <= $product_quantity ; $i++) { 
							if (count(array_intersect($cat_product,$promo_cat_ids)) > 0) {
								$count++; $this->excludeProductFromActions($product_id);
								if($count >= $promo_cond['category_quantity']){
									$condition_checks['category_name'.$key] = true;	

									if($promo_cond['category_quantity'] == 0){
										$this->excludeProductFromActions($product_id, $product_quantity - $i);
									} else {
										break;
									}
								}								
							}							
						}	
					}

					break;
				case 'manufac_name':
					$manufacturers = $this->getConditionValues($promo_cond['condSelect']);
					$condition_checks['manufac_name'.$key] = false;
					$count = 0;

					foreach ($manufacturers as $product_id => $manufacturer_id) {
						$product_quantity = $this->getProductInCartQuantity($product_id);

						for ($i=1; $i <= $product_quantity ; $i++) { 						
							if($promo_cond['manufacturer_id'] == $manufacturer_id){
								$count++;$this->excludeProductFromActions($product_id);

								if($count >= $promo_cond['manufacturer_quantity']){
									$condition_checks['manufac_name'.$key] = true;	
									if($promo_cond['manufacturer_quantity'] != 0){
										$this->excludeProductFromActions($product_id, $product_quantity - $i);
										break;
									}
								}
							}
						}	
					}
					break;
				case 'customer_name':
					$customer_now = $this->getConditionValues($promo_cond['condSelect']);
					if( $customer_now == $promo_cond['customer_id']){
						$condition_checks['customer_name'.$key] = true;
					}else {
						$condition_checks['customer_name'.$key] = false;
					}
					break;
				case 'day':
					$daynow = $this->getConditionValues($promo_cond['condSelect']);
					if ($promo_cond['dayofweek'] == strtolower(jddayofweek($daynow, 2)) ) {
						$condition_checks['day'.$key] = true;
					}else {
						$condition_checks['day'.$key] = false;
					}
					break;
				case 'customer_reg_date':
					$customer_reg_since = $this->getConditionValues($promo_cond['condSelect']);

					$isTrue = false;
					if($customer_reg_since) {
						$isTrue = strtotime($customer_reg_since) - strtotime($promo_cond['customer_date']);
					}
	
					if ($isTrue > 0) {
						$condition_checks['customer_reg_date'.$key] = true;
					} else {
						$condition_checks['customer_reg_date'.$key] = false;
					}
					break;
				case 'customer_order':
					$val = $this->getConditionValues($promo_cond['condSelect']);
					$condition_input = $promo_cond['condition_input'];
					$condEquals = $promo_cond['condEquals'];

					if($condEquals == 'eq'){
						if($val == $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					} else if($condEquals == 'neq'){
						if($val != $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					} else if($condEquals == 'gtr'){
						if($val > $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					} else if($condEquals == 'lth'){
						if($val < $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					}else {
						$condition_checks[$promo_cond['condSelect'].$key] = false;
					}
					break;
				default:
					$val = $this->getConditionValues($promo_cond['condSelect']);
					$condEquals = $promo_cond['condEquals'];
					$condition_input = $promo_cond['condition_input'];
					if($condEquals == 'eq'){
						if($val == $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					} else if($condEquals == 'neq'){
						if($val != $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					} else if($condEquals == 'gtr'){
						if($val > $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					} else if($condEquals == 'lth'){
						if($val < $condition_input) $condition_checks[$promo_cond['condSelect'].$key] = true;
						else $condition_checks[$promo_cond['condSelect'].$key] = false;
					}else {
						$condition_checks[$promo_cond['condSelect'].$key] = false;
					}
					break;
			}
		}

		$this->conditionChecks = $condition_checks;

		if($condition_rules['condition_bool'] == 'False') {
			if($condition_rules['condition_combine'] == 'All'){
				if(!in_array(true, $condition_checks)){
					return true;
				}
			} else {
				if(in_array(false, $condition_checks)){
					return true;
				}
			}
		} else {
			if($condition_rules['condition_combine'] == 'All'){
				if(!in_array(false, $condition_checks)){
					return true;
				}
			} else {
				if(in_array(true, $condition_checks)){
					return true;
				}
			}
		}

		return false;

	}

	private function getConditionValues($field) { // TOTAL, QUANTITY, ..etc
		switch ($field) {
			case 'cart_total':
				return $this->cart->getTotal() - $this->grandTotal;

				break;
			case 'cart_total_no_changes':
				return $this->cart->getTotal();

				break;			
			case 'cart_quantity':
				return $this->cart->countProducts();

				break;
			case 'cart_weight':
				return $this->cart->getWeight();

				break;
			case 'customer_group_id':
				return $this->customer->getGroupId();

				break;
			case 'customer_name':
				return $this->customer->getId();

				break;
			case 'customer_reg_date':
				$this->load->model('account/customer');
				$customer_data = $this->model_account_customer->getCustomer($this->customer->getId());

				if(empty($customer_data)) return false;
				else return $customer_data['date_added'];
				
				break;
			case 'customer_order':

				if($this->customer->getId() == 0) return 0;

				$this->load->model('account/order');
				return $this->model_account_order->getTotalOrders();
				break;
			case 'get_cheapest_product':
					$cartProducts = $this->cart->getProducts();

					usort($cartProducts, function($a, $b) {
					    return $a['price'] - $b['price'];
					});
					$product = reset($cartProducts);
					return $product['product_id'];
				break;
			case 'get_expensive_product':
					$cartProducts = $this->cart->getProducts();

					usort($cartProducts, function($a, $b) {
					    return $b['price'] - $a['price'];
					});

					$product = reset($cartProducts);
					return $product['product_id'];
				break;
			case 'manufac_name':
				$this->load->model($this->modulePath);
				$products = $this->cart->getProducts();
				$ids = array();
				foreach ($products as $key => $product) {
					$ids[$product['product_id']] = $this->{$this->callModel}->getManufacIDbyProdID($product['product_id']);
				}
				return $ids;
				break;
			case 'category_name':
				$this->load->model('catalog/product');
				$products = $this->cart->getProducts();
				$ids = array();
				foreach ($products as $key => $product) {
					$cats = $this->model_catalog_product->getCategories($product['product_id']);
					foreach ($cats as $category) {
						$ids[$product['product_id']][] = $category['category_id'];
					}
				}
				return $ids;
				break;
			case 'day':
				return date('w') - 1;
				break;
			default:
				return 'error (no such condition )';
				break;
		}
	}

	private function checkProductInCart($id, $quantity = 1){
		$cartProducts = $this->cart->getProducts();
		$id = array_search($id , array_column1($cartProducts, 'product_id'));
		if($id === false ) return false;
		$product = $cartProducts[$id];
		if($product['quantity'] < $quantity) return false;
		return true;
	}

	private function getProductInCart($id){
		if($this->checkProductInCart($id)){
			$cartProducts = $this->cart->getProducts();
			$product = $cartProducts[array_search($id , array_column1($cartProducts, 'product_id'))];
			return $product;
		} 
		return false;
	}

	private function getProductInCartPrice($id){
		$product = $this->getProductInCart($id);
		if($product){
			   return $this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'));
		} else return false;
	}

	private function getProductInCartQuantity($id){
		$product = $this->getProductInCart($id);
		if($product){
			   return $product['quantity'];
		} else return false;
	}

	private function checkIfFreeProductForDiscount($id){
		if(!$this->checkProductInCart($id)) return false;

		if(array_key_exists($id, $this->conditionProducts)){
			$quantity = $this->conditionProducts[$id];
			if($quantity < $this->getProductInCartQuantity($id)) return $this->getProductInCartQuantity($id) - $quantity;
			else return false;
		}
		 return $this->getProductInCartQuantity($id);
	}

	private function applyActions($actions, &$total){
		if(empty($actions)){
			return;
		}

		switch ($actions[1]['mainSelect']) {
			case 'order_discount':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];

				if( $disc_type == 'percentage') {
					$total += $amount*$this->getConditionValues('cart_total')/100;
				} elseif ( $disc_type == 'fixed_price') {
					$total += $this->getConditionValues('cart_total') - $amount;
				} else {
					$total += $amount; 
				}
				break;
			case 'free_shipping':
					if(isset($this->session->data['shipping_method'])){
								$total += $this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $this->config->get('config_tax'));
								
						}
				break;
			case 'discount_cheapest':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];
				$product_id = $this->getConditionValues('get_cheapest_product');
				$this->excludeProductsFromConditions($product_id);
				if( $disc_type == 'percentage') {
					$total += $amount*$this->getProductInCartPrice($product_id)/100;
				} elseif ( $disc_type == 'fixed_price') {
					$total += $this->getProductInCartPrice($product_id) - $amount;
				} else {
					$total += $amount; 
				}
				break;
			case 'discount_expensive':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];
				$product_id = $this->getConditionValues('get_expensive_product');
				$this->excludeProductsFromConditions($product_id);
				if( $disc_type == 'percentage') {
					$total += $amount*$this->getProductInCartPrice($product_id)/100;
				} elseif ( $disc_type == 'fixed_price') {
					$total += $this->getProductInCartPrice($product_id) - $amount;
				} else {
					$total += $amount; 
				}
				break;
			case 'discount_on_products':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];
				$products = $actions[1]['product'];
				foreach ($products as $product_id) {
					$this->excludeProductsFromConditions($product_id);
					if($this->checkProductInCart($product_id) && $this->checkIfFreeProductForDiscount($product_id)){
						$price = $this->getProductInCartPrice($product_id);
 						if( $disc_type == 'percentage') {
 							$total += $amount*$price/100;
						} elseif ( $disc_type == 'fixed_price') {
							$total += $price - $amount;
						} else {
							$total += $amount; 
						}
					}
				}
				break;
			case 'discount_all_products':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];
				$cartProducts = $this->cart->getProducts();

				$exclude_products = array(); $exclude_category = array();
				if(isset($actions[1]['exclude_product'])) {
					$exclude_products = $actions[1]['exclude_product'];
				}
				if(isset($actions[1]['exclude_category'])) {
					$exclude_category = $actions[1]['exclude_category'];
				}
				
				$this->load->model('catalog/product');

				foreach ($cartProducts as $key => $cart_product) {

					
					$product_id = $cart_product['product_id'];
					$categories_product = $this->model_catalog_product->getCategories($product_id);

					if(in_array($product_id, $exclude_products)) continue;

					foreach ($categories_product as $cats) {
						if(in_array($cats['category_id'], $exclude_category)) continue;
					}

					$product_price = $this->tax->calculate($cart_product['price'], $cart_product['tax_class_id'], $this->config->get('config_tax'));
					if( $disc_type == 'percentage') {
						$total += $amount*$product_price * $cart_product['quantity']/100;
					} elseif ( $disc_type == 'fixed_price') {
						$total += ($product_price - $amount) * $cart_product['quantity'];
					} else {
						$total += $amount * $cart_product['quantity'];
					}
				}

				break;
			/*
			case 'add_product_cart':	
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];
				$products_to_cart = $actions[1]['product'];


				foreach ($products_to_cart as $product_id) {
					if(!$this->checkProductInCart($product_id)) {
						$this->cart->add($product_id);
					} else {				
						$product_price = $this->getProductInCartPrice($product_id);

						if( $disc_type == 'percentage') {
							$total += $amount*$product_price / 100;
						} elseif ( $disc_type == 'fixed_price') {
							$total += $product_price - $amount;
						} else {
							$total += $amount;
						}
					}
				}
				break;
			*/
			case 'discount_products_from_conditions':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];

				foreach ($this->conditionProducts as $product_id => $quantity) {
					if( $disc_type == 'percentage') {
						$total += $amount*$this->getProductInCartPrice($product_id) * $quantity/100;
					} elseif ( $disc_type == 'fixed_price') {
						$total += ($this->getProductInCartPrice($product_id) - $amount) * $quantity;
					} else {
						$total += $amount * $quantity;
					}
				}
				break;			
			case 'discount_on_categories':
				$disc_type  = $actions[1]['disc_type'];
				$amount = $actions[1]['amount'];
				$quantity = isset($actions[1]['max_quantity_category']) ? $actions[1]['max_quantity_category'] : 99999;
				$count = 0;
				$categories = $actions[1]['category'];
				$products = $this->getConditionValues('category_name');


				$exclude_products = array();
				if(isset($actions[1]['exclude_product_from_cat'])) {
					$exclude_products = $actions[1]['exclude_product_from_cat'];
				}


				foreach ($categories as $desired_cat_id) {
					foreach ($products as $product_id => $category_id) {

						if(in_array($product_id, $exclude_products)) continue;

						if(array_search($desired_cat_id, $category_id) !== false){
							for ($i=0; $i < $this->checkIfFreeProductForDiscount($product_id)  ; $i++) { 

								if($i > $quantity - 1) break 3;
								if($count >= $quantity) break 3;
								$count++;

								$this->excludeProductsFromConditions($product_id);

								if( $disc_type == 'percentage') {
									$total += $amount*$this->getProductInCartPrice($product_id)/100;
								} elseif ( $disc_type == 'fixed_price') {
									$total += $this->getProductInCartPrice($product_id) - $amount;
								} else {
									$total += $amount; 
								}
							}
						}
					}
				}

				break;			
			case 'order_discount_range':
				usort($actions[1]['ranges'], function($a, $b) {
				    return $b['total'] - $a['total'];
				});

				foreach ($actions[1]['ranges'] as $range) {
					$disc_type  = $range['type'];
					$amount = $range['amount'];
					$total_to_reach = $range['total'];

					if($total_to_reach > $this->getConditionValues('cart_total')) continue;

					if( $disc_type == 'percentage') {
						$total += $amount*$this->getConditionValues('cart_total')/100;
						break;
					} else {
						$total += $amount; 
						break;
					}	
				}
				break;		
			default:
				# code...
				break;
		}

	}

	public function getTotal($totals) {

				$total = &$totals['total'];
				$taxes = &$totals['taxes'];
				$total_data = &$totals['totals'];

				//Admin check
				$moduleSettings = $this->config->get('promotion');
				if(isset($moduleSettings['development_mode']) && $moduleSettings['development_mode'] == 'yes') {
					if(!$this->user->isLogged()) return;
				}

				if (empty(self::$total)) {

					$promotions = $this->getPromotions();

					unset($this->session->data['promotions']);

					foreach ($promotions as $key => $value) { $key+=1;

						$status = $value['status'];

						$this->promotion_id = $value['module_id'];

						//If promotion is disabled it will skip
						if($status == 'no') continue;
						

						//Settings, conditions and actions
						$general_settings = $value['general_settings'];
						$conditions = $value['conditions'];
						$condition_rules = $value['condition_rules'];
						$actions = $value['actions'];
						$total_promotion = 0;
						$this->conditionProducts = array();
						$this->actionProducts = array();

						//First we check general settings if they fail we skip everything
						$checkGeneralSetting = $this->checkGeneralSetting($general_settings);
						if($checkGeneralSetting) {
							// Then we check conditions
							$isContitionsTrue = $this->checkConditions($conditions, $condition_rules);
							if($isContitionsTrue) {
								$this->applyActions($actions, $total_promotion);
							} 
						}

						if(isset($general_settings['multiply']) && $actions[1]['mainSelect'] != 'free_shipping' && $actions[1]['mainSelect'] != 'discount_expensive' && $actions[1]['mainSelect'] != 'discount_cheapest') {
							if($general_settings['multiply'] == 'yes') {
								$count = $this->checkIfThePromotionCanBeAppliedAgain();
								if($count) $total_promotion *= $count + 1;
							}	
						}	

						//If no change in price we do not show the promotion total.
						if($total_promotion > 0){

							self::$total_data[] = array(
							'code'       => 'promotion_total',
							'title'      => 'Promotions: ' . $value['name'],
							'value'      => -$total_promotion,
							'sort_order' => $this->config->get('promotion_total2_sort_order') + (1 - 1/$key)
							);

							$this->session->data['promotions'][] = $value['module_id'];
							
							$this->grandTotal += $total_promotion;

							if($general_settings['stackable'] == 'no') break;
						} 

							self::$ProductsIDS = array_merge(self::$ProductsIDS,array_keys($this->conditionProducts));
							
					}
					self::$total = (float)$this->grandTotal;
			    }
				
				$total_data = array_merge($total_data, self::$total_data);
				$total -= self::$total;
				
				if ($total < 0) {
					//$total = 0; 
				}
	}

}