<?php
/**
  Clase SuperUsuario
 */

class SuperUsuario extends Objeto{
	//Primero voy a declarar variables estáticas que vamos a utilizar
	private static $loggedUser = NULL;
	public static $campos_tabla = array();
	public static $alias = '';
	public static $nombreTabla = '';
	public static $camposSelect = '';
	public static $whereSelect = '';
	public static $publicFieldList = array();
	
	
    public $codigo = '';
    public $codigo_sinlib = 0;
    public $nombre_comercial = '';
    public $nombre_legal = '';
    public $email = '';
    public $direcciones = array();
    public $direccion_principal = 0; //Este es el índice del array de direcciones que apunta a la predeterminada
    public $direccion = '';
    public $cod_postal = '';
    public $localidad = '';
    public $provincia = '';
    public $pais = '';
    public $telefono = '';
    public $telefono2 = '';
    public $cif = '';
    public $tarifa = 0;
    public $no_precio_especial = 0;
    public $precios_escalados = 0;
    public $resta_iva = 0;
    public $tarifa_dto_pap = 0;
    public $descuento_papeleria = 0;
    public $descuento_libros = 0;
    public $descuento_texto = 0;
    public $limpiar_cesta = 0;
    public $cod_descuento = 0;
    public $direc_predeterminada = 0; //Este es el código de la dirección predeterminada
    public $escalados_tafifas = 0;
    public $vender_costo = false;
	public $vender_precio_medio_costo = false;
	public $vender_precio_costo_con_descuento = false;
    public $fecha_nacimiento = '';
    public $version_sinli = 0;
    public $administrador = false;
    public $factura_sin_detalle = false;
    public $favoritos = array();
    public $tipo_cliente = 0;
    public $tipo_envio = 0;
	public $ruta_importe_minimo = 0;
    public $ruta_gastos_envio = 0;
	//30/Enero/2019 ==> Añadimos el password:
	public $password = '';
	public $reestablecer_password = '';
	//04/Febrero/2019 ==> El código de confirmación de registro hay que pasarlo también:
	public $codigo_confirmacion = 0;
	//21/Marzo/2019 ==> Añadimos el hash de google (está encruptado)
	public $google_user = false;
	//07/Mayo/2019 ==> Indicamos aquí si es un usuario de facebook
	public $facebook_user = false;
	private $flag_utf8 = false;
	//09/Mayo/2019 ==> Hemos encontrado campos que están en la BD pero aquí no se cargan, por ahora voy añadiendo sólo los que necesite:
	public $comunicados = false;
	//02/Febrero/2020 ==> El usuario tiene tarifas múltiples y no estaba aquí definido:
	public $tarifas_multiples = 255;
	

	//La funcion de get nombre tabla la dejo así por ahora porque del usuario solo vamos a sacar los datos del mismo.
	//más adelante sacaremos las tablas asociadas
	public static function getNombreTabla($soloPrincipal = NULL){
		//Incluimos los globals para coger el valor del idioma:
		static::$nombreTabla = strtolower(get_called_class());
		static::getTablaRelacionada();
		//Ahora vamos a componer el nombre de la tabla teniendo en cuenta si es sólo principal, si no o si es todo (NULL)
		$consulta = ' ';
		if ($soloPrincipal || $soloPrincipal === NULL){
			$consulta .= static::$nombreTabla . ' as `' .  static::getAlias() . '` ';
		}
		//Sólo asignamos el nombre de la tabla si no nos piden más parámetros
		if ($soloPrincipal == NULL){
			static::$nombreTabla = $consulta;
		}
		return($consulta);
	}

	public static function getWhereTabla(){
		$argumentos = func_get_args();
		$codigo = isset($argumentos[0]) ? $argumentos[0] : NULL;
		$email = isset($argumentos[1]) ? $argumentos[1] : NULL;
		$limitar = isset($argumentos[2]) ? $argumentos[2] : true;
		include('comunes/globals.php');
		if ($codigo != NULL){
			static::$whereSelect = ' `' . static::getAlias() . '`.`codigo` = \'' . $codigo . '\'';
		}
		if ($email != NULL){
			static::$whereSelect = ' `' . static::getAlias() . '`.`email` = \'' . $email . '\'';
		}
		if ($limitar){
			static::$whereSelect .= ' LIMIT 1 ';
		}
		return(static::$whereSelect);
	}

