<?php
/* CORE API */
	//Infos api
	$api = new Api("core", "Api du coeur applicatif");
	$api->route('infos','retourne les informations sur l\'environnement','GET',function($request,&$response){
		global $myUser,$databases_credentials;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);

		$repository = '';
		if(file_exists(__DIR__.SLASH.'.git'.SLASH.'config')){
			$stream = file_get_contents(__DIR__.SLASH.'.git'.SLASH.'config');
			preg_match('|url = (.*\.fr)[:/]([^\n]*)|is', $stream,$match);
			$repository = $match[2];
			$repositoryUrl = preg_replace('|[^@]*@|i','http://',$match[1]).'/'.$match[2];
		}
		if(file_exists(__DIR__.SLASH.'.git'.SLASH.'refs'.SLASH.'heads'.SLASH.'master'))
			$commitVersion = str_replace(array("\n","\r"),"",file_get_contents(__DIR__.SLASH.'.git'.SLASH.'refs'.SLASH.'heads'.SLASH.'master'));

		$response['application']['label'] = PROGRAM_NAME;
		$response['application']['version'] = SOURCE_VERSION;
		$response['application']['versionning']['type'] = 'git';
		$response['application']['versionning']['repository'] = $repository;
		$response['application']['versionning']['repository_url'] = $repositoryUrl;
		$response['application']['versionning']['commit_version'] = $commitVersion;
		$response['application']['timezone'] = TIME_ZONE;
		$response['php']['version'] = phpversion();
		$response['apache']['version'] = apache_get_version();
		$response['databases'] = array();
		foreach ($databases_credentials as $key => $value) {
			unset($value['password']);
			$value['uid'] = $key;
			$response['databases'][] = $value;
		}

		$response['os']['type'] = PHP_OS;
		$response['os']['time'] = time();

	});


	$api->route('token','retourne un jwt token en fonction des identifiants fournis sur l\'environnement','POST',function($request,&$response){

		$_ = json_decode($request['body'],true);

		if(!isset($_['api_id']) || !isset($_['api_secret']))  throw new Exception("Api Credentials are missing",401);
		global $conf;
		if(empty($conf->get('jwtauth_secret'))) throw new Exception('JWT secret is missing in core',501);

		if(session_status() == PHP_SESSION_ACTIVE) session_destroy();
		session_start();

		$apiKey = UserPreference::load(array('key'=>'api_id','value'=>encrypt($_['api_id'])));
		if(!$apiKey) throw new Exception('Api id not found',404);

		$apiSecret = UserPreference::load(array('key'=>'api_secret','user'=>$apiKey->user,'value'=>encrypt($_['api_secret'])));
		if(!$apiSecret) throw new Exception('Bad api secret',401);

		$apiEnabled = UserPreference::load(array('key'=>'api_enabled','user'=>$apiKey->user,'value'=>1));
		if(!$apiEnabled) throw new Exception('Api is not enabled for this account',401);

		global $myUser,$myFirm;
		$myUser = User::connectLogin($apiSecret->user);

		if(!$myUser || !$myUser->connected()) throw new Exception('Bad credentials',401);
		if(file_exists('enabled.maintenance') && $myUser->superadmin != 1) throw new Exception('Maintenance is enabled, only super admin can connects',403);

		$_SESSION['currentUser'] = serialize($myUser);
		$_SESSION['firm'] = serialize($myFirm);

		$response['session'] = session_id();

		$json = array();
		$json['exp'] = strtotime('+8hours');

		$json['attributes'] = array(
			'session_id' => session_id(),
			'user' => $myUser->login
		);
		$response['token'] = JWToken::createFromJson($json,$conf->get('jwtauth_secret'));

	});



	//right api
	$api->route('rights','retourne la liste des droits du logiciel','GET',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['rights'] = array();

		if(isset($request['parameters']['sort']))  throw new Exception("Sort is not implemented for firms",501);
		if(isset($request['parameters']['filter']))  throw new Exception("Filter is not implemented for firms",501);

		$limit = isset($request['parameters']['limit']) ? array($request['parameters']['limit']) : array();

		foreach (Right::loadAll(array(),array(),$limit) as $right) {
			$row = $right->toArray();
			$response['rights'][] = $row;
		}
	});

	$api->route('rights/[rightid]','ajoute/modifie un droit du logiciel','PUT',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['right'] = array();
		//Création
		$_ = $request['parameters'];
		$form = json_decode($request['body'],true);
		if(!$form) throw new Exception("Invalid JSON body",400);
		User::check_access('right','edit');

		if(!empty($request['pathes'])){
			$right = Right::getById($request['pathes'][0]);
			if(empty($right->id)) throw new Exception("Right not found", 404);
			$response['code'] = 200; //Modifié
		}else{
			$right =  new right();
			if(!isset($form['rank']) || empty($form['rank'])) throw new Exception("L'id du rang est obligatoire",400);
			if(!isset($form['scope']) || empty($form['scope'])) throw new Exception("Le nom de la scope est obligatoire",400);
			if(!isset($form['firm']) || empty($form['firm'])) throw new Exception("L'id de l'établissement est obligatoire",400);

			$response['code'] = 201; //Créé
		}

		//Check si le rang existe
		$rank = Rank::getById($form['rank']);
		if(empty($rank->id)) throw new Exception("Rank not found", 400);

		//Check si la firm existe
		$firm = Firm::getById($form['firm']);
		if(empty($firm->id)) throw new Exception("Firm not found", 400);

		//Check si la scope existe
		$scopes = array();
		Plugin::callHook('section',array(&$scopes));
		$find = false;
		foreach($scopes as $scope=>$description){
			if ($scope==$form['scope']){
				$find = true;
				break;
			}
		}
		if (!$find) throw new Exception("Section not found", 400);

		if(isset($form['targetUid'])) $right->targetUid = $form['targetUid'];
		if(isset($form['scope'])) $right->scope = $form['scope'];
		if(isset($form['firm'])) $right->firm = $form['firm'];
		if(isset($form['read'])) $right->read = $form['read'];
		if(isset($form['edit'])) $right->edit = $form['edit'];
		if(isset($form['delete'])) $right->delete = $form['delete'];
		if(isset($form['configure'])) $right->configure = $form['configure'];

		$right->save();
		Log::put("Création/Modification de droit ".$right->toText(),'Droit');
		$response['right'] = array('id'=>$right->id,'scope'=>$right->scope);

	});

	$api->route('rights/rightid','Supprime un rang du logiciel','DELETE',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		if(empty($request['pathes'])) throw new Exception("You must specify right id", 400);
		User::check_access('right','delete');
		$right = Right::getById($request['pathes'][0]);
		if(!$right) throw new Exception("Right not found",404);

		$right->deleteById($right->id);

		Log::put("Suppression du rang ".$right->toText(),'Rang');
		$response['code'] = 204;
	});

	//rank api
	$api->route('ranks','retourne la liste des rangs du logiciel','GET',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['ranks'] = array();

		if(isset($request['parameters']['sort']))  throw new Exception("Sort is not implemented for firms",501);
		if(isset($request['parameters']['filter']))  throw new Exception("Filter is not implemented for firms",501);

		$limit = isset($request['parameters']['limit']) ? array($request['parameters']['limit']) : array();
		foreach (Rank::loadAll(array(),array(),$limit) as $rank) {
			$row = $rank->toArray();
			$response['ranks'][] = $row;
		}
	});

	$api->route('ranks/[rankid]','ajoute/modifie un rang du logiciel','PUT',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['rank'] = array();
		//Création
		$_ = $request['parameters'];
		$form = json_decode($request['body'],true);
		if(!$form) throw new Exception("Invalid JSON body",400);
		User::check_access('rank','edit');

		if(!empty($request['pathes'])){
			$rank = Rank::getById($request['pathes'][0]);
			if(empty($rank->id)) throw new Exception("Rank not found", 404);
			$response['code'] = 200; //Modifié
		}else{
			$rank =  new rank();
			if(!isset($form['label']) || empty($form['label'])) throw new Exception("Le libellé est obligatoire",400);
			//Check si un rang n'existe pas déjà avec ce label
			if(Rank::load(array('label'=>$form['label']))) throw new Exception("Un rang existe déjà avec ce nom",400);
			$rank->label = $form['label'];
			$response['code'] = 201; //Créé
		}

		if(isset($form['label'])) $rank->label = $form['label'];
		if(isset($form['description'])) $rank->description = $form['description'];

		$rank->save();
		Log::put("Création/Modification de rang ".$rank->toText(),'Rang');
		$response['rank'] = array('id'=>$rank->id,'label'=>$rank->label);

	});

	$api->route('ranks/rankid','Supprime un rang du logiciel','DELETE',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		if(empty($request['pathes'])) throw new Exception("You must specify rank id", 400);
		User::check_access('rank','delete');
		$rank = Rank::getById($request['pathes'][0]);
		if(!$rank) throw new Exception("Rank not found",404);

		foreach(UserFirmRank::loadAll(array('rank'=>$rank->id)) as $ufrLink)
			UserFirmRank::deleteById($ufrLink->id);

		$rank->deleteById($rank->id);

		Log::put("Suppression du rang ".$rank->toText(),'Rang');
		$response['code'] = 204;
	});



	//firm api
	$api->route('firms','retourne la liste des établissements du logiciel','GET',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['firms'] = array();

		if(isset($request['parameters']['sort']))  throw new Exception("Sort is not implemented for firms",501);
		if(isset($request['parameters']['filter']))  throw new Exception("Filter is not implemented for firms",501);

		$limit = isset($request['parameters']['limit']) ? array($request['parameters']['limit']) : array();

		foreach (Firm::loadAll(array(),array(),$limit) as $i=>$firm) {
			$row = $firm->toArray();
			$response['firms'][] = $row;
		}
	});

	$api->route('firms/[firmid]','ajoute/modifie un établissement du logiciel','PUT',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['firm'] = array();
		//Création
		$_ = $request['parameters'];
		$form = json_decode($request['body'],true);
		if(!$form) throw new Exception("Invalid JSON body",400);
		User::check_access('firm','edit');

		if(!empty($request['pathes'])){
			$firm = Firm::getById($request['pathes'][0]);
			if(empty($firm->id)) throw new Exception("Firm not found", 404);
			$response['code'] = 200; //Modifié
		}else{
			$firm =  new Firm();
			if(!isset($form['label']) || empty($form['label'])) throw new Exception("Le libellé est obligatoire",400);
			if(!isset($form['mail']) || empty($form['mail'])) throw new Exception('Le champ "Mail"est obligatoire',400);
			//Check si une firm n'existe pas déjà avec ce label
			if(Firm::load(array('label'=>$form['label']))) throw new Exception("Un établissement existe déjà avec ce nom",400);
			$firm->label = $form['label'];
			$response['code'] = 201; //Créé
		}

		if(isset($form['label'])) $firm->label = $form['label'];
		if(isset($form['description'])) $firm->description = $form['description'];
		if(isset($form['mail'])) $firm->mail = $form['mail'];
		if(isset($form['phone'])) $firm->phone = $form['phone'];
		if(isset($form['fax'])) $firm->fax = $form['fax'];
		if(isset($form['street'])) $firm->street = $form['street'];
		if(isset($form['street2'])) $firm->street2 = $form['street2'];
		if(isset($form['city'])) $firm->city = $form['city'];
		if(isset($form['zipcode'])) $firm->zipcode = $form['zipcode'];
		if(isset($form['siret'])) $firm->siret = $form['siret'];
		if(isset($form['iban'])) $firm->iban = $form['iban'];

		$firm->save();
		Log::put("Création/Modification de l'établissement ".$firm->toText(),'Etablissement');
		$response['firm'] = array('id'=>$firm->id,'label'=>$firm->label);

	});

	$api->route('firms/firmid','Supprime un établissement du logiciel','DELETE',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		if(empty($request['pathes'])) throw new Exception("You must specify firm id", 400);
		User::check_access('firm','delete');
		$firm = Firm::getById($request['pathes'][0]);
		if(!$firm) throw new Exception("Firm not found",404);

		foreach(UserFirmRank::loadAll(array('firm'=>$firm->id)) as $ufrLink)
			UserFirmRank::deleteById($ufrLink->id);

		$firm->deleteById($firm->id);

		Log::put("Suppression de l'établissement ".$firm->toText(),'Etablissement');
		$response['code'] = 204;
	});

	//user api
	$api->route('account','retourne les informations du compte connecté','GET',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['account'] = $myUser->toArray();
		unset($response['account']['password']);
	});

	//user api
	$api->route('users','retourne la liste des utilisateurs du logiciel','GET',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['users'] = array();

		if(isset($request['parameters']['sort']))  throw new Exception("Sort is not implemented for users",501);
		if(isset($request['parameters']['filter']))  throw new Exception("Filter is not implemented for users",501);

		foreach (User::getAll(array('right'=>false)) as $i=>$user) {
			if(isset($request['parameters']['limit']) && $request['parameters']['limit']==$i) break;
			$row = $user->toArray();
			unset($row['password']);
			unset($row['manager']);
			$row['origin'] = !isset($row['id']) ?  'plugin': 'database';
			$response['users'][] = $row;
		}
	});

	$api->route('users/[userid]','ajoute/modifie un utilisateur du logiciel','PUT',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		$response['user'] = array();
		//Création
		$_ = $request['parameters'];
		$form = json_decode($request['body'],true);
		if(!$form) throw new Exception("Invalid JSON body",400);
		User::check_access('user','edit');

		if(!empty($request['pathes'])){
			$user = User::byLogin($request['pathes'][0]);

			if(empty($user->login)) throw new Exception("User not found", 404);
			$response['code'] = 200; //Modifié
		}else{
			$user =  new User();
			if(!isset($form['login']) || empty($form['login'])) throw new Exception("Identifiant obligatoire",400);
			if(!isset($form['password']) || empty($form['password'])) throw new Exception("Mot de passe obligatoire",400);
			if(!isset($form['mail']) || empty($form['mail'])) throw new Exception('Le champ "Mail"est obligatoire',400);

			foreach(User::getAll(array('right'=>false)) as $existingUser)
				if($existingUser->mail == trim($_['mail'])) throw new Exception("Un utilisateur existe déjà avec cette adresse e-mail");

			//Check si un user n'existe pas déjà avec ce login (on récupère tous les users car user peut être supprimé logiquement / désactivé uniquement)
			if(User::load(array('login'=>$form['login']))) throw new Exception("Un utilisateur existe déjà avec cet identifiant",400);
			$user->login = $form['login'];
			$response['code'] = 201; //Créé
		}

		if(!empty(trim($form['password']))){
			$passwordErrors = User::check_password_format(html_entity_decode($form['password']));
			if(count($passwordErrors)!=0 && !$myUser->superadmin) throw new Exception("Le format de mot de passe ne respecte pas les conditions suivantes : <br>".implode("<br>",$passwordErrors), 400);

			if($form['password']==$form['login'] || $form['password']==$form['mail'] ) throw new Exception("Le mot de passe ne peut pas être identique à l'identifiant ou à l'e-mail",400);

			$user->password = User::password_encrypt($form['password']);
			$user->preference('passwordTime',time());
		}

		if(isset($form['firstname'])) $user->firstname = mb_ucfirst(mb_strtolower($form['firstname']));
		if(isset($form['name'])) $user->name = mb_strtoupper($form['name']);
		if(isset($form['mail'])) $user->mail = $form['mail'];

		$user->state = User::ACTIVE;
		if(isset($form['manager'])) $user->manager = $form['manager'];
		$user->save();
		User::getAll(array('right'=>true,'force'=>true));
		Log::put("Création/Modification de l'utilisateur ".$user->toText(),'Utilisateur');
		$response['user'] = array('id'=>$user->id,'login'=>$user->login);

	});

	$api->route('users/userid','Supprime un utilisateur du logiciel','DELETE',function($request,&$response){
		global $myUser;
		if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
		if(empty($request['pathes'])) throw new Exception("You must spcify user login", 400);
		User::check_access('user','delete');
		$user = User::byLogin($request['pathes'][0]);
		if(!$user) throw new Exception("User not found",404);
		if($user->superadmin == 1) throw new Exception("You can't delete superadmin account",403);
		if($user->login == $myUser->login) throw new Exception("You can't delete your own account",403);
		if(empty($user->id)) throw new Exception("You cant delete no db account", 400);

		$user = User::getById($user->id);
		$user->state = User::INACTIVE;
		$user->save();

		foreach(UserFirmRank::loadAll(array('user'=>$user->login)) as $ufrLink)
			UserFirmRank::deleteById($ufrLink->id);
		if(isset($_SESSION['users_rights'])) unset($_SESSION['users_rights']);
		if(isset($_SESSION['users_norights'])) unset($_SESSION['users_norights']);
		Log::put("Suppression de l'utilisateur ".$user->toText(),'Utilisateur');
		$response['code'] = 204;
	});

	$api->register();
	/* FIN CORE API */
?>