<?php if (!defined('HTTP_SERVER')) die('You can not access this file directly!');
/**
  @licence GPL 2005-2011  The osCSS developers - osCSS Open Source E-commerce
  @portion code Copyright (c) 2002 osCommerce
  @package osCSS-2 <www http://www.oscss.org>
  @version 2.1.0
  @date  29/01/11, 10:55
  @author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
  @encode UTF-8
  @Class customer
  gestion public des clients|membre
  Traitement db select|insert|update du compte membre
  Fonction native du noyau deporté dans cette class
*/

class customer {

  /**
    @var l'id du customer chargée
  */
  public $customer_id;
  /**
    @var tableau detail customers
  */
  public $customer;

  /**
    @var $methodeMessage string name methode / for methode call in messageStack class
  */
  protected  static $methodeMessage='add_session';

  protected static $_instance;

  /**
    Constructeur
    @param
    @a int id customer
  */
   protected function __construct($customer_id=''){

    if(!empty($customer_id)) $this->the_customer($customer_id);
    if(!function_exists('tep_validate_password')) require_once(DIR_WS_FUNCTIONS.'password_funcs.php');

    return $this->customer;
  }

  /**
   * \fn getInstance
   * @param $customer_id int | null
   */
  public static function getInstance($customer_id='') {
    if(self::$_instance == null) self::$_instance = new self($customer_id);
    return self::$_instance;
  }

  /**
   * \fn resetInstance()
   */
  public static function resetInstance(){
    self::$_instance = null;
    return self::getInstance();
  }


  /**
   * \brief fetch user data
   * @param $customer_id integer
   * @return array
   */
  public function the_customer($customer_id=''){
    global $page;
    if(!is_numeric($customer_id)) return $this->customer;

    $this->languages_id=$page->the_var('languages_id');
    $this->customer_id=(int)$customer_id;
    $this->detail_cust();

    return $this->customer;
  }

  /**
   * \fn detail_cust()
   * \brief Reconstruit le detail d'un customer
   *  Prend en Charge la gestion des extra_fields
   *  @return array
   */
    private function detail_cust(){
      $account_query = tep_db_query("select customers_id, customers_gender, customers_firstname, customers_lastname, customers_dob, customers_email_address, customers_telephone, customers_fax, customers_newsletter,customers_default_address_id, c.customers_group_id,  c.customers_group_ra, c.customers_payment_allowed, c.customers_shipment_allowed, c.customers_order_total_allowed, c.customers_specific_taxes_exempt , customers_status, customers_shopping_points  from " . TABLE_CUSTOMERS . " c where customers_id = '" . $this->customer_id . "'");
      $account = tep_db_fetch_array($account_query);

      $value_query = tep_db_query("select fields_name,fields_key, value from " . TABLE_EXTRA_FIELDS . " ce, " . TABLE_CUSTOMERS_TO_EXTRA_FIELDS . " cef, " . TABLE_EXTRA_FIELDS_INFO . " cei where cef.customers_id= '" . $this->customer_id . "'  and cei.fields_id=ce.fields_id and cef.fields_id= cei.fields_id  and languages_id='".$this->languages_id."' and ce.fields_admin !=1 " );

      while ($t=tep_db_fetch_array($value_query) )
        $account[(!empty($t['fields_key'])? $t['fields_key']: $t['fields_name'])]=$t['value'];

      $this->customer=$account;
    }

    /**
     * \fn add_var_customer($key, $value)
     * \brief add data in array current user
     * @param $key string
     * @param $value string
     * @return non
     */
    public function add_var_customer($key, $value){
      $this->customer[$key]=$value;
    }

    /**
     * \fn detail_long_cust()
     * \brief full data user
     * @return array
     */
    public function detail_long_cust(){
      $account_query = tep_db_query("select * from " . TABLE_CUSTOMERS_INFO . " where customers_info_id = '" . $this->customer_id . "'");
      $account = tep_db_fetch_array($account_query);
      return $this->customer=array_merge((array)$this->customer,(array)$account);
    }


   /**
    * \fn userNotifiUpdate($_post)
    * \brief Assure enregsitrement action=newseltters
    * @param $_post array
   */
    public function userNotifiUpdate($_post){
      global $page;

      if (isset($_post['newsletter_product_notification']) && is_numeric($_post['newsletter_product_notification'])) $sql_data_array = array('global_product_notifications'=> '1' );
      else  $sql_data_array = array('global_product_notifications'=> '0' );

      tep_db_perform(TABLE_CUSTOMERS_INFO, $sql_data_array, 'update', " customers_info_id = '" . $this->customer_id . "'");

      if (isset($_post['newsletter_general']) && is_numeric($_post['newsletter_general'])) $sql_data_array = array('customers_newsletter'=> '1' );
      else $sql_data_array = array('customers_newsletter'=> '0' );

      $res=tep_db_perform(TABLE_CUSTOMERS, $sql_data_array, 'update', " customers_id = '" . $this->customer_id . "'");

      if($res ==false) return false;
      else  self::PassmessageStack('account', SUCCESS_NEWSLETTER_UPDATED, 'success');

      return true;
    }

    /**
     * \fn userTestNotExist($email)
     * \brief test user not exist, control by email
     * @param $email string
     * @return boolean
     *        true if not exist
     *        false if exists
     */
    public function userTestNotExist($email){
	return (!(bool)self::search('customers_email_address', $email)?false: true );
    }

