<?php

/**
  * Customer class, Customer.php
  * Customers management
  * @category classes
  *
  * @author PrestaShop <support@prestashop.com>
  * @copyright PrestaShop
  * @license http://www.opensource.org/licenses/osl-3.0.php Open-source licence 3.0
  * @version 1.0
  *
  */

class		Customer extends ObjectModel
{
	public 		$id;

	/** @var string Secure key */
	public		$secure_key;

	/** @var integer Gender ID */
	public		$id_gender = 9;

	/** @var string Lastname */
	public 		$lastname;

	/** @var string Firstname */
	public 		$firstname;

	/** @var string Birthday (yyyy-mm-dd) */
	public 		$birthday = NULL;

	/** @var string e-mail */
	public 		$email;

	/** @var boolean Newsletter subscription */
	public 		$newsletter;

	/** @var boolean Opt-in subscription */
	public 		$optin;

	/** @var integer Password */
	public 		$passwd;

	/** @var boolean Status */
	public 		$active = 1;

	/** @var string Object creation date */
	public 		$date_add;

	/** @var string Object last modification date */
	public 		$date_upd;

	public		$years;
	public		$days;
	public		$months;

	protected $tables = array ('customer');

 	protected 	$fieldsRequired = array('lastname', 'passwd', 'firstname', 'email');
 	protected 	$fieldsSize = array('lastname' => 32, 'passwd' => 32, 'firstname' => 32, 'email' => 128);
 	protected 	$fieldsValidate = array('secure_key' => 'isMd5', 'lastname' => 'isName', 'firstname' => 'isName', 'email' => 'isEmail', 'passwd' => 'isPasswd',
		 'id_gender' => 'isUnsignedId', 'birthday' => 'isBirthDate', 'newsletter' => 'isBool', 'optin' => 'isBool', 'active' => 'isBool');

	protected 	$table = 'customer';
	protected 	$identifier = 'id_customer';

	public function getFields()
	{
		parent::validateFields();

		$fields['secure_key'] = pSQL($this->secure_key);
		$fields['id_gender'] = intval($this->id_gender);
		$fields['lastname'] = pSQL(Tools::strtoupper($this->lastname));
		$fields['firstname'] = pSQL($this->firstname);
		$fields['birthday'] = pSQL($this->birthday);
		$fields['email'] = pSQL($this->email);
		$fields['newsletter'] = intval($this->newsletter);
		$fields['optin'] = intval($this->optin);
		$fields['passwd'] = pSQL($this->passwd);
		$fields['active'] = intval($this->active);
		$fields['date_add'] = pSQL($this->date_add);
		$fields['date_upd'] = pSQL($this->date_upd);

		return $fields;
	}

	public function add($autodate = true, $nullValues = true)
	{
		$this->birthday = (empty($this->years) ? $this->birthday : intval($this->years).'-'.intval($this->months).'-'.intval($this->days));
		$this->secure_key = md5(uniqid(rand(), true));
	 	return parent::add($autodate, $nullValues);
	}

	public function update($nullValues = false)
	{
		$this->birthday = (empty($this->years) ? $this->birthday : intval($this->years).'-'.intval($this->months).'-'.intval($this->days));
	 	return parent::update(true);
	}
	
	public function delete()
	{
		$addresses = $this->getAddresses(intval(Configuration::get('PS_LANG_DEFAULT')));
		foreach ($addresses as $address)
		{
			$obj = new Address($address['id_address']);
			$obj->delete();
		}
		return parent::delete();
	}