    function __construct($codigo) {
		//08/Mayo/2019 ==> Hay que inicualizar los campos en la lista de campos de la tabla sólo si no está inicializada:
		if (empty(static::$publicFieldList)){
			static::initPublicFields();
		}
        //include('comunes/globals.php');
		//Adaptamos el objeto usuario a los nuevos tiempos:
		if ( is_array($codigo) || is_object($codigo) ){	//	SI no nos pasan el código vamos a pasar la variable por el "opciones de objeto" para que lo parsee:
			$opciones = new ObOptions($codigo);
		}else{
			$opciones = new ObOptions(
				array(
					'codigo' => $codigo
				)
			);
		}
		//Vamos a controlar que no se nos haya pasado un opciones widget
		$codigo = $opciones->getDefaultValue('codigo', '');
		$filaUsuario = $opciones->getDefaultValue('filaUsuario', NULL);
		$fila = NULL;
		//Si no hemos recibido fila usuario, vamos a hacer la select:
		if ($filaUsuario == NULL){
			//echo("Vamos a cargar el usuario");
			/*
			$sentencia_sql = 'SELECT `codigo`, `codigo_sinlib`, `nombre_comercial`, `nombre_legal`, `email`, `direccion`, `cod_postal`, `localidad`, `provincia`, `telefono`, `telefono2`, `cif`, `pais`, `no_precio_especial`, `tarifa`, `precios_escalados`, `resta_iva`, `tarifa_dto_pap`, `descuento_papeleria`, `descuento_libros`, `descuento_texto`, `limpiar_cesta`, `cod_descuento`, `tarifas_multiples`, `direc_predeterminada`, `escalados-tarifa`, `vender-costo`, `fecha_nacimiento`, `version_sinli`, `factura_sin_detalle`,`tipo_cliente`, `tipo_envio`
			 FROM cliente WHERE codigo = ' . $codigo;
			 */
			$sentencia_sql = 'SELECT ' . static::getCampos() . '
								FROM ' . static::getNombreTabla() . '
								WHERE ' . static::getWhereTabla($codigo);
			$bd = new BaseDatos();
			if ($bd->isConectado()){
				$bd->setConsultaSQL($sentencia_sql);
				$fila = $bd->getFila();
			}
			//echo("-----------$sentencia_sql<br />\n");
		}else{
			$fila = $filaUsuario;
		}
		if ($fila != NULL) {
			$this->extractData($fila);
		}
	}

	public function extractData($fila){
		$this->codigo = $fila[static::getAlias() . '_codigo'];
		$this->codigo_sinlib = $fila[static::getAlias() . '_codigo_sinlib'];
		$this->nombre_comercial = $fila[static::getAlias() . '_nombre_comercial'];
		$this->nombre_legal = $fila[static::getAlias() . '_nombre_legal'];
		$this->email = $fila[static::getAlias() . '_email'];
		//Vamos a crear un objeto direcciones para añadir la dirección del cliente
		$this->direccion = $fila[static::getAlias() . '_direccion'];
		$this->cod_postal = $fila[static::getAlias() . '_cod_postal'];
		$this->localidad = $fila[static::getAlias() . '_localidad'];
		$this->provincia = $fila[static::getAlias() . '_provincia'];
		$this->telefono = $fila[static::getAlias() . '_telefono'];
		$this->pais = $fila[static::getAlias() . '_pais'];
		//$this->direcciones[0] = new Direcciones($this->codigo, 0, $this->direccion, $this->cod_postal, $this->localidad, $this->provincia, $this->telefono, $this->nombre_legal, $this->pais);
		$this->telefono2 = $fila[static::getAlias() . '_telefono2'];
		$this->cif = $fila[static::getAlias() . '_cif'];
		$this->tarifa = $fila[static::getAlias() . '_tarifa'];
		$this->no_precio_especial = $fila[static::getAlias() . '_no_precio_especial'];
		$this->precios_escalados = $fila[static::getAlias() . '_precios_escalados'];
		$this->resta_iva = $fila[static::getAlias() . '_resta_iva'];
		$this->tarifa_dto_pap = $fila[static::getAlias() . '_tarifa_dto_pap'];
		$this->descuento_papeleria = $fila[static::getAlias() . '_descuento_papeleria'];
		$this->descuento_libros = $fila[static::getAlias() . '_descuento_libros'];
		$this->descuento_texto = $fila[static::getAlias() . '_descuento_texto'];
		$this->limpiar_cesta = $fila[static::getAlias() . '_limpiar_cesta'];
		$this->cod_descuento = $fila[static::getAlias() . '_cod_descuento'];
		$this->direc_predeterminada = $fila[static::getAlias() . '_direc_predeterminada'];
		$this->escalados_tafifas = $fila[static::getAlias() . '_escalados-tarifa'];
		$this->vender_costo = ($this->getProp($fila, 'vender-costo')) ? true : false;
		$this->vender_precio_medio_costo = ($this->getProp($fila, 'vender_precio_medio_costo')) ? true : false;
		$this->vender_precio_costo_con_descuento = ($this->getProp($fila, 'vender_precio_costo_con_descuento')) ? true : false;
		$this->fecha_nacimiento = $fila[static::getAlias() . '_fecha_nacimiento'];
		$this->version_sinli = $fila[static::getAlias() . '_version_sinli'];
		$this->factura_sin_detalle = ( $fila[static::getAlias() . '_factura_sin_detalle'] == 0) ? false : true;
		$this->tipo_cliente = $fila[static::getAlias() . '_tipo_cliente'];
		$this->tipo_envio = $fila[static::getAlias() . '_tipo_envio'];
		$this->ruta_importe_minimo = $fila[static::getAlias() . '_ruta_importe_minimo'];
		$this->ruta_gastos_envio = $fila[static::getAlias() . '_ruta_gastos_envio'];
		$this->password = $this->getProp($fila, 'password');
		$this->reestablecer_password = $this->getProp($fila, 'reestablecer_password');
		$this->codigo_confirmacion = $this->getProp($fila, 'codigo_confirmacion');
		$this->google_user = ($this->getProp($fila, 'google_user')) ? true : false;
		$this->facebook_user = ($this->getProp($fila, 'fbId') != '') ? true : false;
		$this->comunicados = ($this->getProp($fila, 'comunicados')) ? true : false;
		$this->tarifas_multiples = $this->getProp($fila, 'tarifas_multiples');

		//Vamos a comprobar rápidamente si el usuario es administrador ==> Esto lo podemos optimizar en la consulta inicial
		$sentencia_sql = 'SELECT codigo FROM administrador WHERE email = \'' . $this->email . '\';';
		//echo($sentencia_sql);
		$bd = new BaseDatos();
		if ($bd->isConectado()){
			$bd->setConsultaSQL($sentencia_sql);
			$fila = $bd->getFila();
			if ($fila["codigo"] != '') {
				$this->administrador = true;
			}
		}

		//Pedro 31/Agosto/2020 ==> las direcciones se gestionan desde una función:
		$this->getAdress();
		/*
		//Pedro 12/Abril/2019 ==> Ahora las direcciones se cargan desde la clase de direcciones
		$this->direcciones = Direcciones::getUserDirs($this->codigo);

		//si no tenemos direcciones, hay que crear (si procede) la direccion de este usuario:
		if (count($this->direcciones) == 0){
			//A crear la direccion:
			if ( trim($this->direccion . $this->nombre_comercial . $this->nombre_legal . $this->cod_postal . $this->localidad . $this->provincia . $this->pais . $this->telefono) != ''){
				$opciones = array(
					'cliente' => $this->codigo,
					'direccion' => $this->direccion,
					'nombre' => ($this->nombre_comercial != '') ? $this->nombre_comercial : $this->nombre_legal,
					'cod_postal' => $this->cod_postal,
					'localidad' => $this->localidad,
					'provincia' => $this->provincia,
					'pais' => $this->pais,
					'telefono' => $this->telefono
				);
				$this->direcciones[] = $direccion = new Direcciones($opciones);
				//Si el usuario tiene código la guardamos:
				if ($this->codigo != ''){
					//FileSystem::log('Guardamos dirección desde el  usuario');
					$direccion->save();
				}
			}
		}
		//Pedro 31/Agosto/2020 ==> Tenemos que indicar en el array cual es la dirección principal
		FileSystem::log('-------------------------------------------');
		FileSystem::log('Llamada desde Usuario');
		$this->direccion_principal = $this->getAdressIndex($this->direc_predeterminada);
		*/
		//Cargamos los favoritos. No se inicializan los objetos artículos por optimizar la velocidad
		$sentencia_sql = 'SELECT articulo.codigo FROM articulo, favoritos WHERE favoritos.articulo = articulo.codigo AND favoritos.cliente = \'' . $this->codigo . '\' ORDER BY favoritos.fecha_alta ASC';
		if ($bd->isConectado()){
			$bd->setConsultaSQL($sentencia_sql);
			while ($fila = $bd->getFila()){
				$this->favoritos[] = $fila["codigo"];
			}
		}

	}

