<?php
/**
* ---------------------------------------------------------------------------------
*
* This file is part of the 'giftonordermodule' module feature (main || related module)
* Developped for Prestashop platform.
* You are not allowed to use it on several site
* You are not allowed to redistribute this module
* This header must not be removed
*
* @category  giftonordermodule
* @author    OleaCorner <contact@oleacorner.com> <www.oleacorner.com>
* @copyright OleaCorner
* @version   4.3
* @license   XXX
*
* ---------------------------------------------------------------------------------
*/

define ('_GIFTONORDER_TYPE_SYSTEMATIC_', 0);
define ('_GIFTONORDER_TYPE_FIRSTORDER_', 1);
define ('_GIFTONORDER_TYPE_NEXTORDER_', 2);

define ('_GIFTONORDER_VOUCHERS_ALL_', 0);
define ('_GIFTONORDER_VOUCHERS_CUMULATIVE_', 1);
define ('_GIFTONORDER_VOUCHERS_NONE_', 2);

class Giftonorder extends ObjectModel
{

	public $id;

	public $name;

	public $description;

	public $gift_id_product;

	public $gift_id_product_list;

	public $gift_id_combination;

	public $allow_other_gift;

	public $fo_display = 1;

	public $gift_discount_multiple;

	public $criteria_type;

	public $criteria_cart_amount = 0.0;

	public $criteria_category_amount = 0.0;

	public $criteria_different_products = 1;

	public $criteria_nb_products = 1;

	public $criteria_qty_multiple = 0;

	public $criteria_categories;

	public $criteria_attributes;

	public $criteria_attributes_detectsall;

	public $criteria_discounts;

	public $criteria_suppliers = 'any';

	public $criteria_manufacturers = 'any';

	public $criteria_max_per_customer = 0;

	public $criteria_cumulative_with_voucher_type = _GIFTONORDER_VOUCHERS_ALL_;

	public $criteria_cumulable_reduced_products = true;

	public $criteria_date_from;

	public $criteria_date_to;

	public $active = true;

	public $position;

	public $message_fo;

	public $gift_selector_message;

	public $gift_preselector_product_page = 0;

	public $date_add;

	public $date_upd;

	public $missing_amount = 0;

	public $missing_otherproducts = false;

