<?php

/**
 * Backend API Realitypro.eu.
 *
 * Jejich API je kompatibilní s Srealitami (proto je tato třída původně kopie exportu na Sreality), ale ne zas tak moc.
 *
 * RealityPro nemění session ID a jejich metody mají prefix reality.XXX .
 *
 * Jednotlivé metody by měly odpovídat metodám na vzdáleném serveru.
 * Pro jejich volání je použito XML RPC.
 *
 * @category   Dalten
 * @package    Export
 * @subpackage Api
 */
class Dalten_Export_Api_Backend_RealityPro implements Dalten_Export_Api_Backend_LoggableBackendInterface
{
    /**
	 * Adpatér pro volání metod přes XML RPC.
	 *
	 * @var Serenity_Rpc_XmlRpc
	 */
	private $_adapter;

    /**
	 * Konstruktor.
	 *
	 * @param Serenity_Rpc_XmlRpc $adapter Adpatér pro volání metod přes XML RPC.
	 */
	public function __construct(Serenity_Rpc_XmlRpc $adapter)
	{
		$this->_adapter = $adapter;
	}

	/**
     * Potvrzení přihlášení.
	 *
	 * Na rozdíl od Srealit používá reality pro jméno a heslo v plainu.
     *
     * @param string $login    Login relace.
     * @param string $password Heslo relace.
     *
     * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: []
     *                                 }
     *                                 </code>
     */
    public function login($login, $password)
	{
        $response = $this->_adapter->call('reality.login', array((string) $login, (string) $password));

		return new Dalten_Data_ArrayObject($response);
	}

	/**
     * Odhlášení.
     *
     * @param string $sessionId ID relace.
     *
     * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: []
     *                                 }
     *                                 </code>
     */
    public function logout($sessionId)
    {
	    return new Dalten_Data_ArrayObject($this->_adapter->call('reality.logout', array((string) $sessionId)));
    }

	/**
	 * Přidání / editace inzerátu.
	 * Metodě se předává slovník advert data, který v sobě nese veškeré číselníkové i nečíselníkové
	 * údaje o inzerátu. Pokud chybí povinná položka, addAdvert končí s chybou. Pozor, některé položky jsou
	 * povinné v závislosti na typu (kategorii) inzerátu. Pozor, datová struktura advert data nemusí obsahovat
	 * všechny předepsané atributy, jsou vyžadovány pouze povinné atributy. Pokud atribut není ve slovníku
	 * obsažen, server odpovídající položku nechává nedotčenou. Tedy nemění samovolně její hodnotu. Metoda
	 * vrací status a advert id, které je vhodné si uchovat pro další operace s uloženým inzerátem. Pokud
	 * je vyplněn parametr advert rkid, musí být v rámci inzerce konkrétního klienta unikátní. Tento parametr
	 * obsahuje vlastní identifikátor inzerátu a tento identifikátor lze v budoucnu použít pro práci s inzerátem
	 * přes importní rozhraní, kde plně zastupuje advert id.
	 * Editace inzerátu se zajistí vyplněním advert id již uloženého inzerátu, nebo je možno zadat existující
	 * advert rkid. Adresu inzerátu lze vyplnit více způsoby: klasické zadání, UIR-ADR, GPS souřadnice.
	 *
	 * Poznámka: Pokud zadáte cenu 0 nebo 1, bude místo ceny zobrazeno Info o ceně u RK.
	 *
	 * @param string $sessionId  ID relace.
	 * @param array  $advertData Data nabídky.
	 *
	 * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: {
	 *                                         advertId: xxx
	 *                                     }
     *                                 }
     *                                 </code>
     */
    public function addAdvert($sessionId, array $advertData)
    {
        if (isset($advertData['ready_date'])) {
			$advertData['ready_date'] = $this->_adapter->setType($advertData['ready_date'], 'datetime');
		}

		if (isset($advertData['energy_performance_attachment'])) {
			$advertData['energy_performance_attachment'] = $this->_adapter->setType($advertData['energy_performance_attachment'], 'base64');
		}

		$response = $this->_adapter->call('reality.addAdvert', array((string) $sessionId, $advertData));
		$output = (array) current($response['output']);

		$response['output'] = array(
			'advertId' => current($output)
		);

		return new Dalten_Data_ArrayObject($response);
    }

