<?php

/**
 * Gestion des utilisateurs
 * 
 * @author Olivier Arteau
 */

class Utilisateur {

    private $flags = null;
    private $nom = null;
    private $lastping = null;
    private $id = null;
    private $salles = null;
    
    public function __construct($name = null) {
    	if ($name != null) {
    		$this->loadUser($name);
    	}
    }
    
    /**
     * Mets en mémoire seulement le nom de l'utilisateur et si d'autres informations sont
     * nécessaire, elles seront chargé plus tard.
     * 
     * @param (String) $nom Nom de l'utilisateur
     * @throws Exception Si le nom est invalide, il n'est pas chargé
     */
    
    public function loadUser($nom) {
    	if (!$this->isValidUsername($nom)) {
    		throw new Exception("Nom invalide");
    	}
    	
    	$this->nom = $nom;
    }
    
    /**
     * Charge les données relatives à un utilisateur en fonction de son id.
     * 
     * @param (int) $id
     */
    
    public function loadUserFromID($id) {
    	$bd = BDConnexion::getBdConnexion();
    	$sql = 'SELECT nom, flags, lastping FROM utilisateurs WHERE id=? AND lastping>?';
    	$parametre = array($id, time() - PING_TIMEOUT);
    	$resultat = $bd->execQuerySelect($sql, $parametre);
		
		if (isset($resultat[0])) {
	    	$this->flags = $resultat[0]['flags'];
	    	$this->lastping = $resultat[0]['lastping'];
	    	$this->nom = $resultat[0]['nom'];
	    	$this->id = $id;
		} else {
			throw new Exception('Utilisateur invalide ou inexistant.');
		}
    }
    
    /**
     * Charge les informations générique de l'utilisateur. Cette méthode est seulement appelé quand
     * la classe a besoin de l'information pour éviter de surcharger le serveur en traitement et en mémoire.
     */
    
    private function loadInfo () {
    	if (!isset($this->nom) && isset($this->id))
    		return $this->loadUserFromID($this->id);
    	
    	$bd = BDConnexion::getBdConnexion();
    	$sql = 'SELECT id, flags, lastping FROM utilisateurs WHERE nom=? AND lastping>?';
    	$parametre = array($this->nom, time() - PING_TIMEOUT);
    	$resultat = $bd->execQuerySelect($sql, $parametre);
		
		if (isset($resultat[0])) {
	    	$this->flags = $resultat[0]['flags'];
	    	$this->lastping = $resultat[0]['lastping'];
	    	$this->id = $resultat[0]['id'];
		} else {
			throw new Exception('Utilisateur invalide ou inexistant.');
		}
    }
    
    /**
     * Vérifie si le nom est valide synthaxiquement parlant.
     * 
     * @param (String) $name
     * @return (Boolean)
     */
    
    private function isValidUsername($name) {
    	$regexp = "/^[a-zA-Z0-9_-]{2,32}$/";
    	
    	return (preg_match($regexp, $name) != 0);
    }
    
    /**
     * Retourne la liste des salles à laquelles l'utilisateur est connecté
     * 
     * @return (Salle[]) Liste des salles
     */
    
    public function getSallesConnectes() {
    	if ($this->id == null)
			$this->loadInfo();
    	
    	if ($this->salles == null) {
	    	$this->salles = array();
	    	$bd = BDConnexion::getBdConnexion();
	    	$sql = 'SELECT o.salleID, s.nom FROM occupation o INNER JOIN salles s ON o.salleID=s.id WHERE o.utilisateurID=?';
	    	$parametres = array($this->id);
	    	$resultat = $bd->execQuerySelect($sql, $parametres);
	    	
	    	for ($i=0; $i<count($resultat); $i++) {
	    		$s = new Salle();
	    		$s->setID($resultat[$i]['salleID']);
	    		$s->setNom($resultat[$i]['nom']);
	    		array_push($this->salles, $s);
	    	}
    	}
    	
    	return $this->salles;
    }
    
    /**
     * Vérifie si l'utilisateur est dans un salle.
     * 
     * @param (String) Nom de la salle a tester
     * @return (Boolean) Vrai si l'utilisateur s'y trouve
     */
    
    public function isInRoom ($nomSalle)  {
    	$sallesConnectes = $this->getSallesConnectes();
		
		for ($i=0; $i<count($sallesConnectes); $i++) {
			if ($sallesConnectes[$i]->getNom() == $nomSalle) {
				return true;
			}
		}
		
		return false;
    }
    
