<?php
/**
 * Backend exportu na Hyperreality.
 *
 * @category   Dalten
 * @package    Export
 * @subpackage Api
 */
class Dalten_Export_Api_Backend_Hyperreality implements Dalten_Export_Api_Backend_LoggableBackendInterface
{
    private $_http;
    private $_ftp;
    private $_export;
    private $_config;
    /** @var null|Dalten_Export_Api_Backend_Logger_LoggerInterface */
    private $_logger = null;
    private $_importUrl;
    private $_batchTime;

    private $_user;
    private $_password;

    private $_brokersPhotoSend=array();
    private $_advertTemplate = null;
    private $_addressConverter = null;

    /**
     * Konstruktor. Nastavuje závislosti.
     *
     * @param Dalten_Http_ClientInterface         $http      HTTP klient.
     * @param Dalten_Ftp_ConnectorInterface       $ftp       Přihlášený FTP klient.
     * @param Dalten_Export_AbstractExport        $export    Převaděč hodnot.
     * @param Serenity_Config_Config              $config    Načtený konfig exportu.
     * @param string                              $importUrl URL http části importního serveru.
     */

    function __construct(
        Dalten_Http_ClientInterface $http,
        Dalten_Ftp_ConnectorInterface $ftp,
        Dalten_Export_AbstractExport $export,
        Serenity_Config_Config $config,
        $importUrl
    )
    {
        $this->_http = $http;
        $this->_ftp = $ftp;
        $this->_export = $export;
        $this->_config = $config;
        $this->_importUrl = $importUrl;
        $this->_advertTemplate = $this->_getAdvertTemplate();
        $this->_addressConverter = new Dalten_AddressConverter_Hyperreality_Static();
    }

    /**
     * Pokusí se přihlásit k HTTP části exportu.
     *
     * @param string $user     Užizvatelské jméno.
     * @param string $password Heslo.
     *
     * @return bool Zda se podařilo přihlásit.
     */
    public function login($user, $password)
    {
        $url = sprintf(
            '%s/login/?login=%s&pwd=%s',
            $this->_importUrl,
            urlencode($user),
            urlencode($password)
        );
        $responseTXT = $this->_getHttp($url);

        $response  = simplexml_load_string($responseTXT);

        if (isset($response) && isset($response->code) && $response->code==200) {
            $this->_user = $user;
            $this->_password = $password;
            $this->_batchTime = time();
            return true;
        }
        return false;
    }

    /**
     * Zkusí zda funguje FTP login.
     *
     * @return bool Zda je FTP správně přihlášeno.
     */
    public function checkFTPLogin()
    {
        try {
            $this->_ftp->getConnection();
            return true;
        } catch (Dalten_Ftp_Exception_BadLoginOrPassword $e) {
            return false;
        }
    }

    /**
     * Přidá nabídku na server.
     *
     * @param array $listing Informace o nemovitosti.
     * @param array $broker  Informace o makléři nabídky.
     * @param array $photos  Informace o fotografiích nabídky.
     *
     * @return object Pokud se vše povedlo je toto SimpleXMLElement s odpovědí serveru.
     */
    public function addAdvert($listing, $broker, $photos)
    {
        $xml = new Dalten_Xml_SimpleXml('<?xml version="1.0" encoding="UTF-8" ?><advert/>');
        $listing = $this->_addressConverter->convertAddress($listing);
        $nabidka = $this->_export->convertEntityValues('advert', $listing, $this->_config->advert);
        $makler = $this->_export->convertEntityValues('broker', $broker, $this->_config->broker);

        $this->_advertTemplate->fill($xml, $nabidka + $makler);

        $fName = sprintf(
            '%s-%s-%d.xml',
            $this->_user,
            $this->_getForeignId($listing),
            time()
        );

        $this->sendAllPhotos($photos);
        $this->_buildPhotosNodes($photos, $xml->photos);
        $brokerPhoto = $this->sendBrokerPhoto($broker);
        if (isset($xml->broker) && $brokerPhoto) {
            $xml->broker->photo = $brokerPhoto;
        }

        $this->_ftp->putContent($xml->getMultilineXml(), $fName);
        $responseXML = $this->_getHttp(
            sprintf(
                '%s/add-advert/?login=%s&pwd=%s&xml=%s',
                $this->_importUrl,
                urlencode($this->_user),
                urlencode($this->_password),
                urlencode($fName)
            )
        );

        $response = simplexml_load_string($responseXML);

        return $response;
    }