	/**
	 * Vymazání inzerátu.
	 * Pomocí advert id nebo advert rkid se identifikuje inzerát. Uložené fotografie u inzerátu a statistiky budou
	 * smazány. Pokud inzerát neexistuje bude vrácen status OK (200).
	 *
	 * Poznámka: Inzeráty nejsou smazány ihned po zavolání této metody, aktuálně se drží ještě po
	 * nějakou dobu než se opravdu smažou.
	 *
	 * @param string $sessionId  ID relace.
	 * @param int    $advertId   ID nabídky.
	 * @param string $advertRkId Vlastní ID nabídky.
	 *
	 * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: []
     *                                 }
     *                                 </code>
	 */
	public function delAdvert($sessionId, $advertId, $advertRkId)
	{
		$response = $this->_adapter->call('reality.delAdvert', array(
			(string) $sessionId,
			(int) $advertId,
			(string) $advertRkId
		));

		return new Dalten_Data_ArrayObject($response);
	}

	/**
	 * Vložení fotografie k již uloženému inzerátu.
	 * Vstupními parametry jsou advert id nebo advert rkid a struktura data:
	 * <code>
	 * array(
	 *		binary data vlastní obrázek
	 *		int main 1=hlavní fotka, 0=ostatní
	 *   	int order nepovinné pořadí v rámci vedlejších fotek
	 *		string alt nepovinný údaj, popisek obrázku
	 *		string photo_id nepovinný údaj, interní id fotky
	 *		string photo_rkid nepovinný údaj, rkid fotky
	 * )
	 * </code>
	 * Pomocí advert id nebo advert rkid se identifikuje inzerát. Výstupem je photo id, které je vhodné si uložit
	 * pro mazání fotky. Pokud je vkládána vedlejší fotografie, a přitom není u inzerátu žádná,
	 * stává se tato automaticky hlavní fotografií. Pokud je vkládána hlavní fotografie, a přitom
	 * u inzerátu již jedna je, stane se vložená fotka fotkou hlavní. Minimální rozlišení fotografie je
	 * 480x360 a maximální velikost souboru 500kB. Po překročení této velikosti server vrací chybu a fotografii
	 * nezpracuje. Je možné obrázek pouze editovat, což znamená, že se nepřeukládá vlastní obrázek,
	 * pouze se editují jeho parametry (hlavní, pořadí, popisek). Pro snadnější orientaci se dá vložit
	 * photo rkid, pomocí kterého se později fotka adresuje.
	 *
	 * @param string $sessionId  ID relace.
	 * @param int    $advertId   ID nabídky.
	 * @param string $advertRkId Vlastní ID nabídky.
	 * @param array  $data       Data fotografie.
	 *
	 * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: {
	 *                                         photoId: xxx
	 *                                     }
     *                                 }
     *                                 </code>
	 */
	public function addPhoto($sessionId, $advertId, $advertRkId, array $data)
	{
		$data['data'] = $this->_adapter->setType($data['data'], 'base64');
		$data['main'] = (int) $data['main'];

		if (isset($data['order'])) {
			$data['order'] = (int) $data['order'];
		}
		if (isset($data['alt'])) {
			$data['alt'] = (string) $data['alt'];
		}
		if (isset($data['photo_id'])) {
			$data['photo_id'] = (string) $data['photo_id'];
		}
		if (isset($data['photo_rkid'])) {
			$data['photo_rkid'] = (string) $data['photo_rkid'];
		}

		$response = $this->_adapter->call('reality.addPhoto', array(
			(string) $sessionId,
			(int) $advertId,
			(string) $advertRkId,
			$data
		));
		$output = (array) current($response['output']);

		$response['output'] = array(
			'photoId' => current($output)
		);

		return new Dalten_Data_ArrayObject($response);
	}

    /**
	 * Vymazání fotografie.
	 * Pomocí photo id nebo photo rkid se identifikuje fotografie. Pokud je mazána hlavní fotografie,
	 * hlavní se automaticky stane první vedlejší. Pokud fotografie neexistuje bude vracen status OK (200).
	 *
	 * @param string $sessionId ID relace.
	 * @param int    $photoId   ID fotografie.
	 * @param string $photoRkId Vlastní ID fotografie.
	 *
	 * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: []
     *                                 }
     *                                 </code>
	 */
	public function delPhoto($sessionId, $photoId, $photoRkId)
	{
		return new Dalten_Data_ArrayObject(
			$this->_adapter->call('reality.delPhoto', array((string) $sessionId, (int) $photoId, (string) $photoRkId)
		));
	}

	/**
	 * Výpis fotografií existujícího inzerátu.
	 *
	 * Pomocí advert id nebo advert rkid se identifikuje inzerát. V output je vráceno pole, kde každý prvek pole
	 * obsahuje strukturu (viz níže). Fotografie jsou seřazeny podle pořadí vložení.
	 *
	 * @param string $sessionId  ID relace.
	 * @param int    $advertId   ID nabídky.
	 * @param string $advertRkId Vlastní ID nabídky.
	 *
	 * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: [
	 * 										           {
	 * 										               photo_id: int,
	 * 										               proto_rkid: string,
	 * 										               main: int (1,0)
	 * 										           }
	 *                                             ]
     *                                 }
     *                                 </code>
	 */
	public function listPhoto($sessionId, $advertId, $advertRkId)
	{
		return new Dalten_Data_ArrayObject(
			$this->_adapter->call('reality.listPhoto', array((string) $sessionId, (int) $advertId, (string) $advertRkId)
		));
	}