    /**
     * Retourne le nom de l'utilisateur
     * 
     * @return (String)
     */
    
    public function getNom() {
    	if ($this->nom == null && $this->id != null)
    		$this->loadUserFromID($this->id);
    	return $this->nom;
    }
    
    /**
     * Change le nom de l'utilisateur en mémoire et en base de donnée
     * 
     * @param (String) Nouveau nom
     */
    
    public function setNom ($nom) {
    	if ($this->id == null)
	 		$this->loadInfo();
    	
    	$bd = BDConnexion::getBdConnexion();
    	$sql = 'UPDATE utilisateurs u SET u.nom=? WHERE u.nom=? AND u.id=?';
    	$parametre = array($nom, $this->nom, $this->id);
    	$bd->execQuery($sql, $parametre);
    	$this->nom = $nom;
    }
    
    /**
     * Ajoute un ou plusieurs flags à l'utilisateur
     * 
     * @param (String) $flag Liste des flags à ajouter
     */
    
    public function ajouterFlag($flag) {
    	$flag = strtolower($flag);
    	$newFlags =	array_unique(array_merge(
	    				str_split($this->getFlags()),
	    				str_split($flag)));
	    sort($newFlags);
	    $newFlags = implode('', $newFlags);
	    
	    $this->setFlags($newFlags);
    }
    
    /**
     * Enlève un ou plusieurs flags à l'utilisateur
     * 
     * @param (String) $flag Liste des flags à enlever
     */
    
    public function enleverFlag($flag) {
    	$flag = strtolower($flag);
    	$newFlags = implode('', array_diff(str_split($this->getFlags()),
    		array_intersect(
    			str_split($this->getFlags()),
    			str_split($flag))));
    	
    	$this->setFlags($newFlags);
    }
    
    /**
     * Défini la liste des flags de l'utilisateur
     * 
     * @param (String) 
     */
         
    public function setFlags($flags) {
    	if ($this->id == null)
	 		$this->loadInfo();
    	
    	$bd = BDConnexion::getBdConnexion();
    	$sql = 'UPDATE utilisateurs u SET u.flags=? WHERE u.flags=? AND u.id=?';
    	$parametre = array($flags, $this->flags, $this->id);
    	$bd->execQuery($sql, $parametre);
    	$this->flags = $flags;
    }
    
    /**
     * Retourne la liste des flags de l'utilisateur
     * 
     * @return (String) 
     */
    
    public function getFlags() {
    	if ($this->flags == null)
	 		$this->loadInfo();
	 	
	 	return $this->flags;
    }
    
    /**
     * Retourne si l'utilisateur a la liste des flags passé en paramètre
     * 
     * @param (String) $flags
     * @return (Boolean)
     */
    
    public function hasFlags($flags) {
    	return (strlen($flags) == count(
    		array_intersect(str_split($flags), str_split($this->getFlags()))
    	));
    }
    
    /**
     * Retourne le moment de la dernière requête de l'utilisateur.
     * 
     * @return (Integer)
     */
    
    public function getLastPing() {
    	if ($this->lastping == null)
			$this->loadInfo();
    	
    	return $this->lastping;
    }
    
    /**
     * Définit le temps où la dernière requête à eu lieu
     * 
     * @param (Integer)
     */
    
    public function setLastPing($lastping) {
    	if ($this->id == null)
	 		$this->loadInfo();
	 		   	
    	$bd = BDConnexion::getBdConnexion();
    	$sql = 'UPDATE utilisateurs u SET u.lastping=? WHERE u.lastping=? AND u.id=?';
    	$parametre = array($lastping, $this->lastping, $this->id);
    	$bd->execQuery($sql, $parametre);
    	$this->lastping = $lastping;
    }
    
    /**
     * Retourne le ID de l'utilisateur
     * 
     * @return (Integer)
     */
    
    public function getID() {
    	if ($this->id == null)
    		$this->loadInfo();
    	return $this->id;	
    }
    
    /**
     * Définit le ID de l'utillisateur
     * 
     * Note : À utiliser seulement si on veut charger des informations à partir du ID.
     * 
     * @param (int) id
     */
    
    public function setID($id) {
    	$this->id = $id;	
    }
}
?>