<?php


/**
 *
 * @author Peter Csubak (chuby)
 * @copyright Peter Csubak (chuby)
 */
class PeaConnector{

	private static $Instance = null;
	
	private $response = null; 

	/**
	 * Szabályos singleton példánykérő metódus. Tehát egy példányt ad vissza, ha már létezik egy példány,
	 * akkor mindig ugyan azt. Ha nem akkor, létrehoz egyet. Gyakorlatilag ez a metódus szolgál a 
	 * példányosító utasítás helyett.
	 * 
	 * @return PeaConnector A kért példány.
	 */
	public static function getInstance(){
		if (self::$Instance == null){
			self::$Instance = new PeaConnector();
		}
		return self::$Instance;
	}

	/**
	 * A singleton miatt kell, hogy privát metódus legyen a konstruktor.
	 */
	private function __construct(){
	}
	
	/**
	 * A megkapott üzenetet alakítja értelmezhető formára, és adja tovább a parseMessage metódusnak.
	 * 
	 * @param string $message Az üzenet teljes szövge string formában.
	 */
	public function reciveMessage($message){
		$xml = null;
		try{
			$xml = new SimpleXMLElement($message);
		}catch (Exception $e){
			try{
				throw new PeaException("A küldött üzenet nem értelmezhető.", null, 100);
			}catch (PeaException $pe){
				$this->collectResponse(null, null, XmlSerializer::serializeException($pe));
				return;
			}
		}
		$this->parseMessage($xml);
	}
	
	/**
	 * Lekérdezi az üzenetre adott választ.
	 * 
	 * @return string A válasz üzenet teljes szövege.
	 */
	public function getResponse(){
		return $this->response;
	}
	
	/**
	 * Összeállítja a válasz üzenetet, úgy, hogy a végeredmény string formában kerüljön a response
	 * attribútumba, amit a getResponse metódussal lehet lekérdezni később.
	 * 
	 * @param string $sessionId Az aktuális session azonosítója.
	 * @param string $objectId Az aktuálisan használt objektum távoli objektum azonosítója 
	 * (ROID - Remote Object ID)
	 * @param string $result A metódushívás, visszatérési értéke, illetve a serializált kivétel, 
	 * abban az esetben, ha a metódushívásban kiváltódott bármilyan kivétel, amit a metódus tovább dobott. 
	 */
	private function collectResponse($sessionId, $objectId, $result){
		$res = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
		$res .= "<response>";
		$res .= "<sid>".$sessionId."</sid>";
		$res .= "<oid>".$objectId."</oid>";
		$res .= "<result>".$result."</result>";
		$res .= "</response>";
		$this->response = $res;
	}
	
	/**
	 * Értelmezi a kapott üzenet xml objektum formájú verzióját. Az értelmezésben benne van a kért metódushívás
	 * illetve session nyitás/zárás végrehajtása is, illetve az üzenetre adandó válasz összeállítása is.
	 * 
	 * @param SimpleXmlElement $xml Az értelmezendő üzenet xml objektum formában.
	 */
	private function parseMessage($xml){
		$methodNode = null;
		$sessionId = null;
		$objectId = null;
		$className = null;
		$schemaName = null;
		$endSession = false;
		
		foreach ($xml as $key => $value){
			if ($key == "sid"){
				$sessionId = "".$value."";
			}elseif ($key == "oid"){
				$objectId = "".$value."";
			}elseif ($key == "cname"){
				$className = "".$value."";
			}elseif ($key == "schname"){
				$schemaName = "".$value."";
			}elseif ($key == "endsession"){
				$endSession = true;
			}else{
				$methodNode = $value;
			}
		}
		
		if (($sessionId == null) && ($className != null) && ($methodNode != null) && ($methodNode->getName() == "create")){
			//új session és példányosítás <-- a kettő összefügg, mert amíg nincs példány addig nem szólunk az új sessionről sem
			$sh = SessionPeaHandler::getInstance();
			$sessionId = $sh->startSession("notajax", $schemaName);
			$objectId = $sh->createInstance($className);
			$res = $sh->serializeResult();
			$this->collectResponse($sessionId, $objectId, $res);
			$sh->pauseSession($sessionId);
		}elseif (($sessionId == null) && ($className != null) && ($methodNode != null)){
			//statless metódushívás
			$sh = SessionPeaHandler::getInstance();
			$objectId = $sh->createInstance($className);
			$sh->parseMethodCall($methodNode, $objectId);
			$res = $sh->serializeResult();
			$this->collectResponse(null, null, $res);
		}elseif (($sessionId != null) && ($className != null) && ($methodNode != null) && ($methodNode->getName() == "create")){
			//meglévő session-be új példány
			$sh = SessionPeaHandler::getInstance();
			$sh->resumeSession($sessionId);
			$objectId = $sh->createInstance($className);
			$res = $sh->serializeResult();
			$this->collectResponse($sessionId, $objectId, $res);
			$sh->pauseSession($sessionId);
		}elseif (($sessionId != null) && ($className == null) && ($methodNode != null) && ($objectId != null)){
			//statful metódushívás	
			$sh = SessionPeaHandler::getInstance();
			$sh->resumeSession($sessionId);
			$sh->parseMethodCall($methodNode, $objectId);
			$res = $sh->serializeResult();
			$this->collectResponse($sessionId, $objectId, $res);
			$sh->pauseSession($sessionId);
		}elseif (($sessionId != null) && ($endSession == true)){
			//session leállítása
			$sh = SessionPeaHandler::getInstance();
			$sh->endSession($sessionId);
		}else{
			//minden más:=> hiba
			try{
				throw new PeaException("Hibás üzenet.", null, 101);
			}catch (PeaException $pe){
				$this->collectResponse(null, null, XmlSerializer::serializeException($pe));
			}
		}
	}

}
?>