	/**
	 * Přidání nového makléře.
	 * Aby makléř byl vložen, je potřeba vyplnit povinné položky v rámci struktury client data.
	 * <code>
	 * array(
	 *		string client_login emailový účet, kterým se dá přihlásit na seznam.cz
	 *		string client_domain nepovinný údaj, doména pro login, lze ji uvést přímo do client_login
	 *		string client_name jméno makléře
	 *		string contact_gsm mobil makléře
	 *		string contact_gsm_code nepovinný údaj, mezinárodní předvolba makléře
	 *		string contact_phone nepovinný údaj, telefon
	 *		string contact_phone_code nepovinný údaj, mezinárodní předvolba
	 *		string contact_email nepovinný údaj, kontaktní email se může lišit
	 *		string makler_note nepovinný údaj, poznámka
	 *		binary photo nepovinný údaj, obrázek makléře
	 * )
	 * </code>
	 * Pomocí seller id nebo seller rkid se identifikuje makléř. Při vkládaní inzerátu, pokud má vlastního
	 * makléře, je tedy na výběr mezi seller rkid a seller id. Ostatní položky ze struktury client data jako
	 * contact phone (telefon), makler note (poznámka makléře) a photo (fotografie makléře) jsou nepovinné.
	 * U korektně vloženého makléře je získáno seller id číslo.
	 *
	 * @param string $sessionId  ID relace.
	 * @param string $sellerId   ID makléře.
	 * @param string $sellerRkId Vlastní ID makléře.
	 * @param array  $clientData Data makléře.
	 *
	 * @return Dalten_Data_ArrayObject <code>
     *                                 {
     *                                     status: xxx,
     *                                     statusMessage: '...',
     *
     *                                     output: {
	 *                                         sellerId: xxx
	 *                                     }
     *                                 }
     *                                 </code>
	 */
	public function addSeller($sessionId, $sellerId, $sellerRkId, array $clientData)
	{
		$clientData = array_map('strval', $clientData);
		$clientData['photo'] = $this->_adapter->setType($clientData['photo'], 'base64');

		$response = $this->_adapter->call('reality.addSeller', array((string) $sessionId, (int) $sellerId, (string) $sellerRkId, $clientData));

		$output = (array) current($response['output']);

		$response['output'] = array(
			'sellerId' => current($output)
		);

		return new Dalten_Data_ArrayObject($response);
	}

	/**
	 * Výpis statistik inzerátu/inzerátů.
	 *
	 * @param string $sessionId  ID relace.
	 * @param array  $advertId   Pole ID nabídek.
	 * @param array  $advertRkId Pole vlastních ID nabídek.
	 *
	 * @return Dalten_Data_ArrayObject Vrácené XML.
	 */
	public function listStat($sessionId, array $advertId, array $advertRkId)
	{
		$response = $this->_adapter->call('reality.listStat', array((string) $sessionId, $advertId, $advertRkId));
		return new Dalten_Data_ArrayObject($response, false);
	}

	/**
	 * Výpis denní statistiky inzerátu.
	 *
	 * @param string $sessionId  ID relace.
	 * @param int    $advertId   ID nabídky.
	 * @param string $advertRkId Vlastní ID nabídky.
	 *
	 * @return Dalten_Data_ArrayObject
	 */
	public function listDailyStat($sessionId, $advertId, $advertRkId)
	{
		$response = $this->_adapter->call('reality.listDailyStat', array((string) $sessionId, (int) $advertId, (string) $advertRkId));
		return new Dalten_Data_ArrayObject($response, false);
	}

	/**
	 * Přidání nového developerského projektu.
	 *
	 * Metodě se předává slovník project_data, který v sobě nese veškeré číselníkové i nečíselníkové
	 * údaje o projektu.
	 * Tyto atributy naleznete v tabulce 2 na straně 22. Pokud chybí povinná položka, addProject končí s chybou.
	 *
	 * @param int   $sessionId   ID relace.
	 * @param array $projectData Naformátovaná data projektu.
	 *
	 * @return Dalten_Data_ArrayObject Odpověď serveru.
	 */
	public function addProject($sessionId, array $projectData)
	{
		if (isset($projectData['date_construct_completion'])) {
			$projectData['date_construct_completion'] = $this->_adapter->setType(
				$projectData['date_construct_completion'], 'datetime'
			);
		}

		if (isset($projectData['date_move'])) {
			$projectData['date_move'] = $this->_adapter->setType($projectData['date_move'], 'datetime');
		}

		if (isset($projectData['date_sale'])) {
			$projectData['date_sale'] = $this->_adapter->setType($projectData['date_sale'], 'datetime');
		}

		$response = $this->_adapter->call('reality.addProject', array((string) $sessionId, $projectData));

		$output = (array) current($response['output']);

		$response['output'] = array(
			'advertId' => current($output)
		);

		return new Dalten_Data_ArrayObject($response);
	}

