<?php
/**
 * Backend pro Topreality.sk
 *
 * @category   Dalten
 * @package    Export
 * @subpackage Api
 */
class Dalten_Export_Api_Backend_Toprealitysk implements Dalten_Export_Api_Backend_LoggableBackendInterface
{
	public $xmlHead = '<?xml version="1.0" encoding="utf-8"?>';
	public $exportURL;

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

	/**
	 * Uživatelské jméno.
	 *
	 * @var string
	 */
	private $_username;

	/**
	 * Heslo.
	 *
	 * @var string
	 */
	private $_password;

	/**
	 * Konstruktor.
	 *
	 * @param string $exportURL url kde čeká exportní skript
	 */
	public function __construct($exportURL = "http://realityexport.sk/import/")
	{
		$this->exportURL = $exportURL;
	}

	/**
	 * Nastaví logger pro backend.
	 *
	 * @param \Dalten_Export_Api_Backend_Logger_LoggerInterface $logger Instance loggeru.
	 *
	 * @return Dalten_Export_Api_Backend_Toprealitysk Fluent interface.
	 */
	public function setLogger(Dalten_Export_Api_Backend_Logger_LoggerInterface $logger)
	{
		$this->_logger = $logger;
		return $this;
	}

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

	/**
	 * Nastaví přihlašovací údaje pro upload, přihlásí se až při akci.
	 *
	 * @param string $user jméno
	 * @param string $pass heslo
	 */
	public function login($user, $pass)
	{
		$this->_username = $user;
		$this->_password = $pass;
	}

	/**
	 * Pošle na server připravené XML s nemovitostmi.
	 *
	 * @param array $listing      Data nabídky.
	 * @param array $languageData Jazykově závislá data nabídky.
	 * @param array $images       Pole obrázků.
	 *
	 * @return Dalten_Export_Api_ServerResponse
	 */
	public function addListing(array $listing, array  $languageData, array  $images)
	{
		try {
			$xml = $this->prepareObjectXml($listing, $languageData, $images);
			$response = $this->postXml($xml);
			if ($this->_logger) {
				$this->_logger->logRemoteResponse('import', $response);
			}
			return $this->processObjectResponse($response);
		} catch (Exception $e) {
			return new Dalten_Export_Api_ServerResponse(false, 0, $e->getMessage());
		}
	}

	/**
	 * Pošle na server připravený soubor s makléřem.
	 *
	 * @param array $u Data o uživateli
	 *
	 * @return Dalten_Export_Api_ServerResponse
	 */
	public function addUser(array $u)
	{
		$xml = $this->prepareUserXml($u);
		$response = $this->postXml($xml);
		if ($this->_logger) {
			$this->_logger->logRemoteResponse('import', $response);
		}
		try {
			$responseXml = new SimpleXMLElement($response);
			$success = false;
			if ($responseXml->agent->status_code) {
				if ($responseXml->agent->status_code < 4) {
					$success = true;
				}
				return new Dalten_Export_Api_ServerResponse(
					$success,
					$responseXml->agent->status_code,
					$responseXml->agent->status,
					$response
				);
			} elseif ($responseXml->error) {
				return new Dalten_Export_Api_ServerResponse(false, 0, $responseXml->error);
			}
			return new Dalten_Export_Api_ServerResponse(false, 0, 'Chybí status v odpovědi serveru.');
		} catch (Exception $excp) {
			return new Dalten_Export_Api_ServerResponse(false, 0, "Nečitelná odpověď serveru.", $response);
		}
	}

	/**
	 * Pošle na server žádost o smazání nemovitosti
	 *
	 * @param int $id Id nemovitosti ke smazání
	 *
	 * @return Dalten_Export_Api_ServerResponse
	 */
	public function deleteListing($id)
	{
		$xml = $this->prepareDeleteObjectXml($id);
		$response = $this->postXml($xml);
		if ($this->_logger) {
			$this->_logger->logRemoteResponse('import', $response);
		}
		return $this->processObjectResponse($response);
	}

	/**
	 * Rozluští odpověď serveru
	 *
	 * @param string $response Tělo odpovědi serveru.
	 *
	 * @return Dalten_Export_Api_ServerResponse
	 */
	public function processObjectResponse($response)
	{
		try {
			$useErrors = libxml_use_internal_errors(true);
			$responseXml = new SimpleXMLElement($response);
			$success = false;
			libxml_clear_errors();
			libxml_use_internal_errors($useErrors);
			if ($responseXml->object->status_code) {
				if ($responseXml->object->status_code < 4) {
					$success = true;
				}
				return new Dalten_Export_Api_ServerResponse(
					$success,
					$responseXml->object->status_code,
					$responseXml->object->status,
					$response
				);
			} elseif ($responseXml->error) {
				return new Dalten_Export_Api_ServerResponse(false, 0, $responseXml->error[0] . "!", $response);
			} else {
				return new Dalten_Export_Api_ServerResponse(false, 0, 'Nečitelná odpověď serveru.', $response);
			}
		} catch (Exception $exception) {
			return new Dalten_Export_Api_ServerResponse(false, 0, "Nečitelná odpověď serveru.", $response);
		}
	}