    /**
      @fn CheckMailAndPass($password, $email_address)
      @brief test mail and password for login
      @param $password string
      @param $email_address string
      @return boolean false Or integer customers_id
    */
    public function CheckMailAndPass($password, $email_address){
      $DB=Database::getInstance();
      $check_customer_query = $DB->query("select customers_id,customers_password from " . TABLE_CUSTOMERS . " where customers_email_address = '" . tep_db_input($email_address) . "'  ");
      $check_customer = $check_customer_query->fetchAssoc();

      /// include the password crypto functions
      if(!function_exists('tep_validate_password')) require(DIR_WS_FUNCTIONS . 'password_funcs.php');

      return (!tep_validate_password($password, $check_customer['customers_password'])? false : (int)$check_customer['customers_id'] ) ;
    }


    /**
      * \fn userInsert($_post)
      * \brief creat account
      * @param $_post array
      * @return object / false
      */
    public function userInsert($_post){
      global $page;
      $this->languages_id=$page->the_var('languages_id');
      $newcustomer=array();

      if ( ( ($resul=$this->CheckData($_post)) && $resul !=false && is_array($resul))
	  && ( ($pass=$this->CheckDataPassword($_post)) && $pass !=false && is_array($pass) ) ){

	$resul=array_merge($pass,$resul);

	/// include the password crypto functions
	require_once(DIR_WS_FUNCTIONS . 'password_funcs.php');

	if (_cst_bool('CUSTOMER_FORCE_UCWORDS')) {
	  $resul['lastname']=ucwords($resul['lastname']);
	  $resul['firstname']=ucwords($resul['firstname']);
	}
	if (_cst_bool('CUSTOMER_FORCE_STRTOUPPER')) {
	  $resul['lastname']=strtoupper($resul['lastname']);
	}

	$check_customer['customers_group_id']=( (_cst_bool('ACCOUNT_COMPANY') && isset($resul['company_tax_id']))? 0 : 1 );

	$sql_data_array = array('customers_firstname' => $resul['firstname'],
				'customers_lastname' => $resul['lastname'],
				'customers_email_address' => $resul['email_address'],
				'customers_telephone' => $resul['telephone'],
				'customers_fax' => $resul['fax'],
				'customers_newsletter' => $resul['newsletter'],
				'customers_password' => tep_encrypt_password($resul['password']),
				'customers_group_ra'=>  $check_customer['customers_group_id'],
				'customers_language'=>  $this->languages_id,
				'customers_status'=>  (_cst_bool('ACCOUNT_FORCE_ACTIV_MAIL')? 2 : 1)
				);

	if (_cst_bool('ACCOUNT_GENDER')) $sql_data_array['customers_gender'] = $resul['gender'];
	if (_cst_bool('ACCOUNT_DOB')) $sql_data_array['customers_dob'] = tep_date_raw($resul['dob']);

	$res=tep_db_perform(TABLE_CUSTOMERS, $sql_data_array);
	$newcustomer = $sql_data_array;

	$newcustomer['customers_id']=$customer_id=tep_db_insert_id($res);

	tep_db_query("insert into " . TABLE_CUSTOMERS_INFO . " (customers_info_id, customers_info_number_of_logons, customers_info_date_account_created,customers_info_date_account_last_modified) values ('" . (int)$customer_id . "', '0', now(), now())");


	/**
	  @brief extra fields sauf specifique admin
	*/
	$extra_fields_query = tep_db_query("select ce.fields_id, fields_key, fields_required_email from " . TABLE_EXTRA_FIELDS . " ce where ce.fields_status=1 and fields_admin !=1 ");
	while($extra_fields = tep_db_fetch_array($extra_fields_query)) {
	  if(isset($resul['fields_' . $extra_fields['fields_id']])){
	    $sql_data_array = array('customers_id' => (int)$customer_id,
				    'fields_id' => $extra_fields['fields_id'],
				    'value' => $resul['fields_' . $extra_fields['fields_id']]);
	  }
	  else {
	    $sql_data_array = array('customers_id' => (int)$customer_id,
				    'fields_id' => $extra_fields['fields_id'],
				    'value' => '');
	    /// value in list mutli
	    if(isset($resul['fields_' . $extra_fields['fields_id'] . '_total'])){
	      $is_add = false;
	      for($i = 1; $i <= $resul['fields_' . $extra_fields['fields_id'] . '_total']; $i++) {
		if(isset($_POST['fields_' . $extra_fields['fields_id'] . '_' . $i])) {
		  if($is_add) { $sql_data_array['value'] .= "\n"; }
		  else { $is_add = true; }
		  $sql_data_array['value'] .= $resul['fields_' . $extra_fields['fields_id'] . '_' . $i];
		}
	      }
	    }
	  }

	  tep_db_perform(TABLE_CUSTOMERS_TO_EXTRA_FIELDS, $sql_data_array);

	  $newcustomer[(isset($extra_fields['fields_key'])?$extra_fields['fields_key'] : 'fields_'.$extra_fields['fields_id'])]=$sql_data_array['value'];
	  $newcustomer['extra'][]=array_merge($sql_data_array, array('email'=>$extra_fields['fields_required_email']) );
	}


      }
      else return false;

      if ( ($resul=$this->CheckDataAddressBook($_post)) && $resul !=false && is_array($resul)) {

	if (_cst_bool('CUSTOMER_CITY_FORCE_STRTOUPPER')) {
	  $resul['city']=strtoupper($resul['city']);
	}

	$sql_data_array = array('customers_id' => $customer_id,
				'entry_firstname' => $resul['firstname'],
				'entry_lastname' => $resul['lastname'],
				'entry_street_address' => $resul['street_address'],
				'entry_postcode' => $resul['postcode'],
				'entry_city' => $resul['city'],
				'entry_country_id' => $resul['country']);

	if (_cst_bool('ACCOUNT_GENDER')) $sql_data_array['entry_gender'] = $resul['gender'];
	if (_cst_bool('ACCOUNT_COMPANY')){
	  $sql_data_array['entry_company'] = $resul['company'];
	  $sql_data_array['entry_company_tax_id'] = $resul['company_tax_id'];
	}
	if (_cst_bool('ACCOUNT_SUBURB')) $sql_data_array['entry_suburb'] = $resul['suburb'];
	if (_cst_bool('ACCOUNT_STATE')) {
	  if (isset($resul['zone_id']) && $resul['zone_id'] > 0) {
	    $sql_data_array['entry_zone_id'] = @$resul['zone_id'];
	    $sql_data_array['entry_state'] = '';
	  } else {
	    $sql_data_array['entry_zone_id'] = '0';
	    $sql_data_array['entry_state'] = @$resul['state'];
	  }
	}

	tep_db_perform(TABLE_ADDRESS_BOOK, $sql_data_array);

	$newcustomer=array_merge($newcustomer,$sql_data_array);

	$cs_s=tep_db_query("select address_book_id from " . TABLE_ADDRESS_BOOK . "  where customers_id='".$customer_id."' ORDER BY address_book_id DESC");
	$cs=tep_db_fetch_array($cs_s);
	$address_id=$cs['address_book_id'];

	$newcustomer['address_book_id']= $address_id;

	tep_db_query("update " . TABLE_CUSTOMERS . " set customers_default_address_id = '" . (int)$address_id . "' where customers_id = '" . (int)$customer_id . "'");
      }
      else {
	$resul=$this->CheckData($_post);
	$sql_data_array = array('customers_id' => $customer_id,
				'entry_firstname' => $resul['firstname'],
				'entry_lastname' => $resul['lastname']);

	tep_db_perform(TABLE_ADDRESS_BOOK, $sql_data_array);

	$cs_s=tep_db_query("select address_book_id from " . TABLE_ADDRESS_BOOK . "  where customers_id='".$customer_id."' ORDER BY address_book_id DESC");
	$cs=tep_db_fetch_array($cs_s);
	$address_id=$cs['address_book_id'];

	$newcustomer['address_book_id']= $address_id;

	tep_db_query("update " . TABLE_CUSTOMERS . " set customers_default_address_id = '" . (int)$address_id . "' where customers_id = '" . (int)$customer_id . "'");
      }

      /**
	@brief call method module account
      */
      $page=page::getInstance();
      $aca_account=$page->new_class('account',$customer_id);
      $aca_account->userInsert($newcustomer);

      return (is_array($newcustomer) ? new objectInfo(self::CleanKey($newcustomer)) : false);
    }



