<?php

class SonyengineClient {

	const POST_METHOD = "POST";
	const GET_METHOD = "GET";
	
	private $base_url;
	
	public static function getInstance() {
		$host = sfConfig::get('iri_sonyengine_service_host', "localhost");
    	$port = sfConfig::get('iri_sonyengine_service_port', 8080);
    	$path = sfConfig::get('iri_sonyengine_service_path', "/sonyengine");
		
		return new  SonyengineClient($host, $port, $path);
	}
	
	public function __construct($host, $port, $path) {
		$path = rtrim($path,"/");
		$this->base_url = "http://$host:$port/$path";
	}
	
	private function send($path, $method, $fields) {
		
		$path = ltrim($path,"/");
		
		$ch = curl_init();
		$url = "$this->base_url/$path"
		curl_setopt($ch,CURLOPT_URL,$url);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
		
		if($method == self::POST_METHOD) {
			
			$field_string = "";
			
			foreach($fields as $key=>$value) { $fields_string .= $key.'='.urlencode($value).'&'; }
			$fields_string = rtrim($fields_string,'&');
			
			curl_setopt($ch,CURLOPT_POST,1);
			curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
		}
		
		$buffer = curl_exec($ch);
		curl_close($ch);
		
		return $buffer;
	}
	
	
	public function engineTrain($movieId = null) {
		
		$path = "engine/train";
		if(! is_null($movieId)) {
			$path .= "/$movieId";
		}
		
		$res = $this->send($path, self::POST_METHOD, array());
		
		if($res != "ok") {
			throw new Exception('Can not train engine');
		}
		
	}
	
	public function engineFind($movieId, $tag, $distance = "0.05", $more = true ) {
		
		if($more) {
			$more = "true";
		}
		else {
			$more = "false";
		}
		
		$tag = urlencode($tag);
		
		$path = "engine/find/$movieId/$tag/$distance/$more";
		
		$res = $this->send($path,self::GET_METHOD, array());
		
		$result = array();
		
		$doc = DOMDocument::loadXML($res);
		$xpath = new DOMXPath($doc);
		
		$nodes = $xpath->query("/sonyengine/neighbor");
		
		foreach($nodes as $node) {
			$result[] = array("id"=>$node->getAttribute("segment"),"distance"=>$node->getAttribute("distance") );	
		}
				
		return $result;
	}
	
	public function engineReset() {
		$path = "engine/reset";
		
		$res = $this->send($path,self::POST_METHOD,array());

		if($res != "ok") {
			throw new Exception('Can not reset engine');
		}
		
	}
	
	public function segmentCreate($movieId, $retrain) {
		
		$path = "";
		if($retrain)
			$retrain = "true";
		else
		    $retrain = "false";
			
		if(is_array($movieId)) {
			$path = "segment/createall";
			$doc = new DOMDocument();
			$doc->appendChild($doc->createElement("sonyengine"));
			
			foreach($movieId as $id) {
				$elem = $doc->createElement("segment");
				$elem->setAttribute("id",$id);
				$doc->appendChild($elem);
			}
			$fields = array("xml"=>$doc->saveXML(), "retrain"=>$retrain);
		}
		else {
			$path = "segment/create";
			$fields = array("id"=>$movieId, "retrain"=>$retrain);
		}
		
		$res = $this->send($path, self::POST_METHOD, $fields);
		
		if($res != "ok") {
			throw new Exception('Can not create segment');
		}		
		
	}
	
	public function tagAdd($array, $retrain) {
		// test if this is an associative array
		// taken from http://www.php.net/manual/en/function.is-array.php#96724
		$tags = null;
		if($retrain)
			$retrain = "true";
		else
			$retrain = "false";
		
		if(is_array($array) && (0 !== count(array_diff_key($array, array_keys(array_keys($array)))) || count($array)==0)) {
			$tags = $array;
		}
		else {
			$tags = array();
			$tags[] = $array;
		}
		
		$path = "tag/add";

		
		$doc = new DOMDocument();
		$doc->appendChild($doc->createElement("sonyengine"));
		foreach($tags as $tag) {
			$elem = $doc->createElement("tag");
			$elem->setAttribute("name",$tag["name"]);
			$elem->setAttribute("segment",$tag["segment"]);
			$doc->appendChild($elem);
		}
		$fields = array("xml"=>$doc->saveXML(), "retrain"=>$retrain);
		
		$res = $this->send($path, self::POST_METHOD, $fields);
		
		if($res != "ok") {
			throw new Exception('Can not add tags');
		}		

	}

}