<?php

class Serenity_Rpc_XmlRpc implements Dalten_Export_Api_Backend_LoggableBackendInterface
{
	/**
	 * Instance spojeni.
	 *
	 * @var \resource|false
	 */
	private $connection;

	/**
	 * Znacka kodovani.
	 *
	 * @var string
	 */
	private $encoding;

	/**
	 * Instance loggeru komunikace se serverem.
	 *
	 * @var Dalten_Export_Api_Backend_Logger_LoggerInterface
	 */
	private $_logger;

    private $_uri;

	/**
	 * Nastavi spojeni pres curl a vnitrni kodovani.
	 *
	 * @param string $uri      Adresa xml-rpc serveru.
	 * @param string $encoding Kodovani.
	 */
	public function __construct($uri, $encoding = 'UTF-8')
	{
        $this->_uri = $uri;
		$this->connection = curl_init((string) $uri);
		$this->encoding = (string) $encoding;

		curl_setopt_array(
			$this->connection,
			array(
				CURLOPT_POST => true,
				CURLOPT_HTTPHEADER => array('Content-Type: text/xml'),
				CURLOPT_RETURNTRANSFER => true,
				CURLOPT_CAINFO => \Composer\CaBundle\CaBundle::getBundledCaBundlePath()
			)
		);
	}

	/**
	 * Preda parametry metode call.
	 *
	 * @uses call
	 *
	 * @param string $method Nazev metody.
	 * @param mixed $args    Parametry metody.
	 *
	 * @return mixed
	 */
	public function __call($method, $args)
	{
        if ($method == 'login' && $this->_logger) {
            $this->_logger->logRemoteCall('loginUri', $this->_uri);
        }

		return $this->call($method, $args);
	}

	/**
	 * Zavola vzdalenou metodu na serveru a vrati vysledek.
	 *
	 * @param string $method Nazev pozadovane metody.
	 * @param array  $args   Parametry.
	 *
	 * @return mixed
	 */
	public function call($method, array $args)
	{
		$method = (string) $method;
		$options = array(
			'encoding' => $this->encoding,
			'escaping' => 'markup'
		);

		$oldLocale = setlocale(LC_NUMERIC, 0);
		setlocale(LC_NUMERIC, 'en_US');
		$xml = xmlrpc_encode_request($method, $args, $options);

		if ($this->_logger instanceof Dalten_Export_Api_Backend_Logger_LoggerInterface) {
			$this->_logger->logRemoteCall($method, $xml);
		}

		curl_setopt($this->connection, CURLOPT_POSTFIELDS, $xml);

		$rawResponse = curl_exec($this->connection);
		$result = xmlrpc_decode($rawResponse, $this->encoding);
		setlocale(LC_NUMERIC, $oldLocale);

		if ($this->_logger instanceof Dalten_Export_Api_Backend_Logger_LoggerInterface) {
			$this->_logger->logRemoteResponse($method, $rawResponse);
		}

		return $result;
	}

	/**
	 * Nastavi xmlrpc typ, base64 nebo datetime pro PHP retezce.
	 *
	 * @param string $value Odkaz na promenou.
	 * @param string $type Pozadovany typ 'base64' nebo 'datetime'.
	 *
	 * @return string
	 */
	public function setType($value, $type)
	{
		$value = (string) $value;
		xmlrpc_set_type($value, (string) $type);

		return $value;
	}

	/**
	 * Nastaví logger pro backend.
	 *
	 * Logger bude použit pouze pokud to backend dovoluje.
	 *
	 * @param Dalten_Export_Api_Backend_Logger_LoggerInterface $logger Instance loggeru.
	 *
	 * @return Dalten_Export_Api_LoggableApiInterface Fluent interface.
	 */
	public function setLogger(Dalten_Export_Api_Backend_Logger_LoggerInterface $logger)
	{
		$this->_logger = $logger;

		return $this;
	}

	/**
	 * Odstraní nastavený logger.
	 *
	 * @return Dalten_Export_Api_LoggableApiInterface Fluent interface.
	 */
	public function removeLogger()
	{
		$this->_logger = null;

		return $this;
	}

	/**
	 * Změní nastavení adaptéru pomocí funkce {@see curl_setopt}.
	 *
	 * @param int   $option Konstanta pro výběř nastavení.
	 * @param mixed $value  Nová hodnota.
	 *
	 * @return $this Fluent.
	 */
	public function curlSetOpt($option, $value)
	{
		curl_setopt($this->connection, $option, $value);
		return $this;
	}
}