	/**
	  * Return customers list
	  *
	  * @return array Customers
	  */
	static public function getCustomers()
	{
		return Db::getInstance()->ExecuteS('
		SELECT `id_customer`, `email`
		FROM `'._DB_PREFIX_.'customer`
		ORDER BY `id_customer` ASC');
	}

	/**
	  * Return customer instance from its e-mail (optionnaly check password)
	  *
	  * @param string $email e-mail
	  * @param string $passwd Password is also checked if specified
	  * @return Customer instance
	  */
	public function getByEmail($email, $passwd = NULL)
	{
	 	if (!Validate::isEmail($email) OR ($passwd AND !Validate::isPasswd($passwd)))
	 		die (Tools::displayError());

		$result = Db::getInstance()->GetRow('
		SELECT *
		FROM `'._DB_PREFIX_	.'customer`
		WHERE `active` = 1 AND `email` = \''.pSQL($email).'\''.(isset($passwd) ? 'AND `passwd` = \''.md5(pSQL(_COOKIE_KEY_.$passwd)).'\'' : ''));

		if (!$result)
			return false;
		$this->id = $result['id_customer'];
		foreach ($result AS $key => $value)
			if (key_exists($key, $this))
				$this->{$key} = $value;

		return $this;
	}

	/**
	  * Check if e-mail is already registered in database
	  *
	  * @param string $email e-mail
	  * @return mixed Customer ID if found, an empty array otherwise
	  */
	static public function customerExists($email)
	{
	 	if (!Validate::isEmail($email))
	 		die (Tools::displayError());

		$result = Db::getInstance()->getRow('
		SELECT `id_customer`
		FROM `'._DB_PREFIX_.'customer`
		WHERE `email` = \''.pSQL($email).'\'');
		return isset($result['id_customer']);
	}

	/**
	  * Check if, except current customer, someone else registered this e-email
	  *
	  * @return integer Number of customers who have also this e-mail
	  */
	public function cantChangeemail()
	{
	 	if (!Validate::isEmail($this->email))
	 		die (Tools::displayError());
		$result = Db::getInstance()->getRow('
		SELECT COUNT(`id_customer`) AS total
		FROM `'._DB_PREFIX_.'customer`
		WHERE `email` = \''.pSQL($this->email).'\' AND `id_customer` != '.intval($this->id));

		return $result['total'];
	}

	/**
	  * Check if an address is owned by a customer
	  *
	  * @param integer $id_customer Customer ID
	  * @param integer $id_address Address ID
	  * @return boolean result
	  */
	static public function customerHasAddress($id_customer, $id_address)
	{
		$result = Db::getInstance()->getRow('
		SELECT COUNT(`id_address`) AS ok
		FROM `'._DB_PREFIX_.'address`
		WHERE `id_customer` = '.intval($id_customer).'
		AND `id_address` = '.intval($id_address).'
		AND `deleted` = 0');

		return $result['ok'];
	}

	/**
	  * Return customer addresses
	  *
	  * @param integer $id_lang Language ID
	  * @return array Addresses
	  */
	public function getAddresses($id_lang)
	{
		return Db::getInstance()->ExecuteS('
		SELECT a.*, cl.`name` AS country, s.name AS state
		FROM `'._DB_PREFIX_.'address` a
		LEFT JOIN `'._DB_PREFIX_.'country` c ON a.`id_country` = c.`id_country`
		LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON c.`id_country` = cl.`id_country`
		LEFT JOIN `'._DB_PREFIX_.'state` s ON s.`id_state` = a.`id_state`
		WHERE `id_lang` = '.intval($id_lang).'
		AND `id_customer` = '.intval($this->id).'
		AND a.`deleted` = 0');
	}


	/**
	  * Returns customer last connections
	  *
	  * @param integer $nb Number of connections wanted
	  * @return array Connections
	  */
	public function getConnections($nb = 10)
	{
		return Db::getInstance()->ExecuteS('
		SELECT `ip_address`, `date`
		FROM `'._DB_PREFIX_.'connections`
		WHERE `id_customer` = '.intval($this->id).'
		ORDER BY `date` DESC
		LIMIT 0,'.intval($nb));
	}

	/**
	  * Count the number of addresses for a customer
	  *
	  * @param integer $id_customer Customer ID
	  * @return integer Number of addresses
	  */
	public static function getAddressesTotalById($id_customer)
	{
		$result = Db::getInstance()->getRow('
		SELECT COUNT(a.`id_address`) AS total
		FROM `'._DB_PREFIX_.'address` a
		WHERE a.`id_customer` = '.intval($id_customer).'
		AND a.`deleted` = 0');

		return $result['total'];
	}

	/**
	  * Check if customer password is the right one
	  *
	  * @param string $passwd Password
	  * @return boolean result
	  */
	static public function checkPassword($id_customer, $passwd)
	{
	 	if (!Validate::isUnsignedId($id_customer) OR !Validate::isMd5($passwd))
	 		die (Tools::displayError());

		$result = Db::getInstance()->getRow('
		SELECT `id_customer`
		FROM `'._DB_PREFIX_.'customer`
		WHERE `id_customer` = '.intval($id_customer).' AND `passwd` = \''.pSQL($passwd).'\'');

		return isset($result['id_customer']) ? $result['id_customer'] : false;
	}

	/**
	  * Add a connection in the connections table
	  *
	  * @return boolean result
	  */
	public function addConnection()
	{
		if ($ip = ip2long($_SERVER['REMOTE_ADDR']))
			return Db::getInstance()->AutoExecute(_DB_PREFIX_.'connections', array('id_customer' => intval($this->id),
			'ip_address' => intval($ip), 'date' => date('Y-m-d H:i:s')), 'INSERT');
		return false;
	}

	/**
	  * Return customers who have subscribed to the newsletter
	  *
	  * @return array Customers
	  */
	public static function getNewsletteremails()
	{
		return Db::getInstance()->ExecuteS('
		SELECT `email`, `firstname`, `lastname`, `newsletter`
		FROM `'._DB_PREFIX_.'customer`
		WHERE `newsletter` = 1
		AND `active` = 1');
	}

	/**
	  * Return the number of customers who registered today
	  *
	  * @return integer number of customers who registered today
	  */
	public static function getTodaysRegistration()
	{
		$result = Db::getInstance()->getRow('
		SELECT COUNT(`id_customer`) as nb
		FROM `'._DB_PREFIX_.'customer`
		WHERE DAYOFYEAR(`date_add`) = DAYOFYEAR(NOW())
		AND YEAR(`date_add`) = YEAR(NOW())');
		if (!$result['nb'])
			return '0';
		return $result['nb'];
	}

	/**
	  * Light back office search for customers
	  *
	  * @param string $query Searched string
	  * @return array Corresponding customers
	  */
	public static function searchByName($query)
	{
	 	if (!Validate::isName($query))
	 		die (Tools::displayError());

		return Db::getInstance()->ExecuteS('
		SELECT c.*, g.`iso_code`
		FROM `'._DB_PREFIX_.'customer` c
		LEFT JOIN `'._DB_PREFIX_.'gender` g ON g.`id_gender` = c.`id_gender`
		WHERE c.`email` LIKE \'%'.pSQL($query).'%\'
		OR c.`lastname` LIKE \'%'.pSQL($query).'%\'
		OR c.`firstname` LIKE \'%'.pSQL($query).'%\'');
	}

	/**
	  * Return several useful statistics about customer
	  *
	  * @return array Stats
	  */
	public function getStats()
	{
		$result = Db::getInstance()->getRow('
		SELECT COUNT(`id_order`) AS nb_orders, SUM(`total_paid`) AS total_orders
		FROM `'._DB_PREFIX_.'orders` o
		WHERE o.`id_customer` = '.intval($this->id).'
		AND (
			SELECT os.`invoice`
			FROM `'._DB_PREFIX_.'orders` oo
			LEFT JOIN `'._DB_PREFIX_.'order_history` oh ON oh.`id_order` = oo.`id_order`
			LEFT JOIN `'._DB_PREFIX_.'order_state` os ON os.`id_order_state` = oh.`id_order_state`
			WHERE oo.`id_order` = o.`id_order`
			ORDER BY oh.`date_add` DESC, oh.`id_order_history` DESC
			LIMIT 1
		) = 1');

		$result2 = Db::getInstance()->getRow('
		SELECT MAX(`date`) AS last_visit
		FROM `'._DB_PREFIX_.'connections` c
		WHERE c.`id_customer` = '.intval($this->id).'
		GROUP BY c.`id_customer`');

		$result3 = Db::getInstance()->getRow('
		SELECT (YEAR(CURRENT_DATE)-YEAR(c.`birthday`)) - (RIGHT(CURRENT_DATE, 5)<RIGHT(c.`birthday`, 5)) AS age
		FROM `'._DB_PREFIX_.'customer` c
		WHERE c.`id_customer` = '.intval($this->id));

		$result['last_visit'] = $result2['last_visit'];
		$result['age'] = $result3['age'] != date('Y') ? $result3['age'] : '--';
		return $result;
	}

	/**
	  * Return last cart ID for this customer
	  *
	  * @return integer Cart ID
	  */
	public function getLastCart()
	{
		$result = Db::getInstance()->getRow('
		SELECT MAX(c.`id_cart`) AS id_cart
		FROM `'._DB_PREFIX_.'cart` c
		WHERE c.`id_customer` = '.intval($this->id));
		if (isset($result['id_cart']))
			return $result['id_cart'];
		return false;
	}
}

?>