    /**
     * \fn userUpdate($_post)
     * \brief  Assure enregsitrement d'un customers info de action=edit
     * @param $_post
     * @return boolean
     */
    public function userUpdate($_post){

      global $page;

      $this->languages_id=$page->the_var('languages_id');

      if ( ($resul=$this->CheckData($_post,'',false)) && $resul !=false && is_array($resul)) {

	$sql_data_array = array('customers_firstname' => $resul['firstname'],
				'customers_lastname' => $resul['lastname'],
				'customers_email_address' => $resul['email_address'],
				'customers_telephone' => $resul['telephone'],
				'customers_fax' => $resul['fax']);

	if (_cst_bool('ACCOUNT_GENDER')) $sql_data_array['customers_gender'] = $resul['gender'];
	if (_cst_bool('ACCOUNT_DOB')) $sql_data_array['customers_dob'] = tep_date_raw($resul['dob']);

	tep_db_perform(TABLE_CUSTOMERS, $sql_data_array, 'update', "customers_id = '" . $this->customer_id . "'");

	tep_db_query("update " . TABLE_CUSTOMERS_INFO . " set customers_info_date_account_last_modified = now() where customers_info_id = '" . $this->customer_id . "'");


      /**
      * TODO: Reporter usage function up adress book
      */
	$res=array();
	$bas_user=tep_db_query("select fields_id from " . TABLE_CUSTOMERS_TO_EXTRA_FIELDS . " where customers_id=" . $this->customer_id);
	while ($extra_fields = tep_db_fetch_array($bas_user)) {
	  $res[]=$extra_fields['fields_id'];
	}
	$extra_fields_query = tep_db_query($sql="select ce.fields_id from " . TABLE_EXTRA_FIELDS . " ce  where  ce.fields_status=1 and fields_admin =0 " );

	while ($extra_fields = tep_db_fetch_array($extra_fields_query)) {
	  if(isset($resul['fields_' . $extra_fields['fields_id']])){
	    $sql_data_array = array('value' => $resul['fields_' . $extra_fields['fields_id']]);
	  }else {
	    $sql_data_array = array('value' => '');
	    $is_add = false;
	    for($i = 1; $i <= $_post['fields_' . $extra_fields['fields_id'] . '_total']; $i++) {
	      if(isset($resul['fields_' . $extra_fields['fields_id'] . '_' . $i])) {
		if($is_add) {
		  $sql_data_array['value'] .= "\n";
		}
		else {
		  $is_add = true;
		}
		$sql_data_array['value'] .= $resul['fields_' . $extra_fields['fields_id'] . '_' . $i];
	      }
	    }
	  }

	  if(in_array($extra_fields['fields_id'],$res)) tep_db_perform(TABLE_CUSTOMERS_TO_EXTRA_FIELDS, $sql_data_array, 'update', "fields_id='".(int)$extra_fields['fields_id']."' and customers_id='".(int)$this->customer_id."'");
	  else{
	    $sql_data_array['customers_id']=(int)$this->customer_id;
	    $sql_data_array['fields_id']=(int)$extra_fields['fields_id'];
	    tep_db_perform(TABLE_CUSTOMERS_TO_EXTRA_FIELDS, $sql_data_array);
	  }
	}

	self::PassmessageStack('account', SUCCESS_ACCOUNT_UPDATED, 'success');

      }

      /**
	@brief call method module account
      */
      $page=page::getInstance();
      $aca_account=$page->new_class('account',$this->customer_id);

      $aca_account->userUpdate($_post);

      return (($resul==false)?true:false);
    }