    /**
     * Smaže nabídku ze serveru.
     *
     * @param array $listing Informace o nabídce.
     *
     * @return object Pokud se vše povedlo je toto SimpleXMLElement s odpovědí serveru.
     */
    function delAdvert($listing)
    {
        $responseXML = $this->_getHttp(
            sprintf(
                '%s/del-advert/?login=%s&pwd=%s&foreign_id=%s',
                $this->_importUrl,
                urlencode($this->_user),
                urlencode($this->_password),
                urlencode($this->_getForeignId($listing))
            )
        );

        return simplexml_load_string($responseXML);
    }

    /**
     * Vytopuje nabídku na serveru.
     *
     * @param array $listing Informace o nabídce.
     *
     * @return object Pokud se vše povedlo je toto SimpleXMLElement s odpovědí serveru.
     */
    function topAdvert($listing)
    {
        $responseXML = $this->_getHttp(
            sprintf(
                '%s/top-advert/?login=%s&pwd=%s&foreign_id=%s',
                $this->_importUrl,
                urlencode($this->_user),
                urlencode($this->_password),
                urlencode($this->_getForeignId($listing))
            )
        );

        return simplexml_load_string($responseXML);
    }

    /**
     * Stáhne seznam nabídek na serveru.
     *
     * @return object Pokud se vše povedlo je toto SimpleXMLElement s odpovědí serveru.
     */
    public function listListings()
    {
        $responseXML = $this->_getHttp(
            sprintf(
                '%s/get-adverts/?login=%s&pwd=%s',
                $this->_importUrl,
                urlencode($this->_user),
                urlencode($this->_password)
            )
        );

        return simplexml_load_string($responseXML);
    }

    /**
     * Nahraje na FTP všechny obrázky.
     *
     * Na Hyperreality se zatím obrázky exportovaly vždy všechny.
     *
     * @param array $images Pole s obrázky.
     */
    function sendAllPhotos($images)
    {
        foreach ($images as $image) {
            $hash = "F" . $image['id']; // ID obrázku se nerecykluje
            $this->_ftp->put(
                $image['soubor'],
                $this->_user . '-' . $hash . '-' . $this->_batchTime . '.jpg',
                FTP_BINARY
            );
        }
    }

    /**
     * Pošle na FTP obrázek makléře.
     *
     * @param array $broker Pole s informacemi o makléři.
     *
     * @return string|null Název nahrané fotky makléře nebo null, pokud se žádná nenahrála.
     */
    function sendBrokerPhoto($broker)
    {
        $fileName = $this->_user . '-M' . $broker['id'] . '-' . $this->_batchTime . '.jpg';
        if (file_exists($broker['foto'])) {
            $this->_ftp->put(
                $broker['foto'],
                $fileName,
                FTP_BINARY
            );
            $this->_brokersPhotoSend[] = $broker['id'];
            return $fileName;
        }
        return null;
    }

    /**
     * Postaví informace o obrázcích do XML.
     *
     * @param array                $images     Pole s daty obrázků.
     * @param Dalten_Xml_SimpleXml $photosNode XML element photos kam se bude skládat.
     */
    private function _buildPhotosNodes(array $images, Dalten_Xml_SimpleXml $photosNode)
    {
        foreach ($images as $order=>$image) {
            $hash = "F" . $image['id']; // ID obrázku se nerecykluje
            $newPhoto = $photosNode->addChild('photo');
            $newPhoto->addChild('advert_photo_hash', $hash);
            $newPhoto->addChild('filename', $this->_user . '-' . $hash . '-' . $this->_batchTime . '.jpg');
            $newPhoto->addChild('description', $image['popis']);
            $newPhoto->addChild('main', ($order==0 ? 1 : 0));
        }
    }

    /**
     * Vrací foreign_id nabídky ve správném tvaru.
     *
     * Možno přetížit pro kompatibilitu.
     *
     * @param array $listingData Informace o nabídce.
     *
     * @return string foreign_id které se použije na vzdáleném serveru.
     */
    private function _getForeignId(array $listingData)
    {
        return $listingData['id'];
    }

    /**
     * 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)
    {
        if ($this->_http instanceof Dalten_Export_Api_Backend_LoggableBackendInterface) {
            $this->_http->setLogger($logger);
        }
        if ($this->_ftp instanceof Dalten_Export_Api_Backend_LoggableBackendInterface) {
            $this->_ftp->setLogger($logger);
        }
        $this->_logger = $logger;
        return true;
    }

    /**
     * Odstraní nastavený logger pro backend.
     *
     * @return Dalten_Export_Api_LoggableApiInterface Fluent interface.
     */
    public function removeLogger()
    {
        if ($this->_http instanceof Dalten_Export_Api_Backend_LoggableBackendInterface) {
            $this->_http->removeLogger();
        }
        if ($this->_ftp instanceof Dalten_Export_Api_Backend_LoggableBackendInterface) {
            $this->_ftp->removeLogger();
        }
        $this->_logger = null;
        return false;
    }

