<?php

class ControleExpert {
	
	//********************************************************************************************
	//
	// VARIABLES
	// 
	//********************************************************************************************/
	
	// Oid du contrôle expert
	private $oid;
	
	// Code du contrôle expert
	private $code;
	
	// Texte (nom) du contrôle expert
	private $texte;
	
	// Début de la date de validité du contrôle
	private $date_validite_debut;
	
	// Fin de la date de validité du contrôle
	private $date_validite_fin;
	
	// Contrôle qui apparaît ou non caché à l'utilisateur standard
	private $is_hide;
	
	// Pas encore iplémenté
	private $is_global;
	
	// Indice de gravité du contrôle expert
	private $gravite;
	
	// Etat des dossiers ciblés 0:Tous, 1:Présents, 2:Non facturés
	private $etat_cible;
	
	// Indiue si le contrôle est livré par CTI
	private $is_cti;
	
	// Tableau de règles du contrôle expert (classe RegleExpert)
	private $rules;
	
	// Tableau de résultats du contrôle expert. Voir fonction aggregate_results() pour détails.
	private $results;
	
	// Connexion à la base de données iCTI (Alimenté par ControleExpertManager)
	private $database;
	
	// Tables sur lesquelles peuvent être effectués les contrôles. (Alimenté par ControleExpertManager)
	private $tables;
	
	// Date de sortie des séjours à partir de laquelle on peut lancer les contrôles expert
	private $expert_date_debut;
	
	// Date et heure de la dernière exécution du contrôle
	private $last_execution_timestamp;
	
	// Etat de la dernière exécution du contrôle : OK ou KO
	private $last_execution_ok;
	
	// Message d'erreur en cas d'erreur justement
	private $error_msg;
	
	// Prestataire concerné par le contrôle (par défaut, tous)
	private $prestataire;
	
	// Flag qui indique si le contrôle est activé ou non
	private $actif;
	
	// Indique si le contrôle est réalisable (actif et sur le bon prestataire)
	private $realisable;
	
	
	
	//********************************************************************************************
	//
	// PUBLIC FUNCTIONS
	// 
	//********************************************************************************************/
	
	
	/**
	 * Constructeur
	 *
	 *	@param $db : connexion à la base de données iCTI
	 */
	function  __construct($db=null) {
		
		// Initialisation des variables
		$this->database = $db;
		$this->oid = -1;
		$this->code = '';
		$this->texte = '';
		$this->date_validite_debut = '';
		$this->date_validite_fin = '';
		$this->is_hide = false;;
		$this->is_global = false;
		$this->gravite = -1;
		$this->etat_cible = array();
		$this->is_cti = 0;
		$this->rules = array();
		$this->results = array();
		$this->tables = array();
		$this->expert_date_debut = '';
		$this->last_execution_timestamp = '';
		$this->last_execution_ok = '';
		$this->error_msg = '';
		$this->actif = true;
		$this->prestataire = true;
		$this->realisable = true;
	} 
	
	
	
	/**
	 * Setter 'magique'
	 * à remplacer éventuellemenet par un Setter par propriété
	 */
	public function __set($property, $value) {
		if (property_exists($this, $property)) {
			$this->$property = $value;
		}
		return $this;
	}
	
	
	
	/**
	 * Getter 'magique'
	 * à remplacer éventuellemenet par un getter par propriété
	 */
	public function __get($property) {
		if (property_exists($this, $property)) {
			return $this->$property;
		}
    }
	
	
	