  /**
    * \fn userUpdatepassword($_post)
    * \brief Update password password_current
    *  depend method checkPasswordProcess()
    * @param $_post array(
    * 					password_confirmation,
    * 					password_current ,
    * 					password_new )
    * @return boolean
    */
    public function userUpdatepassword($_post){
      global $page;

      $_current = tep_db_prepare_input($_post['password_current']);
      $_new = tep_db_prepare_input($_post['password_new']);
      $_confirmation = tep_db_prepare_input($_post['password_confirmation']);

      if ($this->checkPasswordProcess($_current, $_new, $_confirmation) ) {
          tep_db_query("update " . TABLE_CUSTOMERS . " set customers_password = '" . tep_encrypt_password($_new) . "' where customers_id = '" . $this->customer_id . "'");

          tep_db_query("update " . TABLE_CUSTOMERS_INFO . " set customers_info_date_account_last_modified = now() where customers_info_id = '" . $this->customer_id . "'");

          self::PassmessageStack('account', SUCCESS_PASSWORD_UPDATED, 'success');
          return true;
      }
      return false;
    }



  /**
   * \fn count_customer_orders($id = '', $check_session = true)
   * \brief count order for customers
   * @param $id integer id customer
   * @param $check_session boolean control session
   * @return integer (number of order)
   */
  public static function count_customer_orders($id = '', $check_session = true) {
    $DB=Database::getInstance();
    global $customer_id;

    if (is_numeric($id) == false) {
      if (tep_session_is_registered('customer_id'))  $id = $customer_id;
      else return 0;
    }

    if ($check_session == true) {
      if ( (tep_session_is_registered('customer_id') == false) || ($id != $customer_id) ) {
        return 0;
      }
    }

    $orders_check_query = $DB->query("select count(*) as total from " . TABLE_ORDERS . " where customers_id = '" . (int)$id . "'");
    $orders_check = $orders_check_query->fetchAssoc();

    return $orders_check['total'];
  }

  /**
   * \fn count_customer_address_book_entries($id = '', $check_session = true)
   * @param $id customer id
   * @param $check_session boolean
   * @return integer
   */
  public static function count_customer_address_book_entries($id = '', $check_session = true) {
    global $customer_id;
    $DB=Database::getInstance();
    if (is_numeric($id) == false) {
      if (tep_session_is_registered('customer_id'))  $id = $customer_id;
       else   return 0;
    }

    if ($check_session == true) {
      if ( (tep_session_is_registered('customer_id') == false) || ($id != $customer_id) ) {
        return 0;
      }
    }

    $addresses_query = $DB->query("select count(*) as total from " . TABLE_ADDRESS_BOOK . " where customers_id = '" . (int)$id . "'");
    $addresses = $addresses_query->fetchAssoc();

    return $addresses['total'];
  }


  /**
   * \fn userDelete()
   * \brief delete customer current
   */
  public function userDelete(){
  	$DB=Database::getInstance();

  	$DB->query("DELETE FROM " . TABLE_CUSTOMERS . " WHERE customers_id = '" . $this->customer_id . "'");

  	$DB->query("DELETE FROM " . TABLE_CUSTOMERS_INFO . " WHERE customers_info_id = '" . $this->customer_id . "'");

  	$DB->query("DELETE FROM " . TABLE_ADDRESS_BOOK . " WHERE customers_id = '" . $this->customer_id . "'");

      /**
	@brief call method module account
      */
      $page=page::getInstance();
      $aca_account=$page->new_class('account',$this->customer_id);

      $aca_account->userDelete($this->customer_id);

  	return true;
  }

  /**
   * \fn address_label($customers_id, $address_id = 1, $html = false, $boln = '', $eoln = "\n")
   * \brief  Return a formatted address
   * TABLES: customers, address_book
   * @param $customers_id insteger
   * @param $address_id integer
   * @param $html boolean
   * @param $boln string/null
   * @param $eoln string
   */
  public static function address_label($customers_id, $address_id = 1, $html = false, $boln = '', $eoln = "\n") {
    $DB=Database::getInstance();

    $address_query = $DB->query("select entry_firstname as firstname, entry_lastname as lastname, entry_company as company, entry_street_address as street_address, entry_suburb as suburb, entry_city as city, entry_postcode as postcode, entry_state as state, entry_zone_id as zone_id, entry_country_id as country_id from " . TABLE_ADDRESS_BOOK . " where customers_id = '" . (int)$customers_id . "' and address_book_id = '" . (int)$address_id . "'");
    $address = $address_query->fetchAssoc();

    $format_id = tep_get_address_format_id($address['country_id']);

    return tep_address_format($format_id, $address, $html, $boln, $eoln);
  }

  /**
   * \fn userLoadAddress($address_id)
   * \brief load address for customer
   * 	Use current customer id
   * @param $address_id integer
   * @return array result sql | false
   */
  public function userLoadAddress($address_id){
    $check_address_query = tep_db_query("select * from " . TABLE_ADDRESS_BOOK . " where customers_id = '" . $this->customer_id . "' and address_book_id = '" . (int)$address_id . "'");

    if(tep_db_num_rows($check_address_query)) {
      return tep_db_fetch_array($check_address_query);
    }
    else return false;
  }