	public static $definition = array(
		'table' => 'giftonorder',
		'primary' => 'id_giftonorder',
		'multilang' => true,
		'fields' => array(
			'gift_id_product' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'gift_id_combination' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'allow_other_gift' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'fo_display' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'gift_discount_multiple' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'criteria_type' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'criteria_cart_amount' => array(
				'type' => self::TYPE_FLOAT,
				'validate' => 'isFloat'
			),
			'criteria_category_amount' => array(
				'type' => self::TYPE_FLOAT,
				'validate' => 'isFloat'
			),
			'criteria_nb_products' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'criteria_different_products' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'criteria_qty_multiple' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'criteria_categories' => array(
				'type' => self::TYPE_STRING,
				'validate' => 'isString'
			),
			'criteria_suppliers' => array(
				'type' => self::TYPE_STRING,
				'validate' => 'isString'
			),
			'criteria_manufacturers' => array(
				'type' => self::TYPE_STRING,
				'validate' => 'isString'
			),
			'criteria_attributes' => array(
				'type' => self::TYPE_STRING,
				'validate' => 'isString'
			),
			'criteria_attributes_detectsall' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'criteria_max_per_customer' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'criteria_date_from' => array(
				'type' => self::TYPE_DATE,
				'validate' => 'isDate'
			),
			'criteria_date_to' => array(
				'type' => self::TYPE_DATE,
				'validate' => 'isDate'
			),
			'active' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'position' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'gift_id_product_list' => array(
				'type' => self::TYPE_HTML,
				'validate' => 'isAnything'
			),
			'criteria_discounts' => array(
				'type' => self::TYPE_STRING,
				'validate' => 'isString'
			),
			'criteria_cumulative_with_voucher_type' => array(
				'type' => self::TYPE_INT,
				'validate' => 'isUnsignedInt'
			),
			'criteria_cumulable_reduced_products' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),
			'gift_preselector_product_page' => array(
				'type' => self::TYPE_BOOL,
				'validate' => 'isBool'
			),

			'name' => array(
				'type' => self::TYPE_STRING,
				'lang' => true,
				'validate' => 'isGenericName',
				'required' => true,
				'size' => 64
			),
			'description' => array(
				'type' => self::TYPE_HTML,
				'lang' => true,
				'validate' => 'isCleanHtml',
				'size' => 256
			),
			'message_fo' => array(
				'type' => self::TYPE_HTML,
				'lang' => true,
				'validate' => 'isCleanHtml',
				'size' => 1024
			),
			'gift_selector_message' => array(
				'type' => self::TYPE_HTML,
				'lang' => true,
				'validate' => 'isCleanHtml',
				'size' => 128
			),

			'date_add' => array(
				'type' => self::TYPE_DATE,
				'validate' => 'isDate'
			),
			'date_upd' => array(
				'type' => self::TYPE_DATE,
				'validate' => 'isDate'
			)
		)

	);

	/*
	 * protected	$fieldsRequiredLang = array('name');
	 * protected	$fieldsSizeLang = array('name' => 64,
	 * 'description' => 256,
	 * 'message_fo' => 1024,
	 * 'gift_selector_message'=>128);
	 * protected	$fieldsValidateLang = array('name' => 'isGenericName',
	 * 'description' => 'isCleanHtml',
	 * 'message_fo' => 'isCleanHtml',
	 * 'gift_selector_message' => 'isCleanHtml');
	 *
	 * protected 	$table = 'giftonorder';
	 * protected 	$tables = array ('giftonorder');
	 * protected 	$identifier = 'id_giftonorder';
	 */

	/*
	 * public function getFields()
	 * {
	 * parent::validateFields();
	 * if (isset($this->id))
	 * $fields['id_giftonorder'] = (int)($this->id);
	 * $fields['gift_id_product'] = (int)($this->gift_id_product);
	 * $fields['gift_id_combination'] = (int)($this->gift_id_combination);
	 * $fields['allow_other_gift'] = ((int)($this->allow_other_gift) ?1 :0);
	 * $fields['fo_display'] = ((int)($this->fo_display) ?1 :0);
	 * $fields['gift_discount_multiple'] = ((int)($this->gift_discount_multiple) ?1 :0);
	 * $fields['criteria_type'] = (int)($this->criteria_type);
	 * $fields['criteria_cart_amount'] = (float)($this->criteria_cart_amount);
	 * $fields['criteria_category_amount'] = (float)($this->criteria_category_amount);
	 * $fields['criteria_nb_products'] = (int)($this->criteria_nb_products);
	 * $fields['criteria_different_products'] = (int)($this->criteria_different_products);
	 * $fields['criteria_qty_multiple'] = (int)($this->criteria_qty_multiple);
	 * $fields['criteria_categories'] = pSQL($this->criteria_categories);
	 * $fields['criteria_suppliers'] = pSQL($this->criteria_suppliers);
	 * $fields['criteria_manufacturers'] = pSQL($this->criteria_manufacturers);
	 * $fields['criteria_attributes'] = pSQL($this->criteria_attributes);
	 * $fields['criteria_attributes_detectsall'] = (int)($this->criteria_attributes_detectsall);
	 * $fields['criteria_max_per_customer'] = (int)($this->criteria_max_per_customer);
	 * $fields['criteria_date_from'] = pSQL($this->criteria_date_from);
	 * $fields['criteria_discounts'] = pSQL($this->criteria_discounts);
	 * $fields['criteria_date_to'] = pSQL($this->criteria_date_to);
	 * $fields['active'] = (int)($this->active);
	 * $fields['position'] = (int)($this->position);
	 * $fields['date_add'] = pSQL($this->date_add);
	 * $fields['date_upd'] = pSQL($this->date_upd);
	 * $fields['gift_id_product_list'] = pSQL($this->gift_id_product_list);
	 * $fields['criteria_cumulative_with_voucher_type'] = (int)($this->criteria_cumulative_with_voucher_type);
	 * $fields['criteria_cumulable_reduced_products'] = (int)($this->criteria_cumulable_reduced_products);
	 * $fields['gift_preselector_product_page'] = (int)$this->gift_preselector_product_page;
	 * return $fields;
	 * }
	 */

	public function __construct($id = null, $id_lang = null, $id_shop = null)
	{
		parent::__construct($id, $id_lang, $id_shop);
		self::oleaAddObjectTableAssociation ('giftonorder');
	}

	public function getTranslationsFieldsChildNOTUSED()
	{
		self::validateFieldsLang ();

		$fieldsArray = array(
			'name',
			'description'
		);
		$fields = array();
		$languages = Language::getLanguages ();
		$defaultLanguage = Configuration::get ('PS_LANG_DEFAULT');
		foreach ($languages as $language)
		{
			$fields[$language['id_lang']]['id_lang'] = $language['id_lang'];
			$fields[$language['id_lang']][$this->identifier] = (int)($this->id);
			if (version_compare (_PS_VERSION_, '1.2', '>='))
			{
				$fields[$language['id_lang']]['message_fo'] = (isset ($this->message_fo[$language['id_lang']])) ? Tools::htmlentitiesDecodeUTF8 (pSQL ($this->message_fo[$language['id_lang']], true)) : '';
				$fields[$language['id_lang']]['gift_selector_message'] = (isset ($this->message_fo[$language['id_lang']])) ? Tools::htmlentitiesDecodeUTF8 (pSQL ($this->gift_selector_message[$language['id_lang']], true)) : '';
			}
			else
			{
				$fields[$language['id_lang']]['message_fo'] = (isset ($this->message_fo[$language['id_lang']])) ? pSQL ($this->message_fo[$language['id_lang']], true) : '';
				$fields[$language['id_lang']]['gift_selector_message'] = (isset ($this->message_fo[$language['id_lang']])) ? pSQL ($this->gift_selector_message[$language['id_lang']], true) : '';
			}
			foreach ($fieldsArray as $field)
			{
				if (!Validate::isTableOrIdentifier ($field))
					die (Tools::displayError ());

					/* Check fields validity */
				if (isset ($this->{$field}[$language['id_lang']]) && !empty ($this->{$field}[$language['id_lang']]))
					$fields[$language['id_lang']][$field] = pSQL ($this->{$field}[$language['id_lang']]);
				elseif (in_array ($field, $this->fieldsRequiredLang))
					$fields[$language['id_lang']][$field] = pSQL ($this->{$field}[$defaultLanguage]);
				else
					$fields[$language['id_lang']][$field] = '';
			}
		}
		return $fields;
	}

	public function updatePosition($way, $position = null)
	{
		if (!$res = Db::getInstance ()->ExecuteS ('
		SELECT g.`id_giftonorder`, g.`position`
		FROM `'._DB_PREFIX_.'giftonorder` g
		WHERE 1
		ORDER BY g.`position` '.((int)($way) ? 'ASC' : 'DESC')))
			return false;
		foreach ($res as $key => $values)
			if ((int)($values[$this->identifier]) == (int)($this->id))
			{
				$k = $key;
				break;
			}
		if (!isset ($k) || !isset ($res[$k]) || !isset ($res[$k + 1]))
			return false;
		$from = $res[$k];
		$to = $res[$k + 1];

		if (isset ($position))
			$to['position'] = (int)($position);

		return (Db::getInstance ()->Execute ('
		UPDATE `'._DB_PREFIX_.'giftonorder`
		SET `position`= position '.($way ? '-1' : '+1').'
		WHERE position between '.min (array(
			$from['position'],
			$to['position']
		)).'
		AND '.max (array(
			$from['position'],
			$to['position']
		))) && Db::getInstance ()->Execute ('
		UPDATE `'._DB_PREFIX_.'giftonorder`
		SET `position`='.(int)($to['position']).'
		WHERE `'.pSQL ($this->identifier).'` = '.(int)($from[$this->identifier])));
	}

	/**
	 * ********************************************************************
	 */
	public static function getAllGiftonorder($id_lang)
	{
		self::oleaAddObjectTableAssociation ('giftonorder');

		return Db::getInstance ()->ExecuteS ('
		SELECT g.*, gl.*
		FROM `'._DB_PREFIX_.'giftonorder` g
		'.Shop::addSqlAssociation ('giftonorder', 'g').'
		LEFT JOIN `'._DB_PREFIX_.'giftonorder_lang` AS gl ON (g.`id_giftonorder` = gl.`id_giftonorder` AND gl.`id_lang` = '.(int)($id_lang).')
		ORDER BY g.`id_giftonorder` ASC');
	}

	public static function getAllGiftProducts($id_lang)
	{
		self::oleaAddObjectTableAssociation ('giftonorder');

		return Db::getInstance ()->ExecuteS ('
			SELECT p.`id_product`, pl.`name`
			FROM `'._DB_PREFIX_.'product` p
			RIGHT JOIN `'._DB_PREFIX_.'category_product` cp ON (p.`id_product` = cp.`id_product` AND cp.`id_category` = '.(int)(Configuration::get ('OLEA_GIFTONORDER_GIFT_CATEGORY')).' )
			LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product`)
			WHERE pl.`id_lang` = '.(int)($id_lang).'
			ORDER BY pl.`name`');
	}

	public static function getPotentialGift($id_customer = 0, $id_lang = 0, $fo_display_only = false)
	{
		static $_cache = array();

		if ((int)($id_lang) == 0)
			$id_lang = Configuration::get ('PS_LANG_DEFAULT');

		$thedate = date ('Y-m-d');

		$cacheId = $id_customer.'-'.$id_lang.'-'.$fo_display_only;
		if (array_key_exists ($cacheId, $_cache))
			return $_cache[$cacheId];

		$join_group = '';
		$where_group = '';
		$where_fo = '';
		if ((boolean)$fo_display_only)
			$where_fo = ' AND g.fo_display = 1 ';

		$where_suppliers = ' AND (g.criteria_supplier LIKE "ANY" || ) ';

		self::oleaAddObjectTableAssociation ('giftonorder');

		if ($id_customer == 0)
		{
			if (version_compare (_PS_VERSION_, '1.2', '>='))
			{
				$join_group = '	LEFT JOIN '._DB_PREFIX_.'giftonorder_group gg on (gg.`id_giftonorder` = g.`id_giftonorder`)';
				$where_group = ' AND (gg.`id_group` = 1)';
			}
			$sqlReq = '
				SELECT DISTINCT g.*, 0 as nb_for_customer, gl.*, i.`cover`, i.`id_image`, il.`legend`, pl.`link_rewrite`
				FROM `'._DB_PREFIX_.'giftonorder` g
				'.$join_group.'
				'.Shop::addSqlAssociation ('giftonorder', 'g').'
				LEFT JOIN `'._DB_PREFIX_.'giftonorder_lang` AS gl ON (gl.`id_giftonorder` = g.`id_giftonorder` AND gl.`id_lang` = '.(int)($id_lang).')
				LEFT JOIN `'._DB_PREFIX_.'image` as i ON (i.`id_product` = g.`gift_id_product` AND i.cover=1)
				LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)($id_lang).')
				LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pl.`id_product` = g.`gift_id_product` AND pl.`id_lang` = '.(int)($id_lang).')
				'.Shop::addSqlRestrictionOnLang('pl').'
				WHERE (g.active = 1) AND ("'.$thedate.'" BETWEEN g.`criteria_date_from` AND g.`criteria_date_to`)
									'.$where_group.$where_fo.'
				ORDER BY g.`position` ASC';
		}
		else
		{
			if (version_compare (_PS_VERSION_, '1.2', '>='))
			{
				$join_group = ' LEFT JOIN '._DB_PREFIX_.'giftonorder_group gg on (gg.`id_giftonorder` = g.`id_giftonorder`)
								INNER JOIN '._DB_PREFIX_.'customer_group cg on (cg.`id_customer` = '.(int)($id_customer).')';
				$where_group = ' AND (cg.id_group = gg.id_group)';
			}
			$sqlReq = '
				SELECT DISTINCT g.*, gl.*, i.`cover`, i.`id_image`, il.`legend`, pl.`link_rewrite`
				FROM `'._DB_PREFIX_.'giftonorder` g
				'.Shop::addSqlAssociation ('giftonorder', 'g').'
				LEFT JOIN `'._DB_PREFIX_.'giftonorder_lang` AS gl ON (gl.`id_giftonorder` = g.`id_giftonorder` AND gl.`id_lang` = '.(int)($id_lang).')
				LEFT JOIN `'._DB_PREFIX_.'image` as i ON (i.`id_product` = g.`gift_id_product` AND i.cover=1)
				LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)($id_lang).')
				LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pl.`id_product` = g.`gift_id_product` AND pl.`id_lang` = '.(int)($id_lang).')
				'.$join_group.'
				'.Shop::addSqlRestrictionOnLang('pl').'
				WHERE (g.active = 1) AND ("'.$thedate.'" BETWEEN g.`criteria_date_from` AND g.`criteria_date_to`)
					'.$where_group.$where_fo.'
				ORDER BY g.`position` ASC';
		}
		$res = Db::getInstance ()->ExecuteS ($sqlReq);
		// error_log(print_r(array('sqlReq'=>$sqlReq, 'res'=>$res), true));
		// DEBUT DEBUG
		foreach ($res as &$r)
			if (isset ($r['gift_id_product_list']))
				$r['gift_id_product_list_exploded'] = explode (',', $r['gift_id_product_list']);
			else
				$r['gift_id_product_list_exploded'] = 'NOT FOUND';
			// FIN DEBUG

		if (is_array ($res) && count ($res))
		{
			$gift_quantities = array();
			$sqlReq = 'SELECT p.id_product, i.id_image, p.quantity, g.id_giftonorder, p.out_of_stock
						FROM '._DB_PREFIX_.'giftonorder g
						'.Shop::addSqlAssociation ('giftonorder', 'g').'
						LEFT JOIN  '._DB_PREFIX_.'product p ON (p.active = 1 AND FIND_IN_SET(p.id_product, g.gift_id_product_list)>0)
						LEFT JOIN `'._DB_PREFIX_.'image` as i ON (i.`id_product` = p.`id_product`)
					';
			$resQty = Db::getInstance ()->ExecuteS ($sqlReq);
			if (is_array ($resQty) && count ($resQty))
			{
				foreach ($resQty as $qtyInfo)

					// Tools::p(array('isAvailOOS'=>$qtyInfo['out_of_stock'], 'qtyInfo'=>$qtyInfo));
					// if ($qtyInfo['quantity'] > 0 || Product::isAvailableWhenOutOfStock($qtyInfo['out_of_stock']))
					$gift_quantities[$qtyInfo['id_giftonorder']][$qtyInfo['id_product']] = array(
						'qty' => $qtyInfo['quantity'],
						'id_image' => $qtyInfo['id_image']
					);
			}

			$resUpdated = array();
			foreach ($res as $gift)
			{
				if (array_key_exists ($gift['id_giftonorder'], $gift_quantities))
				{
					$gift['gift_id_product_list'] = implode (',', array_keys ($gift_quantities[$gift['id_giftonorder']]));
					if (!array_key_exists ($gift['gift_id_product'], $gift_quantities[$gift['id_giftonorder']]))
					{
						$gift['gift_id_product'] = (int)($gift['gift_id_product_list']); // cast that reads only the first || 0 if empty
						$gift['id_image'] = $gift_quantities[$gift['id_giftonorder']][$gift['gift_id_product']]['id_image'];
					}
				}
				else
				{
					$gift['gift_id_product_list'] = '';
					$gift['gift_id_product'] = 0;
				}

				$gift['id_image'] = $gift['gift_id_product'].'-'.$gift['id_image'];
				if (1 || $gift['legend'] == '')
				{
					$p = new Product ($gift['gift_id_product'], false, $id_lang);
					$gift['legend'] = $p->name;
				}
				if ($gift['gift_id_product'] != 0)
					$resUpdated[] = $gift;
				$gift['exploded_list'] = explode (',', $gift['gift_id_product_list']); // DEBUG
			}
		}
		else
			$resUpdated = array();
		$_cache[$cacheId] = $resUpdated;
		return $_cache[$cacheId];
	}

	public static function getGiftsInCart($id_cart)
	{
		$sqlReq = 'SELECT go.*
					FROM `'._DB_PREFIX_.'giftonorder_order` as go
					WHERE go.id_cart = '.$id_cart;

		$result = Db::getInstance ()->ExecuteS ($sqlReq);
		if (!$result)
			$result = array();
		return $result;
	}

	public static function giftsCountForCustomer($id_giftonorder, $id_customer = 0)
	{
		if ((int)($id_customer) == 0)
			return 0;

		$sqlReq = 'SELECT COUNT(*) as nb
					FROM `'._DB_PREFIX_.'giftonorder_order` go
					LEFT JOIN `'._DB_PREFIX_.'orders` o ON go.id_order = o.id_order
					WHERE go.id_giftonorder = '.$id_giftonorder.'
						AND o.id_customer = '.$id_customer.'
					GROUP BY go.`id_giftonorder`';
		$res = Db::getInstance ()->getRow ($sqlReq);
		return (int)($res['nb']);
	}

	public static function giftIsToAdd($potential, $cart_amount, $id_customer, $prods_in_cart, $discounts_full)
	{
		$ret = array();
		$ret['value'] = 'notavail';
		$ret['qty'] = 0;

		$discounts = array();
		$has_not_cumulable_discounts = false;
		foreach ($discounts_full as $d)
		{
			if (array_key_exists ($d['name'], $discounts))
				$discounts[$d['name']] += 1;
			else
				$discounts[$d['name']] = 1;
			if (!((bool)($d['cumulable'])))
				$has_not_cumulable_discounts = true;
		}

		// if (Configuration::get('PS_STOCK_MANAGEMENT') && (Product::getQuantity($potential['gift_id_product']) <= 0)){
		// $ret['value'] = 'notavail';
		// return $ret;
		// }
		if ($potential['criteria_discounts'] != '')
		{
			$intersect_discounts = array_intersect_key ($discounts, array_flip (explode (';', $potential['criteria_discounts'])));
			if (count ($intersect_discounts))
			{
				$ret['qty'] = (boolean)($potential['gift_discount_multiple']) ? array_sum ($intersect_discounts) : 1;
				$ret['value'] = 'OK';
				return $ret;
			}
			else
			{
				$ret['qty'] = 0;
				$ret['value'] = 'NoDiscountFound';
				return $ret;
			}
		}
		switch ($potential['criteria_cumulative_with_voucher_type'])
		{
			case _GIFTONORDER_VOUCHERS_CUMULATIVE_:
				if ($has_not_cumulable_discounts)
				{
					$ret['qty'] = 0;
					$ret['value'] = 'NotCumulativeWithNoCumulDiscounts';
					return $ret;
				}
				break;
			case _GIFTONORDER_VOUCHERS_NONE_:
				if (count ($discounts))
				{
					$ret['qty'] = 0;
					$ret['value'] = 'NoCumulativeWithDiscounts';
					return $ret;
				}
				break;
			default:
				break;
		}

		switch ($potential['criteria_type'])
		{
			case _GIFTONORDER_TYPE_FIRSTORDER_:
				if (Order::getCustomerNbOrders ($id_customer) > 0)
				{
					$ret['value'] = 'notfirstorder';
					return $ret;
				}
				break;
			case _GIFTONORDER_TYPE_NEXTORDER_:
				if (Order::getCustomerNbOrders ($id_customer) == 0)
				{
					$ret['value'] = 'notreorder';
					return $ret;
				}
				break;
			default:
		}
		if ($potential['criteria_max_per_customer'] != 0 && $potential['criteria_max_per_customer'] <= Giftonorder::giftsCountForCustomer ($potential['id_giftonorder'], $id_customer))
		{
			$ret['value'] = 'alreadygiven';
			return $ret;
		}

		if ((float)($cart_amount) < (float)($potential['criteria_cart_amount']))
		{
			$ret['value'] = 'amount';
			$ret['missing_amount'] = (float)($potential['criteria_cart_amount']) - (float)($cart_amount);
			return $ret;
		}

		if (count ($prods_in_cart))
		{
			$nb_products = 0;
			$price_total_wt = 0;
			$different_products = array();
			foreach ($prods_in_cart as $prod)
			{
				if (!($potential['criteria_cumulable_reduced_products']) && $prod['reduction_applies'])
					continue;
				if (!($potential['criteria_manufacturers'] == 'any' || (in_array ($prod['id_manufacturer'], explode (',', $potential['criteria_manufacturers'])))))
					continue;
				if (!($potential['criteria_suppliers'] == 'any' || (count (array_intersect (explode (',', $prod['suppliers']), explode (',', $potential['criteria_suppliers']))))))
					continue;

				$common_categories = array_intersect (explode (',', $prod['categories']), array_diff (explode (';', $potential['criteria_categories']), array(
					(int)(Configuration::get ('OLEA_GIFTONORDER_GIFT_CATEGORY'))
				)));
				if (isset ($common_categories) && count ($common_categories))
				{
					if ((int)($prod['id_product_attribute']) && $potential['criteria_attributes'] != '')
					{
						$prod_attributes = Db::getInstance ()->ExecuteS ('
									SELECT a.id_attribute
									FROM `'._DB_PREFIX_.'attribute` a
									LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (a.`id_attribute` = pac.`id_attribute`)
									WHERE pac.`id_product_attribute` = '.(int)($prod['id_product_attribute']).'
									');
						if ($prod_attributes)
						{

							if (!(bool)$potential['criteria_attributes_detectsall'])
							{ // At least one attribute
								$attribute_ok = false;
								foreach ($prod_attributes as $p_attr)
								{
									if (in_array ((int)($p_attr['id_attribute']), explode (';', $potential['criteria_attributes'])))
										$attribute_ok = true;
								}
							}
							else
							{ // All attributes
								$attribute_ok = true;
								$tmp_p_attrib = array();
								foreach ($prod_attributes as $info)
									$tmp_p_attrib[] = $info['id_attribute'];
								foreach (explode (';', $potential['criteria_attributes']) as $pot_attrib)
									if (!in_array ($pot_attrib, $tmp_p_attrib))
										$attribute_ok = false;
							}
						}
						else
							$attribute_ok = false;
					}
					else
						$attribute_ok = true;
					if ($attribute_ok == true)
					{
						if (!array_key_exists ($prod['id_product'], $different_products))
							$different_products[$prod['id_product']] = 0;
						$different_products[$prod['id_product']] += $prod['quantity'];
						$nb_products += $prod['quantity'];
						$price_total_wt += $prod['total_wt'];
					}
				}
			}
			if ($potential['criteria_category_amount'] > 0)
			{
				if ($price_total_wt > $potential['criteria_category_amount'])
					$ret['qty'] = 1;
				else
				{
					$ret['qty'] = 0;
					$ret['value'] = 'categroy_amount';
					$ret['missing_amount'] = $potential['criteria_category_amount'] - $price_total_wt;
					return $ret;
				}
			}
			else
			{
				$nb_different_products = count ($different_products);
				$nb_products = array_sum ($different_products);
				if ((int)($potential['criteria_different_products']) == 0)
					$potential['criteria_different_products'] = 1;
				if ((int)($potential['criteria_nb_products']) == 0)
					$potential['criteria_nb_products'] = 1;

				$debug_loop = 0;
				$nb_assocs_wanted = (int)($potential['criteria_nb_products']);
				if ($nb_assocs_wanted == 0)
					$nb_assocs_wanted = 1;
				$nb_different_products_wanted = $potential['criteria_different_products'];
				$qty_multiple_wanted = $potential['criteria_qty_multiple'];

				$i = $nb_products + 1;
				$nb_assocs_found = 0;
				$fin = false;
				if ($nb_different_products < $nb_different_products_wanted)
					$fin = true;
				while (0 < $i && !$fin)
				{
					reset ($different_products);
					arsort ($different_products);
					$nb_assocs_loop = min (array_slice ($different_products, 0, $nb_different_products_wanted, true));

					if ($nb_assocs_loop < 1)
						$fin = true;
					else
					{
						$nb_assocs_found += $nb_assocs_loop;
						$j = 0;
						foreach ($different_products as $k => &$v)
						{
							if ($j < $nb_different_products_wanted)
								$v -= $nb_assocs_loop;
							$j += 1;
						}
					}
					$i = $i - 1;
				}
				if (!$fin)
				{
					$nb_assocs_found = 0;
					error_log ('Unexpected end of loop in giftonorder');
				}

				if ($nb_assocs_found < $nb_assocs_wanted)
					$ret['qty'] = 0;
				else
				{
					if ($potential['criteria_qty_multiple'])
						$ret['qty'] = (int)($nb_assocs_found / $nb_assocs_wanted);
					else
						$ret['qty'] = 1;
				}

				/*
				if ($debug_loop)
				{
					p (array(
						'different_products' => $different_products,
						'nb_different_products' => $nb_different_products,
						'potential[criteria_categories]' => $potential['criteria_categories'],
						'potential[criteria_different_products]' => (int)($potential['criteria_different_products']),
						'potential[criteria_nb_products]' => (int)($potential['criteria_nb_products']),
						'potential[criteria_qty_multiple]' => (int)($potential['criteria_qty_multiple']),
						'nb_assocs_found' => $nb_assocs_found,
						'ret[qty]' => $ret['qty']
					));
				}
				*/
				if ($ret['qty'] == 0)
				{
					$ret['value'] = 'notenoughitems';
					return $ret;
				}
			}
		}
		$ret['value'] = 'OK';

		return $ret;
	}

	public static function getNextGiftToAttribute($id_cart, $id_customer, $id_lang)
	{
		$toReturn = array();
		$cart = new Cart ((int)($id_cart));
		if (!Validate::isLoadedObject ($cart))
			$cartAmount = 0;
		else
		{
			if ((int)(Configuration::get ('OLEA_GIFTONORDER_AMOUNT_REDUC')) == 0)
				$cartAmount = $cart->getOrderTotal (true, 1);
			else
				$cartAmount = $cart->getOrderTotal (true, 4);
		}
		if (version_compare ('1.5', _PS_VERSION_) <= 0)
			$cartAmount = Tools::convertPrice ($cartAmount, Context::getContext ()->currency, false);
		elseif (version_compare ('1.4', _PS_VERSION_) <= 0)
			$cartAmount = Tools::convertPrice ($cartAmount, Currency::getCurrent (), false);

		$potentialGifts = Giftonorder::getPotentialGift ((int)($id_customer), (int)($id_lang));
		$productsInCart = self::splitCartContent ($cart);

		/*
		 * $discounts = array();
		 * foreach ($cart->getDiscounts() as $d)
		 * if (array_key_exists($d['name'], $discounts))
		 * $discounts[$d['name']] += 1;
		 * else
		 * $discounts[$d['name']] = 1;
		 */
		// $discounts = $cart->getDiscounts();
		$discounts = array(); // To be reviewed

		$potentialNext = array();
		foreach ($potentialGifts as $potential)
		{
			$isToAdd = Giftonorder::giftIsToAdd ($potential, $cartAmount, (int)($id_customer), $productsInCart, $discounts); /* AVOIR */
			switch ($isToAdd['value'])
			{
				case 'OK':
					if (!$potential['allow_other_gift'])
						break 2;
					else
						break;
					// return $toReturn;
				case 'amount':
					$toReturn = $potential;
					$toReturn['missing_otherproducts'] = false;
					$toReturn['missing_amount'] = $isToAdd['missing_amount'];
					$potentialNext[] = $toReturn;
					break;
				case 'notenoughdifferent':
				case 'notenoughitems':
					$toReturn = $potential;
					$toReturn['missing_otherproducts'] = true;
					$toReturn['missing_amount'] = 0;
					$potentialNext[] = $toReturn;
					break;
				default:
				// Nothing
				// either other value, for which not possible to give the gift
			}
		}
		if (count ($potentialNext))
		{
			$retour = array_slice ($potentialNext, -1, 1);
			return $retour[0];
		}
		else
			return array();
	}

	public static function splitCartContent($cart)
	{
		$id_cart = (int)$cart->id;
		$sqlReq = 'SELECT DISTINCT cp.*, go.id_giftonorder,
								if (isnull(go.id_product), false, true) as is_gift,
								(SELECT GROUP_CONCAT(ctgp.id_category )
									FROM '._DB_PREFIX_.'category_product as ctgp
									WHERE ctgp.id_product = cp.id_product
									GROUP BY ctgp.id_product) as categories,
								(SELECT GROUP_CONCAT(DISTINCT id_supplier) FROM '._DB_PREFIX_.'product_supplier ps
								        WHERE ps.id_product = cp.id_product  GROUP BY ps.id_product) as suppliers
					FROM `'._DB_PREFIX_.'cart_product` as cp
					LEFT JOIN `'._DB_PREFIX_.'giftonorder_order` as go ON (go.id_cart = cp.id_cart AND go.id_product = cp.id_product )
					WHERE cp.id_cart = '.(int)($id_cart);
		$result = Db::getInstance ()->ExecuteS ($sqlReq);
		if (!$result)
			$result = array();
		if (count ($result))
		{
			if (version_compare ('1.4', _PS_VERSION_) <= 0)
			{
				$product_has_reduc = array();
				$total = array();
				$total_wt = array();
				$price = array();
				$price_wt = array();
				$manufacturer = array();
				foreach ($cart->getProducts () as $product)
				{
					$product_has_reduc[$product['id_product']] = (($product['reduction_applies'] === false) ? false : true);
					$total[$product['id_product']][$product['id_product_attribute']] = $product['total'];
					$total_wt[$product['id_product']][$product['id_product_attribute']] = $product['total_wt'];
					$price[$product['id_product']][$product['id_product_attribute']] = $product['price'];
					$price_wt[$product['id_product']][$product['id_product_attribute']] = $product['price_wt'];
					$manufacturer[$product['id_product']] = $product['id_manufacturer'];
				}
				foreach ($result as &$res)
				{
					$res['reduction_applies'] = $product_has_reduc[$res['id_product']];
					$res['total'] = $total[$res['id_product']][$res['id_product_attribute']];
					$res['total_wt'] = $total_wt[$res['id_product']][$res['id_product_attribute']];
					$res['price'] = $price[$res['id_product']][$res['id_product_attribute']];
					$res['price_wt'] = $price_wt[$res['id_product']][$res['id_product_attribute']];
					$res['id_manufacturer'] = $manufacturer[$res['id_product']];
				}
			}
			else
				$res['reduction_applies'] = true; // not supported on 1.2 / 1.3
		}
		return $result;
	}

	public static function getFilteredGiftsOfProduct($product, $id_lang = null)
	{
		return array();
	}

	/**
	 * ********************************************************************
	 */
	public function cleanShops()
	{
		Db::getInstance ()->Execute ('DELETE FROM `'._DB_PREFIX_.'giftonorder_shop` WHERE `id_giftonorder` = '.(int)($this->id));
	}

	public function addShops($shops)
	{
		foreach ($shops as $shop)
		{
			$row = array(
				'id_giftonorder' => (int)($this->id),
				'id_shop' => (int)($shop)
			);
			Db::getInstance ()->AutoExecute (_DB_PREFIX_.'giftonorder_shop', $row, 'INSERT');
		}
	}

	public function getShops()
	{
		$shops = array();
		$result = Db::getInstance ()->ExecuteS ('
		SELECT gs.`id_shop`
		FROM '._DB_PREFIX_.'giftonorder_shop gs
		WHERE gs.`id_giftonorder` = '.(int)($this->id));
		if (is_array ($result))
			foreach ($result as $shop)
				$shops[] = $shop['id_shop'];
		return $shops;
	}

	public function cleanGroups()
	{
		Db::getInstance ()->Execute ('DELETE FROM `'._DB_PREFIX_.'giftonorder_group` WHERE `id_giftonorder` = '.(int)($this->id));
	}

	public function addGroups($groups)
	{
		foreach ($groups as $group)
		{
			$row = array(
				'id_giftonorder' => (int)($this->id),
				'id_group' => (int)($group)
			);
			Db::getInstance ()->AutoExecute (_DB_PREFIX_.'giftonorder_group', $row, 'INSERT');
		}
	}

	public function getGroups()
	{
		$groups = array();
		$result = Db::getInstance ()->ExecuteS ('
		SELECT gg.`id_group`
		FROM '._DB_PREFIX_.'giftonorder_group gg
		WHERE gg.`id_giftonorder` = '.(int)($this->id));
		if (is_array ($result))
			foreach ($result as $group)
				$groups[] = $group['id_group'];
		return $groups;
	}

	public function checkAccess($id_customer)
	{
		if (!$id_customer)
		{
			$result = Db::getInstance ()->getRow ('
			SELECT gg.`id_group`
			FROM '._DB_PREFIX_.'giftonorder_group gg
			WHERE gg.`id_category` = '.(int)($this->id).' AND gg.`id_group` = 1');
		}
		else
		{
			$result = Db::getInstance ()->getRow ('
			SELECT ctg.`id_group`
			FROM '._DB_PREFIX_.'giftonorder_group gg
			INNER JOIN '._DB_PREFIX_.'customer_group cg on (cg.`id_group` = gg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
			WHERE gg.`id_category` = '.(int)($this->id));
		}
		if ($result && isset ($result['id_group']) && $result['id_group'])
			return true;
		return false;
	}

	public function updateGroup($list)
	{
		$this->cleanGroups ();
		if ($list && count ($list))
			$this->addGroups ($list);
	}

	public static function save_preselected_gifts($cart, $gifts_array)
	{
		if (!Validate::isLoadedObject ($cart))
			return;
		Db::getInstance ()->execute ('
				UPDATE  '._DB_PREFIX_.'cart
				SET oleagoo_preselectedgifts = "'.addslashes (serialize ($gifts_array)).'"
				WHERE id_cart = '.(int)$cart->id);
	}

	public static function get_preselected_gifts($cart)
	{
		if (!Validate::isLoadedObject ($cart))
			return array();

		$res = Db::getInstance ()->getValue ('
				SELECT oleagoo_preselectedgifts
				FROM '._DB_PREFIX_.'cart
				WHERE id_cart = '.(int)$cart->id);
		if ($res == '')
			return array();
		else
			return unserialize (Tools::stripslashes ($res));
	}

	protected function setDefinitionRetrocompatibility()
	{
		$res = parent::setDefinitionRetrocompatibility ();

		foreach ($this->{'fieldsValidateLang'} as $field => $validate)
			$this->def['fields'][$field]['lang'] = true;

		foreach ($this->{'fieldsRequiredLang'} as $field)
			$this->def['fields'][$field]['lang'] = true;

		foreach ($this->{'fieldsSizeLang'} as $field => $size)
			$this->def['fields'][$field]['lang'] = true;

		return $res;
	}

	public function getManufacturers()
	{
		return explode (',', $this->criteria_manufacturers);
	}

	public function getSuppliers()
	{
		return explode (',', $this->criteria_suppliers);
	}

	public function setManufacturers($manufacturers)
	{
		if (in_array ('any', $manufacturers))
			$this->criteria_manufacturers = 'any';
		else
			$this->criteria_manufacturers = implode (',', $manufacturers);
	}

	public function setSuppliers($suppliers)
	{
		if (in_array ('any', $suppliers))
			$this->criteria_suppliers = 'any';
		else
			$this->criteria_suppliers = implode (',', $suppliers);
	}

	public static function oleaAddObjectTableAssociation($table_name)
	{
		 Shop::getAssoTable($table_name); // To force init
		 return Shop::addTableAssociation($table_name, array('type' => 'shop'));
	}
}