	/**
	 * Lance l'excution du contrôle expert :
	 * Pour chaque règle du contrôle, exécute la règle et compile les réultats
	 * dans le tableau $this->results[]
	 *
	 * Si toutes les règles se sont bien exécutées, retroune TRUE, si non retourne FALSE
	 */
	public function run() {
		
		$nb_rules = count($this->rules);
		$nb_success = 0;
		
		foreach($this->rules as $rule) {
			// N'exécute la règle que si elle possède réellement une condition d'exécution
			if (strlen($rule->sqlcmd_where) > 0) {
				if($rule->run()) {
					$this->aggregate_results($rule->results);
					$nb_success++;
				}
				else {
					// Empile les erreurs des règles
					$this->error_msg .= $rule->error;
				}
			}
		}
		// Si des règles ont engendré des erreurs, on améliore le message d'erreur en préfixant avec le code du contrôle
		if (strlen($this->error_msg) > 0) {
			$this->error_msg = " Contrôle " . $this->code . ". " . $this->error_msg;
		}
		// Trie le tableau des résultas
		ksort($this->results);
		
		$this->last_execution_ok = $nb_success == $nb_rules ? '1' : '0';
		$this->last_execution_timestamp = date('Y-m-d H:i:s');
		
		return $nb_success == $nb_rules;
	}
	
	
	
	/**
	 * Récupère les informations des règles associées au contrôle expert.
	 * Les règles sont stockées par leurs oids dans le tableau $this->rules[]
	 */
	public function get_rules() {
		
		if (is_null($this->database)) {
			return false;
		}
		
		$request = "
			
			SELECT 
				rule.oid as rule_id,
				rule.controle_id,
				rule.sqlcmd_where,
				rule.sqlcmd_justificatif,
				rule.numero,
				rule.table_id
			FROM
				activite.t_expert_controle_rule rule
				JOIN activite.t_expert_controle controle ON controle.oid = rule.controle_id
			WHERE
				controle.oid = $this->oid
		";
		$result = $this->database->exec($request);
		if ($result === false) {
			$this->error_msg = 'Erreur pendant la récupération des règles _ requête erronée';
			return false;
		}
		
		while ($row = pg_fetch_array($result)) {
			if (strlen($row['sqlcmd_where']) > 0) {
				$rule = new RegleExpert();
				$rule->oid = $row['rule_id'];
				$rule->sqlcmd_where = $row['sqlcmd_where'];
				$rule->sqlcmd_justificatif = $row['sqlcmd_justificatif'];
				$rule->numero = $row['numero'];
				$rule->table_id = $row['table_id'];
				$rule->table = $this->tables[$row['table_id']];
				$rule->expert_date_debut = $this->expert_date_debut;
				$rule->etat_cible = $this->etat_cible;
				$rule->database = $this->database;
				$this->rules[$rule->oid] = $rule;
			}
		}
		return true;
	}
	
	
	
	//********************************************************************************************
	//
	// PRIVATE FUNCTIONS
	// 
	//********************************************************************************************/
	
	/**
	 * Aggrège les résultats des différentes règles d'un contrôle
	 * Rajoute des justificatifs à un contrôle dont une précédente règle à déjà produit des résultats
	 * 
	 *	@param $new_results : tableu de résultats d'une règle expert
	 *
	 *	$new_results[$sejour_id]
	 *					|
	 *					|___['infos']
	 *					|		|_____ $info1 = $valeur1
	 *					|		|_____ $info2 = $valeur2
	 *					|		...
	 *					|
	 *					|___['justificatifs']
	 *					|		|_____ $justif1 = $valeur1
	 *					|		|_____ $justif2 = $valeur2
	 *					|		...
	 
	 */
	private function aggregate_results($new_results) {
		
		// Le tableau à traiter devient le tableau final si ce dernier est vide
		if (count($this->results) == 0) {
			$this->results = $new_results;
		}
		else {
			// Détecte les résultats dont la clé (séjour_id) apparait dans le tabelau final et dans le tableau à traiter
			$doublons = array_intersect_key($new_results, $this->results);
			foreach($doublons as $dossier => $doublon) {
				// Rajoute chaque justificatif du résultat du tableau à traiter à la suite
				// des justificatifs du résultat final possédant la même clé
				foreach($doublon['justificatifs'] as $justif_code => $new_justif) {
					$this->results[$dossier]['justificatifs'][$justif_code] = $new_justif;
				}
			}
			// Ajoute les nouveaux résultats au tableau final de résultats
			$this->results += $new_results;
		}
	}
}

?>