  /**
   * \fn userAddAddressBook($_post)
   * \brief add address book for shipping or payement
   * 		Use customer_id current
   * @param $_post array
   * @param $update int adressbook id
   * @return ressource sql / false
   */
  public function userAddAddressBook($_post, $update=false){

    if ( ($resul=$this->CheckDataAddressBook($_post)) && $resul !=false && is_array($resul)) {

      $db=$sql_data_array = array('customers_id' => $this->customer_id,
			      'entry_firstname' => $resul['firstname'],
			      'entry_lastname' => $resul['lastname'],
			      'entry_street_address' => $resul['street_address'],
			      'entry_postcode' => $resul['postcode'],
			      'entry_city' => $resul['city'],
			      'entry_country_id' => $resul['country']);

      if (_cst_bool('ACCOUNT_GENDER')) $sql_data_array['entry_gender'] = $resul['gender'];
      if (_cst_bool('ACCOUNT_COMPANY')){
	$sql_data_array['entry_company'] = $resul['company'];
	$sql_data_array['entry_company_tax_id'] = $resul['company_tax_id'];
      }
      if (_cst_bool('ACCOUNT_SUBURB')) $sql_data_array['entry_suburb'] = $resul['suburb'];
      if (_cst_bool('ACCOUNT_STATE')) {
	if (isset($resul['zone_id']) && $resul['zone_id'] > 0) {
	  $sql_data_array['entry_zone_id'] = @$resul['zone_id'];
	  $sql_data_array['entry_state'] = '';
	} else {
	  $sql_data_array['entry_zone_id'] = '0';
	  $sql_data_array['entry_state'] = @$resul['state'];
	}
      }

      if(!$update) $res=tep_db_perform(TABLE_ADDRESS_BOOK, $sql_data_array);
      elseif($update !=false) $res=tep_db_perform(TABLE_ADDRESS_BOOK, $sql_data_array, 'update', " address_book_id='".(int)$update."' ");
    }

    return (isset($res)? $res : false);
  }

  /**
    @fn function definePostMess($mode=0)
    @brief define method efor messagestack
    @param $mode 0: add 1: add_session
  */
  public static function definePostMess($mode=0){
    self::$methodeMessage = ((!$mode)? 'add' : 'add_session');
  }

  /**
    * \fn CleanKey($array, $new_array=array() )
    * \brief clean key in array result for customers; function recursive
    * @param $array array data
    * @param $new_array array data result, for recursive
    * @return array
    */
  private static function CleanKey($array, $new_array=array() ){

      $e=strlen('entry_');
      $c=strlen('customers_');
      foreach($array as $k=>$v){
	if(is_array($v)) $new_array = self::CleanKey($v, $new_array);
	elseif( substr($k,0,$e) =='entry_' ) $new_array[substr($k,$e)] =$v;
	elseif( substr($k,0,$c) =='customers_' ) $new_array[substr($k,$c)] =$v;
	else $new_array[$k] =$v;
      }

      return $new_array;
  }

  /**
  * \fn  checkPasswordProcess($current, $new, $confirmation, $mode=1)
  * \brief test and control pre-update password
  * the check process is:
  *  \li min lengt entry   password_current
  *  \li min lengt entry   password_new
  *  \li matching password_new  vs password_confirmation
  * @param $current string
  * @param $new string
  * @param $confirmation string
  * @param $mode integer (default:1)
  * @return boolean
  */
  private function checkPasswordProcess($current, $new, $confirmation, $mode=1){
    global $page;
    $DB=Database::getInstance();
    $error = false;

    switch ($mode) {
      case 2:
	if (strlen($new) < ENTRY_PASSWORD_MIN_LENGTH) {
	  $error = true;

	  self::PassmessageStack('account_password', ENTRY_PASSWORD_NEW_ERROR);
	}

	if ($error == false)return true;
	else return false;
      break;

      case 1:
      default:
/*
	if (strlen($current) < ENTRY_PASSWORD_MIN_LENGTH) {
	  $error = true;

	  self::PassmessageStack('account_password', ENTRY_PASSWORD_CURRENT_ERROR);
	}*/
	if ( ($resul=$this->CheckDataPassword(array('password'=>$new, 'confirmation'=>$confirmation))) && $resul !=false && is_array($resul)){
	  $check_customer_query = tep_db_query("select customers_password from " . TABLE_CUSTOMERS . " where customers_id = '" . $this->customer_id . "'");
	  $check_customer = tep_db_fetch_array($check_customer_query);

	  if (tep_validate_password($current, $check_customer['customers_password'])) {
	    self::PassmessageStack('account', SUCCESS_PASSWORD_UPDATED, 'success');
	    return true;
	  }
	  else {
	    self::PassmessageStack('account_password', ERROR_CURRENT_PASSWORD_NOT_MATCHING);
	    return false;
	  }
      }
    }
  }


  /**
    @fn
    @brief Internal function for post messageStack
  */
  private static function PassmessageStack($class, $mess, $type='error'){
    global $page;
    $methode=self::$methodeMessage;
    $page->messageStack->$methode($class, $mess, $type);
  }

  /**
    @fn CheckData($post)
    @brief check data post
    @param $post array $_POST
      check array(password, confirmation);
  */
  private function CheckDataPassword($_post){
    global $page;
    $sortie = array();
    $error=false;

    $sortie['password'] = tep_db_prepare_input($_post['password']);
    $sortie['confirmation'] = tep_db_prepare_input($_post['confirmation']);


    if (strlen($sortie['password']) < ENTRY_PASSWORD_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack('account_password', ENTRY_PASSWORD_ERROR);
    }
    elseif (strlen($sortie['confirmation']) < ENTRY_PASSWORD_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack('account_password', ENTRY_PASSWORD_ERROR);
    }
    elseif ($sortie['password'] != $sortie['confirmation']) {
      $error = true;
      self::PassmessageStack('confirmation', ENTRY_PASSWORD_ERROR_NOT_MATCHING);
    }

    return (!$error) ? $sortie : false;
  }