    /**
     * Zkratka. Volá metodu GET na HTTP klientovi.
     *
     * @param string $url Kterou URL stáhnout.
     *
     * @return string Stažená data.
     */
    private function _getHttp($url)
    {
        return $this->_http->get($url);
    }

	/**
	 * Poskládá XML šablonu pro nabídku.
	 *
	 * @return Dalten_Xml_Template_Root Šablona.
	 */
	protected function _getAdvertTemplate()
	{
		$advert = new Dalten_Xml_Template_Root('advert');
		$advert->addElement('foreign_id', 'foreign_id');
		$advert->addElement('name', 'name');
		$advert->addElement('description', 'description');
		$advert->addElement('offer_type_id', 'offer_type_id');
		$advert->addElement('advert_state_id', 'advert_state_id');
		$broker = $advert->addElement('broker');
			$broker->addElement('foreign_id', 'broker_foreign_id');
			$broker->addElement('name', 'broker_name');
			$broker->addElement('email', 'broker_email');
			$broker->addElement('phone', 'broker_phone');
		$properties = $advert->addElement('properties');
			$properties->addElement('contact_type_id', 'contact_type_id');
			$properties->addElement('ownership_type_id', 'ownership_type_id');
			$properties->addElement('realty_state_id', 'realty_state_id');
			$properties->addElement('floor_id', 'floor_id');
			$properties->addElement('heating_type', 'heating_type');
			$properties->addElement('building_type_id', 'building_type_id');
			$properties->addElement('object_location_id', 'object_location_id');
			$properties->addElement('house_type_id', 'house_type_id');
			$properties->addElement('energy_label', 'energy_label');
			$properties->addElement('flats_count', 'flats_count');
			$properties->addElement('contract_number', 'contract_number');
			$properties->addElement('annuity', 'annuity');
			$properties->addElement('year_of_development', 'year_of_development');
			$properties->addElement('year_of_reconstruction', 'year_of_reconstruction');
			$properties->addElement('floors_number', 'floors_number');
			$properties->addElement('area','area');
			$properties->addElement('lot_area','lot_area');
			$properties->addElement('built_up_area','built_up_area');
			$properties->addElement('flooring_area','flooring_area');
		$bool_properties = $advert->addElement('bool_properties');
			$bool_properties->addElement('terrace', 'terrace')->zeroIsEmpty(false);
			$bool_properties->addElement('balcony', 'balcony')->zeroIsEmpty(false);
			$bool_properties->addElement('loggia', 'loggia')->zeroIsEmpty(false);
			$bool_properties->addElement('cellar', 'cellar')->zeroIsEmpty(false);
			$bool_properties->addElement('garage', 'garage')->zeroIsEmpty(false);
			$bool_properties->addElement('canalization', 'canalization')->zeroIsEmpty(false);
			$bool_properties->addElement('phone', 'phone')->zeroIsEmpty(false);
			$bool_properties->addElement('internet', 'internet')->zeroIsEmpty(false);
			$bool_properties->addElement('electricity', 'electricity')->zeroIsEmpty(false);
			$bool_properties->addElement('gas', 'gas')->zeroIsEmpty(false);
		$categories = $advert->addElement('categories');
			$categories->addElement('category_id', 'category_id');
		$locality = $advert->addElement('locality');
			$locality->addElement('country_id', 'country_id');
			$locality->addElement('region_id', 'region_id');
			$locality->addElement('district_id', 'district_id');
			$locality->addElement('city_id', 'city_id');
			$locality->addElement('citypart_id', 'citypart_id');
			$locality->addElement('cityverge_id', 'cityverge_id');
			$locality->addElement('street_id', 'street_id');
			$locality->addElement('zip_code', 'zip_code');
            $locality->addElement('gpsLat', 'gpsLat');
            $locality->addElement('gpsLon', 'gpsLon');
		$price = $advert->addElement('price');
			$price->addElement('amount', 'amount');
			$price->addElement('price_type_id', 'price_type_id');
			$price->addElement('currency_id', 'currency_id');
			$price->addElement('note', 'price_note');
		$advert->addElement('photos')->forcedPresence();
		$advert->addElement('videos')->forcedPresence();
		return $advert;
	}
}