	public static function initPublicFields(){
		//En esta función se deben de poner los nombres de los campos en la tabla
		//Sólo pondremos aquellos campos a los que les vamos a dar acceso al usuario
		$publicFieldList = array();
		$publicFieldList[] = 'codigo';
		$publicFieldList[] = 'codigo_sinlib';
		$publicFieldList[] = 'nombre_comercial';
		$publicFieldList[] = 'nombre_legal';
		$publicFieldList[] = 'direccion';
		$publicFieldList[] = 'cod_postal';
		$publicFieldList[] = 'localidad';
		$publicFieldList[] = 'provincia';
		$publicFieldList[] = 'telefono';
		$publicFieldList[] = 'cif';
		$publicFieldList[] = 'pais';
		$publicFieldList[] = 'fecha_ultima_visita';
		$publicFieldList[] = 'hora_ultima_visita';
		$publicFieldList[] = 'pendiente_sinlib';
		$publicFieldList[] = 'telefono2';
		$publicFieldList[] = 'modificado';
		$publicFieldList[] = 'recibir_novedades';
		$publicFieldList[] = 'zona';
		$publicFieldList[] = 'direc_predeterminada';
		$publicFieldList[] = 'fecha_nacimiento';
		$publicFieldList[] = 'version_sinli';
		$publicFieldList[] = 'tipo_envio';
		$publicFieldList[] = 'comunicados';
		$publicFieldList[] = 'tarifas_multiples';
		static::$publicFieldList = $publicFieldList;
	}
    function __destruct() {
        //Limpiamos los hijos que tenga asociados el escaparate
        for ($i = 0; $i < count($this->direcciones); $i++) {
            unset($this->direcciones[$i]);
        }
    }

	public function isRegistered(){
		return( ($this->codigo != '') ? true : false);
	}