  /**
    @fn CheckData($post)
    @brief check data post
    @param $post array $_POST
  */
  public function CheckDataAddressBook($_post,$ErrorClass=''){
    global $page;
    $sortie = array();
    $DB=Database::getInstance();
    $error = false;

    if ( ($resul=$this->CheckDataName($_POST, 'addressbook')) && $resul !=false && is_array($resul)) $sortie=$resul;
    else $error = true;

    if(_cst_bool('ACCOUNT_COMPANY')) {
      $sortie['company'] = (isset($_post['company']) ? tep_db_prepare_input($_post['company']) : '');
      $sortie['company_tax_id'] =(isset($_post['company_tax_id']) ?  tep_db_prepare_input($_post['company_tax_id']): '');
    }

    $sortie['street_address'] = (isset($_post['street_address']) ? tep_db_prepare_input($_post['street_address']): '');
    if (_cst_bool('ACCOUNT_SUBURB')) $sortie['suburb'] = (isset($_post['suburb']) ? tep_db_prepare_input($_post['suburb']): '');
    $sortie['postcode'] = (isset($_post['postcode']) ? tep_db_prepare_input($_post['postcode']): '');
    $sortie['city'] = (isset($_post['city']) ? tep_db_prepare_input($_post['city']): '');

    $sortie['country'] =(isset($_post['country']) ?   (_cst_bool('ACCOUNT_COUNTRY')? tep_db_prepare_input($_post['country']) : STORE_COUNTRY ) : '');

    if (_cst_bool('ACCOUNT_STATE')) {
      $sortie['state'] = tep_db_prepare_input($_post['state']);
      if (isset($_post['zone_id']))  $sortie['zone_id'] = tep_db_prepare_input($_post['zone_id']);
      else   $sortie['zone_id'] = false;
    }


    if (strlen($sortie['street_address']) < ENTRY_STREET_ADDRESS_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack( (!empty($ErrorClass)?$ErrorClass:'street_address'), ENTRY_STREET_ADDRESS_ERROR);
    }

    if (strlen($sortie['postcode']) < ENTRY_POSTCODE_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'postcode'), ENTRY_POST_CODE_ERROR);
    }

    if (strlen($sortie['city']) < ENTRY_CITY_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'city'), ENTRY_CITY_ERROR);
    }

    if (!isset($sortie['country']) || is_numeric($sortie['country']) == false) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'country'), ENTRY_COUNTRY_ERROR);
    }

    if (_cst_bool('ACCOUNT_STATE') && isset($sortie['country'])) {
      $zone_id = 0;
      $check_query = tep_db_query("select count(*) as total from " . TABLE_ZONES . " where zone_country_id = '" . (int)$sortie['country'] . "'");
      $check = tep_db_fetch_array($check_query);
      $entry_state_has_zones = ($check['total'] > 0);
      if ($entry_state_has_zones == true) {
	$zone_query = tep_db_query("select distinct zone_id from " . TABLE_ZONES . " where zone_country_id = '" . (int)$sortie['country'] . "' and (zone_name like '" . tep_db_input($sortie['state']) . "%' or zone_code like '%" . tep_db_input($sortie['state']) . "%')");
	if (tep_db_num_rows($zone_query) == 1) {
	  $zone = tep_db_fetch_array($zone_query);
	  $zone_id = $zone['zone_id'];
	} else {
	  $error = true;
	  self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'state'), ENTRY_STATE_ERROR_SELECT);
	}
      } else {
	if (strlen($sortie['state']) < ENTRY_STATE_MIN_LENGTH) {
	  $error = true;
	  self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'state'), ENTRY_STATE_ERROR);
	}
      }
    }

    return (!$error) ? $sortie : false;
  }


  /**
    @fn CheckData($post)
    @brief check data post, this is information for name, lastane and gender
    @param $post array $_POST
  */
  private function CheckDataName($_post,$ErrorClass=''){
    $sortie = array();
    $error = false;

    if (_cst_bool('ACCOUNT_GENDER')) {
      if (isset($_post['gender'])) {
	$sortie['gender'] = tep_db_prepare_input($_post['gender']);
      } else {
	$sortie['gender'] = false;
      }
    }

    $sortie['firstname'] = tep_db_prepare_input($_post['firstname']);
    $sortie['lastname'] = tep_db_prepare_input($_post['lastname']);

    if (_cst_bool('ACCOUNT_GENDER') && !in_array($sortie['gender'],array('m','f','l')) ) {
      $error = true;
      self::PassmessageStack('gender', ENTRY_GENDER_ERROR);
    }

    if (strlen($sortie['firstname']) < ENTRY_FIRST_NAME_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'firstname'), ENTRY_FIRST_NAME_ERROR);
    }

    if (strlen($sortie['lastname']) < ENTRY_LAST_NAME_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'lastname'), ENTRY_LAST_NAME_ERROR);
    }

    return (!$error) ? $sortie : false;
  }

  /**
    @fn CheckData($post)
    @brief check data post, this is a master save for customers
    @param $post array $_POST
    @param
    @param insert = true
  */
  private function CheckData($_post,$ErrorClass='',$insert=true){
    global $page;
    $DB=Database::getInstance();
    $sortie = array();
    $error = false;

    if ( ($resul=$this->CheckDataName($_POST, 'addressbook')) && $resul !=false && is_array($resul)) $sortie=$resul;
    else $error = true;

    if (_cst_bool('ACCOUNT_DOB')) $sortie['dob'] = tep_db_prepare_input($_post['dob']);
    $sortie['email_address'] = tep_db_prepare_input($_post['email_address']);

    $sortie['telephone'] = (isset($_post['telephone']) ? tep_db_prepare_input($_post['telephone']) :'');

    $sortie['fax'] = (_cst_bool('ACCOUNT_FAXNUM')) ? tep_db_prepare_input($_post['fax']) : '';
    $sortie['newsletter'] = (isset($_post['newsletter'])) ? tep_db_prepare_input($_post['newsletter']) : false ;

    if (_cst_bool('ACCOUNT_DOB'))
      if (checkdate(substr(tep_date_raw($sortie['dob']), 4, 2), substr(tep_date_raw($sortie['dob']), 6, 2), substr(tep_date_raw($sortie['dob']), 0, 4)) == false) {
	$error = true;
	self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'dob'), ENTRY_DATE_OF_BIRTH_ERROR);
      }


    if (strlen($sortie['email_address']) < ENTRY_EMAIL_ADDRESS_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'email_address'), ENTRY_EMAIL_ADDRESS_ERROR);

    } elseif (tep_validate_email($sortie['email_address']) == false) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'email_address'), ENTRY_EMAIL_ADDRESS_CHECK_ERROR);

    }
    elseif($insert)  {
      $check_email_query = tep_db_query("select count(*) as total from " . TABLE_CUSTOMERS . " where customers_email_address = '" . tep_db_input($sortie['email_address']) . "'");
      $check_email = tep_db_fetch_array($check_email_query);
      if ($check_email['total'] > 0) {
	$error = true;
	self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'email_address'), ENTRY_EMAIL_ADDRESS_ERROR_EXISTS);
      }
    }


    if (isset($_post['telephone']) && strlen($sortie['telephone']) < ENTRY_TELEPHONE_MIN_LENGTH) {
      $error = true;
      self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'telephone'), ENTRY_TELEPHONE_NUMBER_ERROR);
    }

