<?php
class Membre {
	const DEFAULT_BANNER = "pictures/bande.png";
	
	protected $ID;
	protected $pseudo;
	protected $hashedPassword;
	protected $adminLevel;
	protected $dateCreation;
	protected $requiredBanner;
	protected $personnalMessage;
	
	protected $connected;
	protected $valid;
	
	public function __construct($ID) {
		$this->ID = $ID;
		$this->connected = FALSE;
		$req = $GLOBALS['bdd']->prepare('SELECT * FROM membres WHERE ID=?');
		$req->execute(array($ID));
		if($rep = $req->fetch()){
			$this->valid = TRUE;
			$this->pseudo = $rep['pseudo'];
			$this->adminLevel = $rep['adminLevel'];
			$this->dateCreation = $rep['dateCreation'];
			$this->hashedPassword = $rep['hashedPassword'];
			$this->decodeData($rep['data']);
		}else{
			$this->valid = FALSE;
		}
	}
	
	public function connect($password) {
			$this->connected = password_verify ( $this->pass, $rep ['mdp'] );
		
			return $this->connected;
		
	}
	
	public function __toString(){
		$out = 'Membre\n';
		$out .= '\tID:' . $this->ID . '\n';
		$out .= '\tPseudo:' . $this->pseudo . '\n';
		$out .= '\tAdmin level:' . $this->adminLevel . '\n';
		$out .= '\tDate of creation:' . $this->dateCreation . '\n';
		$out .= '\tRequired banner:' . $this->requiredBanner . '\n';
		$out .= '\tPersonnal message:' . $this->personnalMessage . '\n';
		return out;
	}
	
	public function isConnected(){
		return $this->connected;
	}
	
	public function exists(){
		return $this->valid;
	}
	
	private function decodeData($data) {
		$jsonData = json_decode ( $data );
		// Set the data's required_banner if it is defined , otherwise sets the DEFAULT_BANNER
		$this->requiredBanner = $jsonData ['requiredBanner'] ?? self::DEFAULT_BANNER;
		$this->personnalMessage = $jsonData ['personnalMessage'] ?? NULL;
	}
	
	
	//Getters
	public function getID(){
		return $this->ID;
	}
	
	public function getPseudo(){
		return $this->pseudo;
	}
	
	public function getAdminLevel() {
		return $this->adminLevel;
	}
	
	public function getDateCreation(){
		return $this->dateCreation;
	}
	
	public function getRequiredBanner() {
		return $this->requiredBanner;
	}
	
	public function getPersonnalMessage(){
		return $this->personnalMessage;
	}
	
	
	//Useful getters
	public function isAdminLevelLowerThan($max){
		return $this->adminLevel<$max;
	}
	
	public function isAdminLevelGreaterThan($min){
		return $this->adminLevel>$max;
	}
	
	public function isAdminLevelLowerOrEqualThan($max){
		return $this->adminLevel<$max;
	}
	
	public function isAdminLevelGreaterOrEqualThan($min){
		return $this->adminLevel>$max;
	}
	
	public function hasPersonnalMessage() {
		return isset ( $this->personnalMessage );
	}
	
	public function showPersonnalMessage() {
		$msg = $this->personnalMessage;
		$this->setPersonnalMessage = NULL;
		return $msg;
	}
	
	//Setters
	public function changePassword($newPassword){
		if(strlen($newPassword)>255)
			return Membre::PASSWORD_TOO_LONG;
		$req = $GLOBALS['bdd']->prepare('UPDATE membres SET mdp=? WHERE ID=?');
		$req->execute(array(password_hash ( $newPassword, PASSWORD_DEFAULT ),$this->ID));
		return Membre::PASSWORD_CHANGED;
	}
	
