<?
class jtms{
	var $nodes;
	var $kb;
	
	function jtms(&$kb){
		$this->setup_jtms($kb);
		$this->kb =& $kb;
	}
	
	function test(){
		echo("<br>JTMS registered<br>");
	}
	
	function setup_jtms($kb){
		//this function simply asserts all of the facts as anotomical
		foreach($kb->facts as $fact){
			$this->nodes[] = new jtmsNode($fact, array("true"));
		}
	}
	
	function jtms_check_node($node){
		//echo("passing to line 23\n");
		//print_r($node);
		//echo("\n passed");
		foreach($node->inList as $justificationSet){
			if($justificationSet = "true"){
				return true;
			}
			elseif(count($justificationSet) == 0){
				return false;
			}
			else{
				$flag = true;
				foreach($justificationSet as $justification){
					$childNode = jtms_find_node($justification);
					if($childNode->label == "OUT" || $childNode == false){
						$flag = false;
					}
				}
				//if one whole justification set is IN then so is this node
				if($flag){
					return true;
				}
			}
		}
		//if it hasnt been proved true by here then it isnt going to be
		return false;
	}
	
	function jtms_find_node($fact){
		if(!$this->nodes){
			return false;
		}
		//echo("Passing to line 50 \n");
		//print_r($this->nodes);
		//echo("\n Passed");
		foreach($this->nodes as $testNode){
			if($testNode->fact == $fact){
				return $testNode;
			}
		}
		return false;
	}
	
	function jtms_test_justification($node, $justification){
		//tests if the node is justified by	the justification provided
		$flag = false;
		foreach($node->justifications as $testSet){
			if(in_o_array($justification, $testSet)){
				$flag = true;
			}
		}
		return flag;
	}
	
	function jtms_remove_justification($node, $justification){
		//removes justification sets containing the justification argument
		//note this does not update any other properties of the node this
		//is a low level function simply for manipulating the lists
		$building = array();
		foreach($node->justifications as $testSet){
			if(!in_o_array($justification, $testSet)){
				$building[] = $testSet;
			}
		}
	}
	
	function jtms_add_justification_set($fact, $justificationSet){
		if($this->jtms_find_node($fact)){
			//we have a node now update it
			$node = $this->jtms_find_node($fact);
			$list = $node->inList;
			$flag = false;
			foreach($node->inList as $jSet){
				if($this->jtms_are_equal_jlists($jSet, $justificationSet)){
					$flag = true;
				}
			}
			if(!$flag){
				$this->jtms_remove_node($fact);
				$node->inList[] = $justificationSet;
				$check = $this->jtms_check_node($node);
				if(!$check){
					$node->label = "OUT";
				}
				$this->nodes[] = $node;
			}
		}
		else{
			$newNode = new jtmsNode($fact, $justificationSet);
			$check = $this->jtms_check_node($newNode);
			if(!$check){
				$node->label = "OUT";
			}
			$this->nodes[] = $newNode;
			//echo("\n Added node: ");
			//print_r($newNode);
			
		}
	}
	
	function jtms_are_equal_jlists($js1, $js2){
		if(count($js1) == 0 || count($js2) == 0){
			return false;
		}
		if(!is_array($js1) && !is_array($js2)){
			return true;
		}
		if(!is_array($js1)){
			return false;	
		}
		if(!is_array($js2)){
			return false;	
		}
		if(count($js1) != count($js2)){
			return false;
		}
		else{
			$flag = true;
			foreach($js1 as $test){
				if(!in_o_array($test, $js2)){
					$flag = false;
				}
			}
			foreach($js2 as $test){
				if(!in_o_array($test, $js1)){
					$flag = false;
				}
			}
			return $flag;
		}
	}
	
	function jtms_remove_node($fact){
		$newNodes = array();
		foreach($this->nodes as $node){
			if($node->fact != $fact){
				$newNodes[] = $node;
			}
		}
		$this->nodes = $newNodes;
	}
	
	function jtms_retract($fact){
		//first remove the node associated with this fact
		//it will be reasserted in the next stage of modus ponenes if it is
		//beleived due to some other inference
		$this->jtms_remove_node($fact);
		//next we need to find which nodes are justified ONLY by a horn containing this fact
		//to delete them and also remove every justification containing this horn from
		//other still beleived clauses
		$retractions = array();
		$newNodes = Array();
		if(isset($this->nodes)){
		foreach($this->nodes as $node){
			$justifications = array();
			
			foreach($node->inList as $horn){
				//echo("<br>BBBBBBBBBBBB<pre>");
				//print_r($horn);
				//echo("</pre>BBBBBBBBBB<br>");
				if($horn == "true"){
					$justifications[] = $horn;
				}
				elseif(!in_o_array($fact, $horn)){
					$justifications[] = $horn;
				}
				else{
					//echo("suspect horn detected");	
				}
			}
			if(count($justifications) == 0){
				//echo("<br> empty justification set detected<br>");
				//echo("<br>Retracting<pre>");
				//print_r($node->fact);
				//echo("</pre>");
				$retractions[] = $node->fact;
				//$this->kb->retract_fact($node->fact);
			}
			else{
				$node->inList = $justifications;
				$newNodes[] = $node;
			}
			
			
		}
		}
		$this->nodes = $newNodes;
		return $retractions;
	}
}
?>