//     if ( ($resul=$this->CheckDataPassword($_post)) && $resul !=false && is_array($resul)) $sortie=array_merge($sortie,$resul);
//     else $error = true;

    //BOF Customers extra fields
    $extra_fields_query = tep_db_query("select ce.fields_id, ce.fields_input_type, ce.fields_required_status, cei.fields_name, ce.fields_status, ce.fields_input_type, ce.fields_size from " . TABLE_EXTRA_FIELDS . " ce, " . TABLE_EXTRA_FIELDS_INFO . " cei where ce.fields_status=1 and ce.fields_admin=0 and cei.fields_id=ce.fields_id  and cei.languages_id =" . $this->languages_id);
    while($extra_fields = tep_db_fetch_array($extra_fields_query)){
      if(strlen($_post['fields_' . $extra_fields['fields_id']])<$extra_fields['fields_size']){
	$error = true;
	self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'extra_fields'), sprintf(ENTRY_EXTRA_FIELDS_LENG_ERROR,$extra_fields['fields_name'],$extra_fields['fields_size']));
      }
      elseif($extra_fields['fields_required_status'] && empty($_post['fields_' . $extra_fields['fields_id']]) ){
	$error = true;
	self::PassmessageStack((!empty($ErrorClass)?$ErrorClass:'extra_fields'), sprintf(ENTRY_EXTRA_FIELDS_REQUIRED_ERROR,$extra_fields['fields_name']));
      }
      else $sortie['fields_' . $extra_fields['fields_id']]=tep_db_prepare_input($_post['fields_' . $extra_fields['fields_id']]);
    }

    return (!$error) ? $sortie : false;
  }


  /**
    @fn initSession($user)
    @brief Session creat / restore  for current user
    @param $user object | array
  */
  static public function initSession($user){
    global $cart;

    $DB=Database::getInstance();
    if (_cst_bool('SESSION_RECREATE'))  tep_session_recreate();

    if(!is_object($user)) $user=new objectInfo($user);

    $_SESSION['customer_id']=$customer_id=(isset($user->customers_id)?$user->customers_id : $user->id );
    $_SESSION['customer_first_name']=$customer_first_name =(isset($user->customers_firstname)? $user->customers_firstname : $user->firstname);
    $_SESSION['customer_default_address_id']=$customer_default_address_id = (isset($user->customers_default_address_id)? $user->customers_default_address_id : $user->address_book_id);
    $customers_group_ra = (isset($user->customers_group_ra)? $user->customers_group_ra: $user->group_ra);
    $_SESSION['sppc_customer_group_id']=$sppc_customer_group_id = (isset($user->customers_group_id)? $user->customers_group_id: 0 );
    $customers_specific_taxes_exempt = (isset($user->customers_specific_taxes_exempt)? $user->customers_specific_taxes_exempt : '' );

    $check_country_query = $DB->query($sql="select entry_country_id, entry_zone_id from " . TABLE_ADDRESS_BOOK . " where customers_id = '" . (int)$customer_id . "' and address_book_id = '" . (int)$customer_default_address_id. "'");
    $check_country = $check_country_query->fetchAssoc();

    $_SESSION['customer_country_id']=$customer_country_id = $check_country['entry_country_id'];
    if (_cst_bool('ACCOUNT_STATE'))
      $_SESSION['customer_zone_id']=$customer_zone_id = $check_country['entry_zone_id'];

    $check_customer_group_tax = tep_db_query($sql="select customers_group_show_tax, customers_group_tax_exempt, group_specific_taxes_exempt, group_discount from " . TABLE_CUSTOMERS_GROUPS . " where customers_group_id = '" .(int)$sppc_customer_group_id . "'");
    $customer_group_tax = tep_db_fetch_array($check_customer_group_tax);

    /// Grp confirmed
    if($customers_group_ra ===1) {
      $_SESSION['sppc_customer_group_show_tax']=$sppc_customer_group_show_tax = (int)$customer_group_tax['customers_group_show_tax'];
      $_SESSION['sppc_customer_group_tax_exempt']=$sppc_customer_group_tax_exempt = (int)$customer_group_tax['customers_group_tax_exempt'];
      /*$_SESSION['group_specific_taxes_exempt']=*/$group_specific_taxes_exempt = $customer_group_tax['group_specific_taxes_exempt'];
      $_SESSION['sppc_group_discount']=$sppc_group_discount = $customer_group_tax['group_discount'];
      if (tep_not_null($customers_specific_taxes_exempt)) $sppc_customer_specific_taxes_exempt = $customers_specific_taxes_exempt;
      elseif (tep_not_null($group_specific_taxes_exempt))  $sppc_customer_specific_taxes_exempt = $group_specific_taxes_exempt;
      else  $sppc_customer_specific_taxes_exempt = '';
    }
    else {
      $_SESSION['sppc_customer_group_show_tax']=$sppc_customer_group_show_tax = 1;
      $_SESSION['sppc_customer_group_tax_exempt']=$sppc_customer_group_tax_exempt = '';
      $group_specific_taxes_exempt = '';
      if (tep_not_null($customers_specific_taxes_exempt)) $sppc_customer_specific_taxes_exempt = $customers_specific_taxes_exempt;
      elseif (tep_not_null($group_specific_taxes_exempt))  $sppc_customer_specific_taxes_exempt = $group_specific_taxes_exempt;
      else  $sppc_customer_specific_taxes_exempt = '';
    }

    if (tep_not_null($sppc_customer_specific_taxes_exempt)) $_SESSION['sppc_customer_specific_taxes_exempt']= $sppc_customer_specific_taxes_exempt;


    // add in session last logon
    $cu=self::$_instance;
    $cu->detail_long_cust();
    $_SESSION['last_logon'] = $cu->customer['customers_info_date_of_last_logon'];

    // restore cart contents
    $cart->restore_contents();


    // update logon user
    $DB->query("UPDATE " . TABLE_CUSTOMERS_INFO . " SET customers_info_date_of_last_logon=NOW() , customers_info_number_of_logons = customers_info_number_of_logons + 1 WHERE customers_info_id 	='".(int)$customer_id."' ");
  }

  /**
    @fn closeSession()
    @brief close and destruct session
  */
  static public function closeSession(){
    global $cart;
    tep_session_unregister('customer_id');
    tep_session_unregister('customer_default_address_id');
    tep_session_unregister('customer_first_name');
    tep_session_unregister('customer_country_id');
    tep_session_unregister('customer_zone_id');
    tep_session_unregister('comments');
    tep_session_unregister('billto');
    tep_session_unregister('sendto');
    tep_session_unregister('shipping');
    tep_session_unregister('payment');
    tep_session_unregister('coupon');
    tep_session_unregister('sppc_customer_group_id');
    tep_session_unregister('sppc_customer_group_show_tax');
    tep_session_unregister('sppc_customer_group_tax_exempt');
    tep_session_unregister('sppc_customer_specific_taxes_exempt');
    tep_session_unregister('country_id');
    tep_session_unregister('state_id');
    $cart->reset();
  }


  /**
    @fn creatValidHash()
    @brief creat valid hash, for account actived by email confirm for current customers
    @return hash string
  */
  public function creatValidHash(){
    $DB=Database::getInstance();

    $date = date('Y-m-d H:i:s');

    $DB->query("UPDATE " . TABLE_CUSTOMERS_INFO . " SET customers_info_date_account_last_modified='".$date."' WHERE customers_info_id 	='".(int)$this->customer['customers_id']."' ");

    return md5($date.strtoupper($this->customer['customers_firstname'].$this->customer['customers_lastname']));
  }

  /**
    @fn checkHash($hash)
    @brief check hash for valid account for current customers and up customers status
    @param hash string
    @return boolean true/false
  */
  public function checkHash($hash){
    $this->detail_long_cust();

    if( md5($this->customer['customers_info_date_account_last_modified'].strtoupper($this->customer['customers_firstname'].$this->customer['customers_lastname'])) == $hash) {
      $DB=Database::getInstance();
      $DB->query("UPDATE " . TABLE_CUSTOMERS . " SET customers_status='1' WHERE customers_id='".(int)$this->customer['customers_id']."' ");

      return true;
    }

    return false;
  }

  /**
    @fn search($key, $value)
    @brief search in db for key and value in tale master customers
    @param key col in db
    @param value for col
    @return customers_id integer
  */
  static public function search($key, $value){
    $value=tep_db_prepare_input($value);
    $check_query = tep_db_query("select * from " . TABLE_CUSTOMERS . " where ".$key." = '" . tep_db_input($value) . "' LIMIT 1");

    if(!(bool)tep_db_num_rows($check_query)) return false;

    $_query=$check_query->fetchAssoc();

    return (!isset($_query[$key])?false: $_query['customers_id'] );
  }
}


/**
 * \example
 *
 * Print array or object return by methode, after CleanKey
 *
 *
(
    [firstname] => test
    [lastname] => test
    [email_address] => xxxxx@xxxxxxx.com
    [telephone] => 0000000000000000
    [fax] =>
    [newsletter] =>
    [password] => e40ca7754e71fbb5243584efb29faf61:97
    [group_ra] => 1
    [gender] => m
    [id] => 30
    [street_address] => lalkskas aks aks
    [postcode] => 28000
    [city] => xxxxxxxxxxxxxx
    [country_id] => 73
    [company] =>
    [company_tax_id] =>
    [suburb] => xxxxxxxxxx
    [address_book_id] => 30
)

 */
?>