	public function getCurrentDirection(){
		//Pedro 15/Abril/2019 ==> Esta función está sobre escrita para que los usuarios sin registro cojan la dirección de la cesta:
		$retorno = NULL;
		//Pedro 18/Junio/2020 ==> No se está cogiendo la dirección de la cesta aunque lo ponga arriba así que la vamos a coger aquí:
		if ($this->codigo == ''){
			$cesta = CabeceraCesta::getCart();
			$retorno = $cesta->getCurrentShippingDestination();
		}else if ($this->direccion_principal == 0){
			if (count($this->direcciones) > 0){
				$retorno = $this->direcciones[0];
			}else{
				$opciones = array(
					'cliente' => $this->codigo,
					'direccion' => $this->direccion,
					'nombre' => ($this->nombre_comercial != '') ? $this->nombre_comercial : $this->nombre_legal,
					'cod_postal' => $this->cod_postal,
					'localidad' => $this->localidad,
					'provincia' => $this->provincia,
					'pais' => $this->pais,
					'telefono' => $this->telefono
				);
				$retorno = new Direcciones($opciones);
			}
		}else{
			//Pedro 31/Agosto/2020 ==> La dirección principal es un índice, aquí se estába tratando como un código:
			if (isset($this->direcciones[$this->direccion_principal])){
				$retorno = $this->direcciones[$this->direccion_principal];
			}
		}

		return($retorno);
	}

	public function limpiarCesta(){
		return(static::setLimpiarCesta($this->codigo));
	}


	public static function setLimpiarCesta($cod_usuario){
		//Vamos a dar el pedido por finalizado.
		$retorno = false;
		$sentencia_sql = 'UPDATE ' . static::getNombreTablaSinAlias() . ' SET `limpiar_cesta` = 1 WHERE `codigo` = \'' . $cod_usuario . '\'; ';
		$bd = new BaseDatos();
		$bd->setConsultaSQL($sentencia_sql);
		if ($bd->getNumeroFilas() > 0){
			$retorno = true;
		}
		return($retorno);
	}

    public function getJSON() {
        $prop = get_object_vars($this);
        $resp = '{ ';
        foreach ($prop as $key => $value) {
            if (!is_object($value)) {
                $value = (string) $value;
                if ($this->flag_utf8) {
                    $resp .= '"' . $key . '":' . json_encode(htmlspecialchars_decode($value)) . ',';
                } else {
                    $resp .= '"' . $key . '":' . json_encode(htmlspecialchars_decode(utf8_encode($value))) . ',';
                }
            } else {
                $ejecutarJson = true;
                if (method_exists(get_class($value), 'getJSON')) {
                    $ejecutarJson = false;
                }
                if (!$ejecutarJson) {
                    $resp .= '"' . $key . '":' . $value->getJSON() . ',';
                } else {
                    $resp .= '"' . $key . '":' . json_encode($value) . ',';
                }
            }
        }
        $resp = substr($resp, 0, -1) . "}";
        return $resp;
    }

	//Logueado nos devuelve si un usuario está logueado o no(aunq sea sin registro) y devuelve el usuario
	public static function logueado(){
		$retorno = NULL;
		//Esta función nos devolverá el objeto usuario si este está logueado
		//Lo primero es ver si tenemos el objeto "loggedUser" en esta clase (es estático)
		if (self::$loggedUser != NULL){
			$retorno = self::$loggedUser;
		}else{
			//Vamos a cogerlo de la sesión:
			$codigoUsuario = Sesion::get('cod_cliente_web', '');
			if ($codigoUsuario != ''){
				$usuario = new Usuario(new OpcionesWidget(array('codigo' => $codigoUsuario)));
				if ($usuario->isRegistered()){
					$retorno = self::$loggedUser = $usuario;
				}
			}else{
				//Vamos a ver si tenemos un usuario sin registro en la sesión:
				$usuarioSinRegistro = Sesion::get('usuarioSinRegistro', NULL);
				if ($usuarioSinRegistro != NULL){
					$retorno = self::$loggedUser = $usuarioSinRegistro;
				}
			}
		}
		return($retorno);
	}
	
	//13/Mayo/2019 ==> Esta función indica si un usuario REGISTRADO está logueado o no
	public static function isLogged(){
		$return = false;
		$usuario = Usuario::logueado();
		if ($usuario != NULL){
			if ($usuario->codigo != ''){
				$return = true;
			}
		}
		return($return);
	}
	