	/**
	 * Pošle na server XML
	 *
	 * @param string $xml Připravené xml.
	 *
	 * @return string opdověď
	 */
	public function postXml($xml)
	{
		$data = array();
		$data['user'] = $this->_username;
		$data['pass'] = md5($this->_password);
		$data['data'] = $xml;
		$vars = http_build_query($data);
		if ($this->_logger) {
			$this->_logger->logRemoteCall('import', $data);
		}
		return $this->do_post_request($this->exportURL, $vars);
	}

	/**
	 * Sestaví XML s informacemi o nemovitosti
	 *
	 * @param array $data     Informace o nemovitosti (přeložené)
	 * @param array $langData Jazykově závislá data (přeložené (né ve smyslu jazyka))
	 * @param array $images   Pole s obrázky
	 *
	 * @return string Vygenerované XML.
	 */
	public function prepareObjectXml(array $data, $langData = array(), $images = array())
	{
		$xml = new SimpleXMLElement($this->xmlHead . '<objects/>');
		$object = $xml->addChild('object');

		$obj = $object->addChild('data');
		foreach ($data as $k => $v) {
			$col = $obj->addChild('col', $v);
			$col->addAttribute('name', $k);
		}

		$ld = $object->addChild('lang_data')->addChild('lang');
		$ld->addAttribute('name', 'sk');
		foreach ($langData as $lk => $lv) {
			$col = $ld->addChild('col');
			$col[0]=$lv; //php bug/feature unterminated entity reference
			$col->addAttribute('name', $lk);
		}

		$media = $object->addChild('media');
		foreach ($images as $iv) {
			$media->addChild('image')->addAttribute('file', $iv['url']);
		}

		return $xml->saveXML();
	}

	/**
	 * Připraví XML na smazání nemovisti.
	 *
	 * @param int $id Id nemovitosti.
	 *
	 * @return string Vrácené XML jako string.
	 */
	public function prepareDeleteObjectXml($id)
	{
		$xml = new SimpleXMLElement($this->xmlHead . '<objects/>');
		$obj = $xml->addChild('object')->addChild('data');
		$obj->addChild('col', $id)->addAttribute('name', 'import_id');
		$obj->addChild('col', 1)->addAttribute('name', 'delete');
		return $xml->saveXML();
	}

	/**
	 * Připraví xml s informaceni o makléři
	 *
	 * @param array $user Informace o makléři
	 *
	 * @return string Vrácené XML jako string.
	 */
	public function prepareUserXml(array $user)
	{
		$xml = new SimpleXMLElement($this->xmlHead . '<export/>');
		$obj = $xml->addChild('agents')->addChild('agent')->addChild('data');
		$obj->addChild('portal_id', $user['id']);
		$jmenoTag = $obj->addChild('meno');
		$jmenoTag[0] = $user['uzivatel_os_jmeno'] . ' ' . $user['uzivatel_os_prijmeni'];
		$telefonTag = $obj->addChild('tel1');
		$telefonTag[0] = $user['telefon'];
		$emailTag = $obj->addChild('email');
		$emailTag[0] = $user['email'];
		return $xml->saveXML();
	}

	/**
	 * Pomocná funkce na vytváření HTTP requestů
	 *
	 * @param string $url             Cílová URL
	 * @param string $data            Data do těla requestu.
	 * @param null   $optionalHeaders Případné další hlavičky
	 *
	 * @return string odpověď
	 * @throws Exception
	 */
	function do_post_request($url, $data, $optionalHeaders = null)
	{
		$params = array('http' => array(
			'method' => 'POST',
			'header' => 'Content-type: application/x-www-form-urlencoded',
			'content' => $data
		));
		if ($optionalHeaders !== null) {
			$params['http']['header'] = $optionalHeaders;
		}
		$ctx = stream_context_create($params);
		$fp = @fopen($url, 'rb', false, $ctx);
		if (!$fp) {
			throw new Exception("Problem with $url");
		}
		$response = @stream_get_contents($fp);
		if ($response === false) {
			throw new Exception("Problem reading data from $url");
		}
		return $response;
	}
}