	/**
	 * 
	 * @return Objects which matchs the specified restrictions
	 */
	public static function getFromAttributes($restrictions){
		$whereCommands = array();
		$restrictionValues = array();
		foreach ($restrictions as $restriction){
			$whereCommand = NULL;
			$attribute = $restriction[0];
			$json = FALSE;
			$operator = NULL;
			$value = NULL;
			try {
				switch ($attribute){
					case 'ID':
						$value = intval($restriction[2]);
						$operator = Utility::getIntegerSqlOperator($restriction[1]);
						break;
					case 'pseudo':
						$value = '"'.strval($restriction[2]).'"';//FIXME escaped chars (',",\n,\t ...)
						$operator = Utility::getStringSqlOperator($restriction[1]);
						break;
					case 'hashedPseudo':
						$value = '"'.strval($restriction[2]).'"';
						$operator = Utility::getStringSqlOperator($restriction[1]);
						break;
					case 'adminLevel':
						$value = intval($restriction[2]);
						$operator = Utility::getIntegerSqlOperator($restriction[1]);
						break;
					case 'dateCreation':
						//FIXME y ä pâs là vàlüè
						$value=""
						$operator = 'convert(datetime, "'.Utility::getDateSqlOperator($restriction[1]).'")';
						break;
					case 'requiredBanner':
						$json=TRUE;
						$value = "'".strval($restriction[2])."'";
						$operator = Utility::getStringSqlOperator($restriction[1]);
						break;
					case 'personnalMessage':
						$json=TRUE;
						$value = "'".strval($restriction[2])."'";
						$operator = Utility::getStringSqlOperator($restriction[1]);
						break;
					default:
						echo 'Unknown attribute "'.$attribute.'" for the class Membre';
						exit;
				}
			}catch(InvalidOperatorException $e){
				echo $e->getMessage().' when reading attribute "'.$attribute.'"';
				exit;
			}
			
			$restrictionValues[] = $value;
			
			if($json){
				$whereCommand = '((data->"$.'.$attribute.'" IS NOT NULL) AND (data->"$.'.$attribute.'" '.$operator.' ? ))';
			}else{
				$whereCommand = $attribute . ' ' . $operator . ' ' . $value;
			}
			$whereCommands[] = $whereCommand;
		}
		$wherePart = 'WHERE '.implode(' AND ',$whereCommands);
		
		
		$req = $GLOBALS['bdd']->prepare('SELECT * FROM membres '.$wherePart);
		$req->execute($restrictionValues);
		if($req->errorInfo()[0] == 0)
			echo 'A SQL exception occured ...';
		$out = array();
		while($rep = $req->fetch())
			$out[] = new Membre($rep['ID']);
			
		//Choose return value
		switch(count($out)){
			case 0:
				return NULL;
			case 1:
				return $out[0];
			default:
				return $out;
		}
	}
	
	public static function getFromPseudo($pseudo){
		return getFromAttributes(array(['pseudo','=',$pseudo]));
	}
	
	public static function getFromAdminLevel($level){
		return getFromAttributes(array(['adminLevel','=',$level]));
	}
	
	public static function getFromDateCreation($date){
		return getFromAttributes(array(['dateCreation','=',$date]));
	}
	
	public static function getCreatedLaterThan($date){
		return getFromAttributes(array(['dateCreation','>',$date]));
	}
	
	public static function getCreatedEarlierThan($date){
		return getFromAttributes(array(['dateCreation','<',$date]));
	}
	
	public static function getAdminGreaterThan($min){
		return getFromAttributes(array(['adminLevel','>',$min]));
	}
	
	public static function getAdminLowerThan($max){
		return getFromAttributes(array(['adminLevel','<',$max]));
	}
	
	
	//Membre creator
	public static function registerPerson($pseudo, $mdp) {
		if (Membre::getFromPseudo($pseudo))
			return Membre::USED_USERNAME;
		$req = $GLOBALS ['bdd']->prepare ('INSERT INTO membres(pseudo,mdp,date_creation) VALUES (?,?,NOW())');
		$req->execute (array($pseudo,password_hash( $mdp, PASSWORD_DEFAULT)));
		return Membre::PERSON_REGISTERED;
	}

	
	//Outputs texts
	
	//changePassword
	const PASSWORD_TOO_LONG = 'Le mot de passe est trop long ! (Max : 255 caract&egrave;res)';
	const PASSWORD_CHANGED = 'Le mot de passe a bien &eacute;t&eacute; chang&eacute;';
	
	//registerPerson
	const USED_USERNAME = 'Le pseudonyme est d&eacute;j&agrave; utilis&eacute;';
	const PERSON_REGISTERED = 'Le membre a bien &eacute;t&eacute; inscrit !';
}
	
	
	
	