	//Creado por Pedro el 28/Enero/2019 ==> Comprobamos si el cliente existe por su email
	public static function exists($email){
		$retorno = false;
		if (isset($email)){
			if (trim($email) != ''){
				$sentencia_sql = 'SELECT ' . static::getCampos() . '
								FROM ' . static::getNombreTabla() . '
								WHERE ' . static::getWhereTabla(NULL, $email);
				//echo($sentencia_sql);
				$bd = new BaseDatos();
				if ($bd->isConectado()){
					$bd->setConsultaSQL($sentencia_sql);
					if ($bd->getFila()){
						$retorno = true;
					}
				}
			}
		}
		return($retorno);
	}
	//Creado por Pedro el 28/Enero/2019 ==> Función que recibe el array de datos del cliente e intenta registrarlo
	public static function register($data = NULL){
		//HAy que destacar que esta función no utiliza el guardado automático puesto que almacena datos sensibles
		$retorno = 0;
		//Data contendrá un array de datos con los nombres de los campos de la BD y sus respectivos valores
		if (is_array($data)){
			if (count($data) > 0){
				//Si hemos recibido un password vamos a controlar si tiene que ir encriptado con el sistema antiguo o el nuevo:
				if (isset($data['password'])){
					if (trim($data['password']) == ''){
						unset($data['password']); //Si el password es una cadena vacía o espacios, lo quitamos para crearlo así
					}else{
						$password = $data['password'];
						//Según la configuración, el password va guardado con un formato u otro:
						if (Shop::$configuracion->sha1_password){
							//Marina (20/07/2020) soluciono problema de compatibilidad entre registro y login cuando se utiliza el password encriptado antiguo
							//$passwordJustificado = str_pad($password, 10, '.');
							$passwordJustificado = str_pad($password, 10);
							$data['password'] = sha1($passwordJustificado);
						}else{
							$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
						}
					}
				}
				$lista_campos = array_keys($data);
				$lista_valores = $data;
				$lista_campos = ' ( `' . implode('`, `', $lista_campos) . '`) ';
				$lista_valores = ' ( \'' . implode('\', \'', $lista_valores) . '\') ';
				$sentencia_sql = 'INSERT INTO ' . static::getNombreTablaSinAlias() . '
					' . $lista_campos . '
					VALUES
					' . $lista_valores . ';';
				//Insertamos en la BD
				//echo("<br>" . $sentencia_sql . "<br>");
				//FileSystem::log($sentencia_sql);
				$bd = new BaseDatos();
				if ($bd->isConectado()){
					if ($bd->setConsultaSQL($sentencia_sql)){
						//Álvaro 070219 Tarea 5177 Comentamos esto ya que el ID ya no es autonumérico
						//$retorno = $bd->getAutonumerico();
						$sentencia_sql = 'SELECT ' . static::getCampos() . '
									FROM ' . static::getNombreTabla() . '
									WHERE ' . static::getWhereTabla(NULL, $data['email']);
						//echo($sentencia_sql);
						$bd->setConsultaSQL($sentencia_sql);
						if ($fila = $bd->getFila()){
							//Álvaro 080219 TAREA 5187 WEBSTORE: Plantillas de emails, ahora devolvemos todo el objeto para tratarlo en el action del registro
							$retorno = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
						}

					}
				}
			}
		}
		return($retorno);
	}

	//Pedro 19/Marzo/2019 ==> Hacemos el registro/login remoto con Google. En este caso vamos a comprobar si el usuario ya está registrado


	//pedro 08/Febrero/2019 ==> Hay un login estático que recibe parámetros para buscar al cliente y loguearlo
	// y una función dinámica que es la que guarda la sesión y eso
	public static function login($email = NULL, $password = NULL, $doLogin = true){
		$retorno = NULL;
		if ( ($email != NULL) && ($password != NULL) ){
			if ( (trim($email) != '') && (trim($password) != '') ){
				//Vamos a cargar los datos de cliente por el email
				$sentencia_sql = 'SELECT ' . static::getCampos() . '
									FROM ' . static::getNombreTabla() . '
									WHERE ' . static::getWhereTabla(NULL, $email);
				//echo("<br/>{$sentencia_sql}<br/>\n");
				$bd = new BaseDatos();
				if ($bd->isConectado()){
					$bd->setConsultaSQL($sentencia_sql);
					if ($fila = $bd->getFila()){
						$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
						//var_dump($cliente);
						//var_dump(Shop::$configuracion);
						//Vamos a comprobar que el password es correcto:
						//Vamos a comprobar si el login es correcto, para ello tenemos en cuenta la retrocompatibilidad
						if (Shop::$configuracion->sha1_password){
							$passwordModificado = sha1(str_pad($password, 10));
							if ($cliente->password == $passwordModificado){
								$retorno = $cliente;
							}
						}else{
							if (password_verify($password, $cliente->password)) {
								$retorno = $cliente;
							}
						}
						if ($retorno == NULL){
							//Llegados a este punto si no tenemos retorno, devolvemos un "error password incorrecto
							$retorno = -2;
						}
					}else{
						$retorno = -1;
					}
				}
			}
		}
		//Modificado por Pedro el 07/Mayo/2019 ==> Añadimos la posibilidad de que una vez que se haga un login, se quede ejecute el proceso de login.
			//Esto es útil si queremos ejecutar esta función sólo para comprobar si el email y password introducidos son válidos
		if ( (is_a($retorno, "Usuario")) && ($doLogin) ){
			$retorno->logme();
		}
		return($retorno);
	}

	public function logme(){
		//Asignamos tanto al objeto estático como a la sesión el cliente con el que estamos
		self::$loggedUser = $this;
		//echo("Asignamos el valor del cliente a la sesión: " . $retorno->codigo . "<br />\n");
		Sesion::set('cod_cliente_web', $this->codigo);
	}

	public static function logout(){
		self::$loggedUser = NULL;
		Sesion::clean();
	}

	//Pedro 03/Abril/2019 ==> En la cesta tenemos que poder "des-loguearnos" sin perder los productos de la cesta:
	public static function cartLogout(){
		self::$loggedUser = NULL;
		Sesion::remove('usuarioSinRegistro');
		Sesion::remove('cod_cliente_web');
	}