	/**
	 * Odebrání existujícího developerského projektu.
	 *
	 * Pomocí project_id nebo project_rkid se identiﬁkuje projekt (viz kapitola 1.6), který má být smazán.
	 * Uložené fotograﬁe u projektu budou smazány.
	 *
	 * @param int    $sessionId  ID relace.
	 * @param int    $advertId   ID projektu.
	 * @param string $advertRkId Vlastní ID projektu.
	 *
	 * @return Dalten_Data_ArrayObject Odpověď serveru.
	 */
	public function delProject($sessionId, $advertId, $advertRkId)
	{
		$response = $this->_adapter->call('reality.delProject', array(
			(string) $sessionId,
			(int) $advertId,
			(string) $advertRkId
		));

		return new Dalten_Data_ArrayObject($response);
	}

	/**
	 * Vyexportuje fotografii projektu.
	 *
	 * @param string $sessionId   ID relace.
	 * @param int    $projectId   ID projektu.
	 * @param string $projectRkId Vlastní ID projektu.
	 * @param array  $data        Pole s informacemi o fotografii.
	 *
	 * @return Dalten_Data_ArrayObject Odpověď serveru.
	 */
	public function addProjectPhoto($sessionId, $projectId, $projectRkId, array $data)
	{
		$data['data'] = $this->_adapter->setType($data['data'], 'base64');
		$data['main'] = (int) $data['main'];

		if (isset($data['order'])) {
			$data['order'] = (int) $data['order'];
		}
		if (isset($data['alt'])) {
			$data['alt'] = (string) $data['alt'];
		}
		if (isset($data['photo_id'])) {
			$data['photo_id'] = (string) $data['photo_id'];
		}
		if (isset($data['photo_rkid'])) {
			$data['photo_rkid'] = (string) $data['photo_rkid'];
		}

		$response = $this->_adapter->call('reality.addProjectPhoto', array(
			(string) $sessionId,
			(int) $projectId,
			(string) $projectRkId,
			$data
		));
		$output = (array) current($response['output']);

		$response['output'] = array(
			'photoId' => current($output)
		);

		return new Dalten_Data_ArrayObject($response);
	}

	/**
	 * Vrátí pole s informacemi o přítomných fotkách projektu.
	 *
	 * @param string $sessionId   ID relace.
	 * @param int    $projectId   ID projektu.
	 * @param string $projectRkId Vlastní ID projektu.
	 *
	 * @return Dalten_Data_ArrayObject Odpověď serveru.
	 */
	public function listProjectPhoto($sessionId, $projectId, $projectRkId)
	{
		return new Dalten_Data_ArrayObject(
			$this->_adapter->call('reality.listProjectPhoto', array((string) $sessionId, (int) $projectId, (string) $projectRkId)
		));
	}

	/**
	 * Smaže fotografii od projektu.
	 *
	 * @param string $sessionId ID relace.
	 * @param int    $photoId   ID fotografie.
	 * @param string $photoRkId Vlastní ID fotografie.
	 *
	 * @return Dalten_Data_ArrayObject Odpověď serveru.
	 */
	public function delProjectPhoto($sessionId, $photoId, $photoRkId)
	{
		return new Dalten_Data_ArrayObject(
			$this->_adapter->call('reality.delProjectPhoto', array((string) $sessionId, (int) $photoId, (string) $photoRkId)
		));
	}

	/**
	 * Nastaví logger pro backend.
	 *
	 * @param \Dalten_Export_Api_Backend_Logger_LoggerInterface $logger Instance loggeru.
	 *
	 * @return Dalten_Export_Api_Backend_Sreality Fluent interface.
	 */
	public function setLogger(Dalten_Export_Api_Backend_Logger_LoggerInterface $logger)
	{
		if ($this->_adapter instanceof Dalten_Export_Api_Backend_LoggableBackendInterface) {
			$this->_adapter->setLogger($logger);
		}

		return $this;
	}

	/**
	 * Odstraní nastavený logger pro backend.
	 *
	 * @return Dalten_Export_Api_Backend_Sreality Fluent interface.
	 */
	public function removeLogger()
	{
		if ($this->_adapter instanceof Dalten_Export_Api_Backend_LoggableBackendInterface) {
			$this->_adapter->removeLogger();
		}

		return $this;
	}
}