	public static function regeneratePassword($email){
		$retorno = NULL;
		if ($email != ''){
			$sentencia_sql = 'SELECT ' . static::getCampos() . '
								FROM ' . static::getNombreTabla() . '
								WHERE ' . static::getWhereTabla(NULL, $email);
			//echo($sentencia_sql);
			$bd = new BaseDatos();
			if ($bd->isConectado()){
				$bd->setConsultaSQL($sentencia_sql);
				if ($fila = $bd->getFila()){
					//Tenemos un usuario con un email
					$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
					//Vamos a modificar este usuario para que tenga ese valor en "reestablecer_password"

						$cliente->reestablecer_password = password_hash($cliente->email, PASSWORD_DEFAULT );
			
					//var_dump($cliente);
					$sentencia_sql = 'UPDATE `' . static::getNombreTablaSinAlias() . '` SET `reestablecer_password` = \'' . $cliente->reestablecer_password . '\' WHERE `email` = \'' . $cliente->email . '\' ;';
					$bd->setConsultaSQL($sentencia_sql);
					$retorno = $cliente;
				}else{
					$retorno = -1;
				}
			}
		}
		return($retorno);
	}

	public static function getCodigoConfirmacionRegistro($email){
		$retorno = 0;
		if ($email != ''){
			$sentencia_sql = 'SELECT ' . static::getCampos() . '
								FROM ' . static::getNombreTabla() . '
								WHERE ' . static::getWhereTabla(NULL, $email);
			//echo($sentencia_sql);
			$bd = new BaseDatos();
			if ($bd->isConectado()){
				$bd->setConsultaSQL($sentencia_sql);
				if ($fila = $bd->getFila()){
					//Tenemos un usuario con un email
					$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
					$retorno = $cliente->codigo_confirmacion;
				}
			}
		}
		return($retorno);
	}

	public static function updatePasswordByHash($user, $newPassword, $hash){
		$retorno = -1;
		//Vamos a actualizar el cliente según su hash, siempre y cuando sea correcto:

		$cliente = new Usuario($user);
		//var_dump($hash);
		//var_dump($cliente);
		if (password_verify($cliente->email, $hash)){
			//echo "prueba";
			//marina(20/07/2020) comprobamos si tiene la codificacion sha1 
			if (Shop::$configuracion->sha1_password){
				$newPassword = sha1(str_pad($newPassword, 10));
			}else{
				$newPassword = password_hash($newPassword, PASSWORD_DEFAULT);
			}
			$sentencia_sql = 'UPDATE `' . static::getNombreTablaSinAlias() . '` SET `reestablecer_password` = \'\', `password` = \'' . $newPassword . '\' '
			. ' WHERE `codigo` = \'' . $cliente->codigo . '\' ;';
			$bd = new BaseDatos();
			if ($bd->isConectado()){
				$bd->setConsultaSQL($sentencia_sql);
			}
			if ($bd->getNumeroFilas() > 0){
				$retorno = $cliente;
			}else{
				$retorno = 0;
			}
		}else{
			//El password no coincide
			$retorno = -3;
		}
		return($retorno);
	}

	//Pedro 21/Marzo/2019 ==> Esta función comprueba que el token de seguridad es correcto:
	public static function googleAuth($token_id){
		//Necesitamos incluir la librería de autenticación de Google:
		require_once(_WS_LIB_DIR_ . 'google-api-php-client-2.2.2/vendor/autoload.php');
		$retorno = false;
		$client = new Google_Client(['client_id' => Shop::$configuracion->google_api_id]);  // Specify the CLIENT_ID of the app that accesses the backend
		$payload = $client->verifyIdToken($token_id);
		if ($payload) {
			//echo("TODO CORRECTO<br>\n");
			$retorno = true;
		}else{
			//echo("Error<br>\n");
		}
		return($retorno);
	}

	//pedro 20/Marzo/2019 ==> Esta función hace el ckeck del cliente por ID de Google o por el email. Lo suyo es sacarla después al módulo
	public static function checkGoogleRegister($email){

		//Primero vamos a sacar los clientes por email:
		$select_usuario = 'SELECT ' . static::getCampos() . '
							FROM ' . static::getNombreTabla() . '
							WHERE ' . static::getWhereTablaArray( array('email'=>$email) );
		$cliente = NULL;
		$bd = new BaseDatos();
		if ($bd->isConectado()){
			$bd->setConsultaSQL($select_usuario);
			if ($fila = $bd->getFila()){
				//Tenemos un usuario con un email
				$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
			}
		}
		if ($cliente != NULL){
			//Si tenemos un cliente, vamos a actualizarlo para setearle el ID de Google (hay que recordar que dicho ID va encriptado)
			$sentenciaUpdate = 'UPDATE ' . static::getNombreTablaSinAlias() . ' SET `google_user` = \'1\' '
			. ' WHERE `codigo` = \'' . $cliente->codigo . '\' ;';
			$bd->setConsultaSQL($sentenciaUpdate);
		}
		return($cliente);
	}

	public static function checkGoogleLogin($email){
		//Primero vamos a sacar los clientes por email:
		$select_usuario = 'SELECT ' . static::getCampos() . '
							FROM ' . static::getNombreTabla() . '
							WHERE ' . static::getWhereTablaArray(
										array(
											'email'=>$email,
											'google_user' => 1
										)
									);
		//echo("$select_usuario<br>\n");
		$cliente = NULL;
		$bd = new BaseDatos();
		if ($bd->isConectado()){
			$bd->setConsultaSQL($select_usuario);
			if ($fila = $bd->getFila()){
				//Tenemos un usuario con un email
				$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
			}
		}
		//Hacemos el login
		if ($cliente != NULL){
			if ($cliente->codigo != ''){
				$cliente->logme();
			}
		}
		return($cliente);
	}


	//pedro 22/Marzo/2019 ==> Si el usuario no está registrado, lo registramos:
	public static function checkFacebookRegister($email, $fbId){

		//Primero vamos a sacar los clientes por email:
		$select_usuario = 'SELECT ' . static::getCampos() . '
							FROM ' . static::getNombreTabla() . '
							WHERE ' . static::getWhereTablaArray( array('email'=>$email, 'fbId'=>$fbId) );
		$cliente = NULL;
		$bd = new BaseDatos();
		if ($bd->isConectado()){
			$bd->setConsultaSQL($select_usuario);
			if ($fila = $bd->getFila()){
				//Tenemos un usuario con un email
				$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
			}
		}
		if ($cliente != NULL){
			//Si tenemos un cliente, vamos a actualizarlo para setearle el ID de Google (hay que recordar que dicho ID va encriptado)
			$sentenciaUpdate = 'UPDATE ' . static::getNombreTablaSinAlias() . ' SET `fbId` = \'' . $fbId . '\' '
			. ' WHERE `codigo` = \'' . $cliente->codigo . '\' ;';
			$bd->setConsultaSQL($sentenciaUpdate);
		}
		return($cliente);
	}

	public static function checkFacebookLogin($email, $fbId){
		//Primero vamos a sacar los clientes por email:
		$select_usuario = 'SELECT ' . static::getCampos() . '
							FROM ' . static::getNombreTabla() . '
							WHERE ' . static::getWhereTablaArray(
										array(
											'email'=>$email,
											'fbId'=>$fbId
										)
									);
		$cliente = NULL;
		$bd = new BaseDatos();
		if ($bd->isConectado()){
			$bd->setConsultaSQL($select_usuario);
			if ($fila = $bd->getFila()){
				//Tenemos un usuario con un email
				$cliente = new Usuario(new OpcionesWidget(array('filaUsuario' => $fila)));
			}
		}
		//Hacemos el login
		if (is_a($cliente, "Usuario")){
			$cliente->logme();
		}
		return($cliente);
	}
	//Pedro 24/Abril/2019 ==> Actualizamos las direcicones en el usuario logueado
	public static function logueadoUpdateDireccion($direccionModificada){
		$user = self::$loggedUser;
		$asignada = false;
		if ($user != NULL){
			if (is_a($direccionModificada, 'Direcciones')){
				foreach ($user->direcciones as $clave => $direccion){
					if ($direccion->codigo == $direccionModificada->codigo){
						$user->direcciones[$clave] = $direccionModificada;
						$asignada = true;
					}
				}
				//Si no se ha asignado lo añadimos al final
				if (!$asignada){
					$user->direcciones[] = $direccionModificada;
				}
			}
		}
		self::$loggedUser = $user;
	}

	//Pedro 07/Mayo/2019 ==> Funciones remotas del usuario:
	public static function remoteSetUserData($data){
		$return = new stdClass();
		//Recibimos un $data con datos del usuario, pero para mayor seguridad, vamos a tener un hash compuesto por el email del usuario:
		if (is_string($data)){
			$data = json_decode($data);
		}
		
		//Por seguridad esta función va a recibir lo valores a modificar junto con una marca de tiempo. Dicha marca de tiempo tiene una validez máxima de 10 minutos
			//Pasado ese tiempo, no se ejecutará este script
			//Además este script utiliza las funciones genéricas de la clase para automodificarse, lo cual hace que el sistema tenga controlados qué campos 
			//se van a modificar y cuales no.
		$updateUser = false;
		$error = 0;
		$msgs = '';
		//$data = new ObOptions($data);
		$hash = '';
		if (isset($data->hash)){
			$hash = $data->hash;
		}
		$usuario = Usuario::logueado();
		if ($hash != ''){
			//Vamos a obtener el hash actual para este objeto
			$currentHash = $usuario->getHash();
			if (Shop::$configuracion->checkSign($currentHash, $hash)){
				$updateUser = true;
			}
		}
		if ($updateUser){
			//Vamos a pasar a la función de actualización los datos:
			$data->modificado = 1;	//Es importante indicar que el usuario ha sido modificado
			static::updateField($usuario->codigo, array_keys(get_object_vars($data)),  array_values(get_object_vars($data)));
		}

		$return->error = $error;
		$return->msgs = $msgs;

		$return = json_encode($return);		
		return($return);
	}
	
	
	//Pedro 29/Julio/2019 ==>Borramos una dirección de envío del usuario y devolvemos true si ha sido correcto:
	public function removeAddress($codigo){
		//Vamos a controlar que sea el usuario estático:
		$staticUser = (Usuario::logueado() == $this) ? true : false;
		$return = false;
		//Vamos a buscar la dirección en el cliente para borrarla:
		$buscar = true;
		for ($indice = 0; ($indice < count($this->direcciones)) && $buscar; $indice++){
			if($this->direcciones[$indice]->codigo == $codigo){
				$buscar = false;
			}
		}

		if (!$buscar){
			$indice--;
			//Indice es el elemento a borrar:
			array_splice($this->direcciones, $indice, 1);  
		}
		
		//Si la dirección principal del usuario es esta, la quitamos y asignamos la primera que haya y si no hay ninguna, ponemos 0
		if ($codigo == $this->direccion_principal){
			//Pedro 31/Agosto/2020 ==> La direccion principal es un índice y por tanto se inicializa a 0 al borrar:
			//$this->direccion_principal = (count($this->direcciones) > 0) ? $this->direcciones[0] : 0;
			$this->direccion_principal = 0;
		}
		
		//Tenemos que actualizar el usuario logueado:
		if ($staticUser){
			$this->logme();
		}
		return($return);
	}



	//25/Noviembre/2019 Métodos mágicos que voy a utilizar para cuando se serializa/desserializa esto
	public function __sleep(){
		return(array(
			'codigo', 'codigo_sinlib', 'nombre_comercial', 'nombre_legal', 'email', 'direccion_principal', 'direccion', 'cod_postal', 'localidad', 
			'provincia', 'pais', 'telefono', 'telefono2', 'cif', 'tarifa', 'no_precio_especial', 'precios_escalados', 'resta_iva', 'tarifa_dto_pap', 
			'descuento_papeleria', 'descuento_libros', 'descuento_texto', 'limpiar_cesta', 'cod_descuento', 'direc_predeterminada','escalados_tafifas', 
			'vender_costo', 'vender_precio_medio_costo' , 'vender_precio_costo_con_descuento' , 'fecha_nacimiento', 'version_sinli', 'administrador', 
			'factura_sin_detalle', 'tipo_cliente', 'tipo_envio', 'ruta_importe_minimo', 'ruta_gastos_envio', 'password', 'reestablecer_password', 
			'codigo_confirmacion', 'google_user', 'facebook_user', 'comunicados', 'tarifas_multiples'
		));
	}
	public function __wakeup (){
		//TODO ==> hay que cargar el objeto tipo de envío así como el array de lotes asociados
	}
	
	
	//Esta es la función personalizada para la exportación. El email no es un campo público pero sí exportable, por tanto hacemos una pequeña correción:
	public static function getAllExportableFields(){
		return(static::getAllPublicColumnsName(array('email')));
	}
	
	//Pedro 31/Agosto/2020 ==> Obtenemos las direcciones de envío mediante una función para que se pueda "estandarizar" el proceso:
	public function getAdress(){
		//El proceso que hay aquí es el que se ejecutaba antes así que dejo las fechas iniciales
		//Pedro 12/Abril/2019 ==> Ahora las direcciones se cargan desde la clase de direcciones
		$this->direcciones = Direcciones::getUserDirs($this->codigo);

		//si no tenemos direcciones, hay que crear (si procede) la direccion de este usuario:
		if (count($this->direcciones) == 0){
			//A crear la direccion:
			if ( trim($this->direccion . $this->nombre_comercial . $this->nombre_legal . $this->cod_postal . $this->localidad . $this->provincia . $this->pais . $this->telefono) != ''){
				$opciones = array(
					'cliente' => $this->codigo,
					'direccion' => $this->direccion,
					'nombre' => ($this->nombre_comercial != '') ? $this->nombre_comercial : $this->nombre_legal,
					'cod_postal' => $this->cod_postal,
					'localidad' => $this->localidad,
					'provincia' => $this->provincia,
					'pais' => $this->pais,
					'telefono' => $this->telefono
				);
				$this->direcciones[] = $direccion = new Direcciones($opciones);
				//Si el usuario tiene código la guardamos:
				if ($this->codigo != ''){
					//FileSystem::log('Guardamos dirección desde el  usuario');
					$direccion->save();
				}
			}
		}
		//Pedro 31/Agosto/2020 ==> Tenemos que indicar en el array cual es la dirección principal
		/*FileSystem::log('-------------------------------------------');
		FileSystem::log('Llamada desde Usuario');*/
		$this->assignAdressIndex($this->direc_predeterminada);
		//$this->direccion_principal = $this->getAdressIndex($this->direc_predeterminada);
	}
	
	//Pedro 31/Agosto/2020 ==> Función que buscará la dirección en el array de direcciones y asignará el índice de la principal al campo correspondiente
	public function assignAdressIndex($code = NULL){
		$return = 0;
		//Tenemos que tener en cuenta si el cliente el el logueado:
		$userLogged = false;
		//Si el código está vacío es un usuario sin registro, por tanto es el usuario logueado:
		if ($this->codigo == ''){
			$userLogged = true;
		}else{
			//Vamos a mirar si el usuario logueado es en el que estamos:
			if ( (isset(self::$loggedUser)) && ($this->codigo == self::$loggedUser->codigo) ){
				$userLogged = true;
			}
		}
		//Necesitamos un código de dirección
		if ($code == NULL){
			$code = $this->direc_predeterminada;
		}
		if ($code > 0){
			//Vamos a recorrer el array de direcciones buscando este código:
			foreach($this->direcciones as $index => $adrObject){
				if ($adrObject->codigo == $code){
					$return = $index;
				}
			}
		}
		/*
		FileSystem::log('Hemos recibido el código ' . $code . ' y establecemos el índice en: ' . $return);
		ob_start();
		var_dump($this->direcciones);
		$texto = ob_get_clean();
		FileSystem::log($texto);
		*/
		
		$this->direccion_principal = $return;
		
		//Si este usuario es el logueado, le asignamos la dirección
		if ($userLogged){
			self::$loggedUser = $this;
		}
		return($return);
	}
	
}

?>