<?php
/**
 * Backend pro globální REMAX.
 *
 * @category   Dalten
 * @package    Export
 * @subpackage Api
 */
class Dalten_Export_Api_Backend_Rex implements Dalten_Export_Api_Backend_LoggableBackendInterface
{
	/**
	 * Zakázka je smazaná.
	 */
	const ZAKAZKA_STAV_SMAZANO = 50;

	/** @var \Dalten_Export_Rex|null Převodník dat. */
	private $_export=null;
	/** @var array|null Načtený newspeak */
	private $_entities=null;
	/** @var \Dalten_Ftp_ConnectorInterface|null Přípojka k FTP. */
	private $_ftp=null;
	/** @var \Dalten_AddressConverter_Rex_Interface Převodník adres. */
	private $_prevodnik=null;

	/** @var  Dalten_Xml_SimpleXml */
	private $_officesXML;
	/** @var  Dalten_Xml_SimpleXml */
	private $_agentsXML;
	/** @var  Dalten_Xml_SimpleXml */
	private $_propertiesXML;

	private $_officesNode;
	private $_agentsNode;
	private $_propertiesNode;

	private $_onlineAgents = array();
	private $_onlineOffices = array();
	private $_onlineListings = array();

	private $_agentCurrentlyAtOffice = array();

	protected $_officesToExport = array();
	protected $_agentsToExport = array();
	protected $_listingsToExport = array();

	protected $_officesImage = array();
	protected $_agentsImage = array();
	protected $_listingsImages = array();

	private $_integratorId=0;
	private $_dateTime='';

	protected $_dataPathPrefix = '';

	/** @var \Dalten_Xml_Template_Node Šablona nabídky. */
	private $_propertyTemplate;
	/** @var \Dalten_Xml_Template_Node Šablona kanceláře. */
	private $_officeTemplate;
	/** @var \Dalten_Xml_Template_Node Šablona makléře. */
	private $_salesAssociateTemplate;

	/** @var \Dalten_Http_ClientInterface HTTP klient. */
	private $_http;
	private $_verificationURL = null;

	/** @var null|Dalten_Export_Api_Backend_Logger_LoggerInterface Logger. */
	private $_logger = null;

	private $_timestamp = null;

	/** @var bool Příznak, zda kancelář s číslem jedna nesmí exportovat. */
	protected $_DaltenShallNotPass = true;

	protected $_batchIsOpen = false;

	/** @var array Seznam zapnutých hacků. */
	protected $_hacks = array();

	/**
	 * Konstruktor. Nastavuje závislosti.
	 *
	 * @param Dalten_Export_Rex                     $export          Převaděč dat.
	 * @param array                                 $entities        Definice entit.
	 * @param Dalten_Ftp_ConnectorInterface         $ftp             Přihlášený FTP klient.
	 * @param int                                   $integratorId    IntegratorID - velice důležité IDčko
	 *                                                               z pohledu globáního REMAXu. Viz dokumentaci.
	 * @param Dalten_AddressConverter_Rex_Interface $prevodnik       Objekt převodníku adres.
	 * @param Dalten_Http_ClientInterface           $http            Objekt HTTP klienta.
	 * @param string                                $verificationURL
	 */
	function __construct(
		Dalten_Export_Rex $export,
		$entities,
		Dalten_Ftp_ConnectorInterface $ftp,
		$integratorId,
		Dalten_AddressConverter_Rex_Interface $prevodnik,
		Dalten_Http_ClientInterface $http,
		$verificationURL
	)
	{
		$this->_export = $export;
		$this->_entities = $entities;
		$this->_ftp = $ftp;
		$this->_integratorId = $integratorId;
		$this->_prevodnik = $prevodnik;
		$this->_http = $http;
		$this->_verificationURL = $verificationURL;

		$this->_timestamp = time();

		$this->_propertyTemplate = $this->_getPropertyTemplate();
		$this->_officeTemplate = $this->_getOfficeTemplate();
		$this->_salesAssociateTemplate = $this->_getSalesAssociateTemplate();
	}

	/**
	 * Resetuje stav zatím vyexportovaných dat.
	 *
	 * @deprecated Změnilo se vnitřní složení exportu.
	 */
	public function resetExport()
	{
		$this->openBatch();
	}

	/**
	 * Přidává nebo odebírá nabídku. Nic nevrací protože by měla vždy přidat/odebrat.
	 *
	 * Také přidává informace o makléři pokud ještě nejsou.
	 *
	 * @param array $ad         Převedené informace o nabídce.
	 * @param array $user       Převedené informace o makléři.
	 * @param array $images     Převedené informace o obrázcích.
	 * @param bool  $isDisabled Chcem místo přidávání smazat? (ve výchozím stavu ne)
	 *
	 * @deprecated Změnilo se vnitřní složení exportu.
	 *
	 * @throws Exception
	 */
	function appendProperty(array $ad, array $user, array $images, $isDisabled=false)
	{
		throw new Exception('Změnilo se vnitřní složení exportu.');
	}

	/**
	 * Přidá informace o kanceláři.
	 *
	 * Ale pouze pokud už nebyly přidány.
	 *
	 * @param array $office     Převedené informace o kanceláři.
	 * @param bool  $isDisabled Chcem místo přidávání smazat? (ve výchozím stavu NE)
	 *
	 * @deprecated Změnilo se vnitřní složení exportu.
	 *
	 * @throws Exception
	 */
	function appendOffice(array $office, $isDisabled=false)
	{
		throw new Exception('Změnilo se vnitřní složení exportu.');
	}

	/**
	 * Přidá informace o makléři.
	 *
	 * Ale jen pokud už nebyly přidány.
	 *
	 * @param array $user       Převedené informace o uživateli.
	 * @param bool  $isDisabled Chceme místo přidávání mazat? (Výchozí je NE)
	 * @param bool  $isTransfer Chceme provést přesun makléře? (Výchozí je NE)
	 *
	 * @deprecated Změnilo se vnitřní složení exportu.
	 *
	 * @throws Exception
	 */
	function appendUser(array $user, $isDisabled=false, $isTransfer=false)
	{
		throw new Exception('Změnilo se vnitřní složení exportu.');
	}

	/**
	 * @deprecated  Změnilo se vnitřní složení exportu.
	 * @throws Exception
	 */
	function uploadXMLFiles()
	{
		throw new Exception('Změnilo se vnitřní složení exportu.');
	}

	/**
	 * Vrátí název souboru podle IntegratorID, data a času.
	 *
	 * @param string $letter Prefix - JOB = job, O = kancelář, A = makléř, P = nemovitost.
	 *
	 * @return string Naformátovaný název souboru.
	 */
	protected function _getFileName($letter)
	{
		return $letter . '_' . $this->_integratorId . '_' . $this->_dateTime . '.xml';
	}

	/**
	 * Nahraje obrázky nabídky na server.
	 *
	 * @param array  $images    Informace o obrázcích (původní).
	 * @param string $kod       ID nabídky.
	 *
	 * @return array Názvy poslaných obrázků.
	 */
	protected function _uploadListingImagesOld(array $images, $kod)
	{
		$sentImages = array(
			'add'=>array(),
			'del'=>array(),
			'ids'=>array()
		);
		foreach ($images as $index=>$image) {
			if (!file_exists($image['soubor'])) {
				continue;
			}
			$imageName = $fileName = 'L_' . $this->_integratorId . '_' . $kod . '_' . $index . '.jpg';
			if ($this->_ftp->put(
				$image['soubor'],
				'XMLImages/' . $imageName,
				FTP_BINARY
			)) {
				$sentImages['add'][$index] = $imageName;
			}
		}
		return $sentImages;
	}

	protected function _uploadListingImagesNew(array $images, array $remoteImages, $kod)
	{
		$sent = array(
			'add'=>array(),
			'del'=>array(),
			'ids'=>$remoteImages
		);
		foreach ($remoteImages as $ord=>$id) {
			if (!isset($images[$ord])) {
				$sent['del'][] = $ord;
				unset($sent['ids'][$ord]);
			}
		}
		foreach ($images as $ord=>$image) {
			$imageName = 'L_' . $this->_integratorId . '_' . $kod . '_' . $ord . '.jpg';
			$upload = false;
			if (!isset($remoteImages[$ord])) {
				$upload = true; // na serveru není obrázek, na lokále ano
			} elseif ($image['id']!=$remoteImages[$ord]) {
				$upload = true; // na serveru je jiné IDčko než na lokále
			}
			if ($upload) {
				$this->_ftp->put(
					$image['soubor'],
					'XMLImages/' . $imageName,
					FTP_BINARY
				);
			}
			$sent['add'][$ord] = $imageName;
			$sent['ids'][$ord] = $image['id'];
		}
		return $sent;
	}

	/**
	 * Vyzkouší zda funguje spojení na FTP.
	 *
	 * @return bool Zda funguje spojení na FTP.
	 *
	 * @throws Dalten_Export_Exception_HumanReadable Vystvětlení co je špatně.
	 */
	function testConnection()
	{
		try {
			$ftpConnection = $this->_ftp->getConnection();
			if ($ftpConnection) {
				return true;
			}
			return false;
		} catch (Dalten_Ftp_Exception_BadLoginOrPassword $e) {
			throw new Dalten_Export_Exception_HumanReadable('Selhalo přihlášení. Zkontrolujte jméno a heslo!');
		} catch (Dalten_Ftp_Exception_Connect $e) {
			throw new Dalten_Export_Exception_HumanReadable('Selhalo přihlášení. Zkontroluje nastavení serveru!');
		} catch (Exception $e) {
			throw new $e;
		}
	}

	/**
	 * Vytvoří JOB control file.
	 *
	 * @return string Job control file.
	 */
	protected function _createJobControlFile()
	{
		$job=new Dalten_Xml_SimpleXml(
			'<?xml version="1.0" encoding="UTF-8"?><JobControl  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.gryphtech.com/REX/XSD/JobControl_v3_2.xsd"/>'
		);
		$job->addChild('IntegratorID', $this->_integratorId);
		if (count($this->_officesToExport)) {
			$job->addChild('OfficeFile', $this->_getFileName('O'));
		}
		if (count($this->_agentsToExport)) {
			$job->addChild('AgentFile', $this->_getFileName('A'));
		}
		if ($this->_listingsToExport) {
			$job->addChild('PropertyFile', $this->_getFileName('P'));
		}
		return $job->getMultilineXml();
	}

	/**
	 * Vrátí šablonu nemovitosti.
	 *
	 * @return Dalten_Xml_Template_Node Šablona.
	 */
	protected function _getPropertyTemplate()
	{
		$property = new Dalten_Xml_Template_Element('Property');
		$property->addElement('IntegratorID', 'IntegratorID')->required();
		$property->addElement('IntegratorPropertyID', 'IntegratorPropertyID')->required()->maxLen(50);
		$property->addElement('IntegratorOfficeID','IntegratorOfficeID')->required()->maxLen(50);
		$property->addElement('IntegratorSalesAssociateID', 'IntegratorSalesAssociateID')->required();
		$property->addOpt('RegionID', 'RegionID')->required();
		$property->addOpt('CommercialResidential', 'CommercialResidential')->required()->whitelistCheck(array(1,2));
		$property->addElement('StreetNumber', 'StreetNumber')->maxLen(20);
		$property->addElement('CityID', 'CityID')->required();
		$property->addElement('LocalZoneID', 'LocalZoneID');
		$property->addOpt('FloorLevel', 'FloorLevel');
		$property->addElement('ShowAddressOnWeb', 'ShowAddressOnWeb');
		$property->addElement('CurrentListingPrice', 'CurrentListingPrice')->required('Neni zadana cena.')->guardFloat();
		$property->addOpt('CurrentListingCurrency', 'CurrentListingCurrency')->required('Neni vybrana mena.')->whitelistCheck(array('CZK','USD','EUR'));
		$property->addOpt('RentalPriceGranularity', 'RentalPriceGranularity');
		$property->addOpt('HidePricePublic', 'HidePricePublic');
		$property->addOpt('TransactionType', 'TransactionType')->required()->whitelistCheck(array(1,2,3));
		$property->addOpt('ContractType', 'ContractType')->required()->whitelistCheck(array(1,2,3,4,5));
		$property->addOpt('PropertyStatus', 'PropertyStatus')->required()->whitelistCheck(array(1,10,11,12,13,14,15,16,17,18,3,6,7,8,9));
		$property->addOpt('PropertyType', 'PropertyType')->required();
		$property->addOpt('ListingStatus', 'ListingStatus')->required();
		$property->addElement('TotalArea', 'TotalArea');
		$property->addElement('LotSizeM2', 'LotSizeM2');
		$property->addElement('TotalNumOfRooms', 'TotalNumOfRooms');
		$property->addElement('NumberOfBedrooms', 'NumberOfBedrooms');
		$property->addElement('NumberOfFloors', 'NumberOfFloors');
		$property->addElement('NumberOfApartmentsInBuilding', 'NumberOfApartmentsInBuilding');
		$property->addElement('YearBuild', 'YearBuild')->maxLen(50);
		$property->addElement('VirtualTour', 'VirtualTour')->maxLen(255);
		$propertyDescriptions = $property->addElement('PropertyDescriptions');
		//$propertyDescriptions = new Dalten_Xml_Template_RexTranslations('PropertyDescriptions');
		//$propertyDescriptions->setVariable('translations');
		// překlad je zatím zakomentován, nasadíme až si vymyslí, že ho chtějí
			$propertyDescription = $propertyDescriptions->addElement('PropertyDescription');
				$propertyDescription->addOpt('LanguageID', 'LanguageID')->required();
				$propertyDescription->addElement('DescriptionText', 'DescriptionText')->required('Neni vyplnen popis.')->maxLen(40000);
		//$property->pushElement($propertyDescriptions);
		$featuresElement = new Dalten_Xml_Template_Features('Features');
		$featuresElement->setVariable('Features');
		$property->pushElement($featuresElement);
		$property->addElement('Images')->forcedPresence();
		$property->addElement('Latitude', 'Latitude');
		$property->addElement('Longitude', 'Longitude');
		return $property;
	}

	/**
	 * Vrátí XML šablonu kanceláře.
	 *
	 * @return Dalten_Xml_Template_Node Šablona.
	 */
	protected function _getOfficeTemplate()
	{
		$office = new Dalten_Xml_Template_Element('Office');
		$office->addElement('IntegratorID', 'IntegratorID')->required();
		$office->addElement('IntegratorOfficeID', 'IntegratorOfficeID')->required();
		$office->addOpt('RegionID', 'RegionID')->required();
		$office->addElement('IntlOfficeID','IntlOfficeID')->required();
		$office->addElement('OfficeName', 'OfficeName')->required()->maxLen(50);
		$office->addElement('Address1', 'Address1')->required()->maxLen(50);
		$office->addElement('CityID', 'CityID')->required();
		$office->addElement('PostalCode', 'PostalCode')->required()->maxLen(15);
		$office->addElement('Latitude', 'Latitude')->required()->guardFloat();
		$office->addElement('Longitude', 'Longitude')->required()->guardFloat();
		$office->addElement('Email', 'Email')->required()->maxLen(75);
		$office->addElement('Phone', 'Phone')->required()->maxLen(25, 'Prilis dlouhe telefonni cislo kancelare!');
		$office->addElement('URLToPrivatePage', 'URLToPrivatePage')->maxLen(100);
		$office->addOpt('Disabled', 'Disabled');
		$marketingInfo = $office->addElement('MarketingInfo');
		$marketingInfo->addElement('OfficeDescription', 'OfficeDescription');
		$office->addElement('ImageFileName', 'ImageFileName');
		return $office;
	}

	/**
	 * Vrátí XML šablonu makléře.
	 *
	 * @return Dalten_Xml_Template_Node Šablona.
	 */
	protected function _getSalesAssociateTemplate()
	{
		$agent = new Dalten_Xml_Template_Element('SalesAssociate');
		$agent->addElement('IntegratorID','IntegratorID')->required();
		$agent->addElement('IntegratorSalesAssociateID','IntegratorSalesAssociateID')->required();
		$agent->addElement('IntegratorOfficeID','IntegratorOfficeID')->required();
		$agent->addOpt('RegionID','RegionID')->required();
		$agent->addElement('IntlAgentID','IntlAgentID');
		$agent->addOpt('IsSalesAssociate','IsSalesAssociate')->required();
		$agent->addElement('FirstName','FirstName')->required()->maxLen(64);
		$agent->addElement('LastName','LastName')->required()->maxLen(50);
		$agent->addElement('Email','Email')->required()->maxLen(50);
		$agent->addElement('Phone','Phone')->maxLen(25);
		$agent->addOpt('Disabled','Disabled');
		$agent->addOpt('MainAgentSpecialization','MainAgentSpecialization')->required();
		$agent->addElement('ImageFileName','ImageFileName');
		$agent->addOpt('Gender','Gender');
		$agent->addElement('DateJoinedREMAX','DateJoinedREMAX');
		$agent->addOpt('RemaxTitle','RemaxTitle');
		$agent->addOpt('cancelAllListings','cancelAllListings');
		$agentTransfer = $agent->addElement('AgentTransfer')->showWhenFilled(array('TransferToOfficeID'));
			$agentTransfer->addElement('TransferToOfficeID','TransferToOfficeID');
			$agentTransfer->addElement('IncludeListingsInTransfer','IncludeListingsInTransfer'); // True
		return $agent;
	}

	/**
	 * Stáhne data seznam úspěšně vyexportovaných nabídek z REXAPI do paměti.
	 *
	 * @deprecated Změnilo se vnitřní složení exportu.
	 */
	public function fetchFromRexapi()
	{
		$this->updateFromRexapi();
	}

	/**
	 * Pokusí se vyhledat daný kód nemovitosti v seznamu nabídek viditelných na webu.
	 *
	 * @param string $kod Kód nemovitosti, po které se sháníme.
	 *
	 * @deprecated Změnilo se vnitřní složení exportu.
	 *
	 * @return bool Je v seznamu viditelných na webu?
	 */
	public function findInVerified($kod)
	{
		return $this->listingPresent(array('kod'=>$kod));
	}

	protected function _passValidRexItems($input)
	{
		if (!is_string($input)) {
			return array();
		}
		$response = json_decode($input, true);
		if (isset($response['RexItems']) && count($response['RexItems'])==$response['RecordCount']) {
			return $response['RexItems'];
		}
		return array();
	}

	public function updateFromRexapi()
	{
		$this->_http->setHeader('Accept', 'application/json');
		$officesURL = str_replace('Listings', 'Offices', $this->_verificationURL);

		$offices = $this->_passValidRexItems($this->_http->get($officesURL));
		foreach ($offices as $office) {
			$officeID = $office['OfficeIntegratorID'];
			$this->_onlineOffices[$officeID] = true;
		}

		$agentsURL = str_replace('Listings', 'Agents', $this->_verificationURL);
		$agents = $this->_passValidRexItems($this->_http->get($agentsURL));
		foreach ($agents as $agent) {
			$agentID = $agent['AgentIntegratorID'];
			$this->_onlineAgents[$agentID] = true;
			$this->_agentCurrentlyAtOffice[$agentID] = $agent['OfficeIntegratorID'];
		}

		$listings = $this->_passValidRexItems($this->_http->get($this->_verificationURL));
		foreach ($listings as $listing) {
			$listingID = $listing['IntegratorPropertyID'];
			$this->_onlineListings[$listingID] = true;
		}
		$this->_http->setHeader('Accept');
	}

	protected function _convertOfficeData(array $office, $isDisabled=false)
	{
		$office['IntegratorID'] = $this->_integratorId;
		if ($isDisabled) {
			$office['disabled'] = true;
		}
		$office['CityID'] = $this->_prevodnik->convertCityID(
			array(
				'nemovitost_uir_okres_kod'=>$office['okres'],
				'nemovitost_uir_obec_kod'=>$office['mesto'],
				'nemovitost_uir_cobce_kod'=>$office['mesto']
			)
		);
		$office = $this->_export->convertEntityValues('Office', $office, $this->_entities->Office);
		return $office;
	}

	protected function _convertAgentData(array $agent, $isDisabled=false)
	{
		$id_uzivatel = $agent['id'];
		$id_firma = $agent['id_firma'];
		$agent['IntegratorID'] = $this->_integratorId;
		if ($isDisabled) {
			$agent['aktivni'] = false;
		}
		if (isset($this->_agentCurrentlyAtOffice[$id_uzivatel]) && $this->_agentCurrentlyAtOffice[$id_uzivatel]!==$id_firma) {
			$agent['TransferToOfficeID'] = $agent['id_firma'];
			$agent['IncludeListingsInTransfer'] = 'True';
			$agent['id_firma'] = $this->_agentCurrentlyAtOffice[$id_uzivatel];
		}

		$agent = $this->_export->convertEntityValues('SalesAssociate', $agent, $this->_entities->SalesAssociate);
		return $agent;
	}

	protected function _convertListingData(array $listing, $isDisabled = false)
	{
		$listing['IntegratorID'] = $this->_integratorId;
		if ($isDisabled) {
			$listing['zakazka_stav'] = self::ZAKAZKA_STAV_SMAZANO;
		}

		// kontrola proti exportu do zahraničí
		if ($this->_prevodnik->isValidRegion($listing)) {
			$listing = $this->_prevodnik->convertAddress($listing);
		}

		$listing = $this->_export->convertEntityValues('Property', $listing, $this->_entities->Property);
		return $listing;
	}

	protected function _fillXML()
	{
		$removeImages = array();
		foreach ($this->_officesToExport as $office) {
			$id_firma = $office['IntegratorOfficeID'];
			if (!empty($this->_officesImage[$id_firma])) {
				$office['ImageFileName'] = $this->_officesImage[$id_firma];
			}
			$this->_officeTemplate->fill($this->_officesNode, $office);
		}
		foreach ($this->_agentsToExport as $agent) {
			$id_uzivatel = $agent['IntegratorSalesAssociateID'];
			if (!empty($this->_agentsImage[$id_uzivatel])) {
				$agent['ImageFileName'] = $this->_agentsImage[$id_uzivatel];
			}
			$this->_salesAssociateTemplate->fill($this->_agentsNode, $agent);
		}
		foreach ($this->_listingsToExport as $listing) {
			$kod = $listing['IntegratorPropertyID'];
			$addedProperty = $this->_propertyTemplate->fill($this->_propertiesNode, $listing);
			/** @var Dalten_Xml_SimpleXML $imagesNode */
			$imagesNode = $addedProperty->Images;
			if (!empty($this->_listingsImages[$kod]['add'])) {
				foreach ($this->_listingsImages[$kod]['add'] as $order=>$foto) {
					$imageNode = $imagesNode->addChild('Image');
					$imageNode->addChild('SequenceNumber', $order);
					$imageNode->addChild('FileName', $foto);
				}
			}
			if (!empty($this->_listingsImages[$kod]['del'])) {
				$removeImages[$kod] = $this->_listingsImages[$kod]['del'];
			}
		}
		if (count($removeImages)>0) {
			$imageRemovals = $this->_propertiesXML->addChild('ImageRemovals');
			foreach ($removeImages as $kod=>$imgs) {
				foreach ($imgs as $ord) {
					$removal = $imageRemovals->addChild('ImageRemoval');
					$removal->addChild('IntegratorPropertyID', $kod);
					$removal->addChild('SequenceNumber', $ord);
				}
			}
		}
	}

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

		$this->_logger = $logger;
		return false;
	}

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

	protected function _logCall($methodName, $data)
	{
		if ($this->_logger) {
			$this->_logger->logRemoteCall($methodName, $data);
		}
	}

	protected function _logResponse($methodName, $data)
	{
		if ($this->_logger) {
			$this->_logger->logRemoteResponse($methodName, $data);
		}
	}

	/**
	 * Připraví novou čistou dávku.
	 */
	public function openBatch()
	{
		$this->_dateTime = date('dmY_His', $this->_timestamp);
		$this->_timestamp += 1;
		// po každém exportu kanceláře zvýšíme timestamp o jednu vteřinu,
		// aby měly soubory unikatni nazvy podle specifikace

		$this->_officesToExport = array();
		$this->_agentsToExport = array();
		$this->_listingsToExport = array();

		$this->_officesImage = array();
		$this->_agentsImage = array();
		$this->_listingsImages = array();

		$this->_propertiesXML = new Dalten_Xml_SimpleXml(
			'<?xml version="1.0" encoding="UTF-8"?><UploadXML xsi:noNamespaceSchemaLocation="http://iconnect.dev.gryphtech.com/REX/XSD/Property_v3_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>'
		);
		$this->_agentsXML = new Dalten_Xml_SimpleXml(
			'<?xml version="1.0" encoding="UTF-8"?><UploadXML xsi:noNamespaceSchemaLocation="http://iconnect.dev.gryphtech.com/REX/XSD/Agent_v3_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>'
		);
		$this->_officesXML = new Dalten_Xml_SimpleXml(
			'<?xml version="1.0" encoding="UTF-8"?><UploadXML xsi:noNamespaceSchemaLocation="http://iconnect.dev.gryphtech.com/REX/XSD/Office_v3_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>'
		);

		$this->_propertiesXML->addChild('Version')->addAttribute('Version', '3.2');
		$this->_propertiesNode = $this->_propertiesXML->addChild('Properties');

		$this->_agentsXML->addChild('Version')->addAttribute('Version', '3.2');
		$this->_agentsNode = $this->_agentsXML->addChild('SalesAssociates');

		$this->_officesXML->addChild('Version')->addAttribute('Version', '3.2');
		$this->_officesNode = $this->_officesXML->addChild('Offices');

		$this->_batchIsOpen = true;
		$this->_logCall(__METHOD__, true);
	}

	public function officePresent($office)
	{
		$id = $office['id_firma'];
		$online = !empty($this->_onlineOffices[$id]);
		$this->_logCall(__METHOD__, $id);
		$this->_logResponse(__METHOD__, $online);
		return $online;
	}

	public function agentPresent($agent)
	{
		$id = $agent['id'];
		$online = !empty($this->_onlineAgents[$id]);
		$this->_logCall(__METHOD__, $id);
		$this->_logResponse(__METHOD__, $online);
		return $online;
	}

	public function listingPresent($property)
	{
		$kod = $property['kod'];
		$online = !empty($this->_onlineListings[$kod]);
		$this->_logCall(__METHOD__, $kod);
		$this->_logResponse(__METHOD__, (int) $online);
		return $online;
	}

	public function officeErrors($office)
	{
		$id = $office['id_firma'];
		$office = $this->_convertOfficeData($office);
		$errors = $this->_officeTemplate->verify($office);
		if ($this->_DaltenShallNotPass && $id==1) {
			$errors[] = 'Firma číslo 1 nesmí být exportovaná na Globál!';
		}
		$this->_logCall(__METHOD__, $id);
		$this->_logResponse(__METHOD__, $errors);
		return $errors;
	}

	public function agentErrors($agent)
	{
		$id = $agent['id'];
		$id_firma = $agent['id_firma'];
		$agent = $this->_convertAgentData($agent);
		$errors = $this->_salesAssociateTemplate->verify($agent);
		if ($this->_DaltenShallNotPass && $id_firma==1) {
			$errors[] = 'Makléři firmy číslo 1 nesmí být exportovaní na Globál!';
		}
		$this->_logCall(__METHOD__, $id);
		$this->_logResponse(__METHOD__, $errors);
		return $errors;
	}

	public function listingErrors($listing)
	{
		$kod = $listing['kod'];
		$this->_logCall(__METHOD__, $kod);
		$id_firma = $listing['id_firma'];
		if (!$this->_prevodnik->isValidRegion($listing)) {
			$errors =  array('Není možné exportovat zahraniční nemovitosti.');
			$this->_logResponse(__METHOD__, $errors);
			return $errors;
		}
		$listing = $this->_convertListingData($listing);
		$errors = $this->_propertyTemplate->verify($listing);
		if ($this->_DaltenShallNotPass && $id_firma==1) {
			$errors[] = 'Nabídky firmy číslo 1 nesmí být exportované na Globál!';
		}
		$this->_logResponse(__METHOD__, $errors);
		return $errors;
	}

	public function officeAdd($office, $delete=false)
	{
		$deleteLog = $delete ? ' (delete)' : '';
		$id_firma = $office['id_firma'];
		$this->_logCall(__METHOD__, $id_firma . $deleteLog);

		if (!empty($office['foto_vypis'])) $office['officepicture'] = $office['foto_vypis'];
		$office['officepicture'] = $this->_dataPathPrefix . $office['officepicture'];

		echo 'zarazena firma - ' . var_export($id_firma, true) . PHP_EOL;
		echo 'cesta - ' . var_export($office['officepicture'], true) . PHP_EOL;
		echo 'existuje -  ' . var_export(file_exists($office['officepicture']), true) . PHP_EOL . PHP_EOL;

		if (!$this->_officesToExport[$id_firma]) {	
			if (file_exists($office['officepicture'])) {
				$imageFileName = sprintf('O_%s_%s.jpg', $this->_integratorId, $id_firma);
				$imageSent = $this->_ftp->put($office['officepicture'], 'XMLImages/' . $imageFileName, FTP_BINARY);
				if ($imageSent) {
					$this->_officesImage[$id_firma] = $imageFileName;
				}
			}
		}
		$office = $this->_convertOfficeData($office, $delete);
		$this->_officesToExport[$id_firma] = $office;
	}

	public function agentAdd($agent, $delete=false)
	{
		$deleteLog = $delete ? ' (delete)' : '';
		$id_uzivatel = $agent['id'];
		$this->_logCall(__METHOD__, $id_uzivatel . $deleteLog);

		if (empty($agent['foto_vypis'])) $agent['foto'] = $agent['foto_vypis'];
		$agent['foto'] = $this->_dataPathPrefix . $agent['foto'];

		echo 'zarazen agent - ' . var_export($id_uzivatel, true) . PHP_EOL;
		echo 'cesta - ' . var_export($agent['foto'], true) . PHP_EOL;
		echo 'existuje -  ' . var_export(file_exists($agent['foto']), true) . PHP_EOL . PHP_EOL;

		if (!$this->_agentsToExport[$id_uzivatel]) {
			if (file_exists($agent['foto'])) {
				$imageFileName = sprintf('A_%s_%s.jpg', $this->_integratorId, $id_uzivatel);
				$imageSent = $this->_ftp->put($agent['foto'], 'XMLImages/' . $imageFileName, FTP_BINARY);
				if ($imageSent) {
					$this->_agentsImage[$id_uzivatel] = $imageFileName;
				}
			}
		}
		$agent = $this->_convertAgentData($agent, $delete);
		$this->_agentsToExport[$id_uzivatel] = $agent;
	}

	public function listingAdd($listing, $images, $remoteImages=array(), $delete=false)
	{
		// všechny firmy posílají obrázky novým způsobem (diffem)
		$useNewImageUploadWay = false;

		$deleteLog = $delete ? ' (delete)' : '';
		$kod = $listing['kod'];
		$this->_logCall(__METHOD__, $kod . $deleteLog);
		if ($useNewImageUploadWay) {
			$imagesSent = $this->_uploadListingImagesNew($images, $remoteImages, $kod);
		} else {
			$imagesSent = $this->_uploadListingImagesOld($images, $kod);
		}
		$this->_listingsImages[$kod] = $imagesSent;
		$listing = $this->_convertListingData($listing, $delete);
		$this->_listingsToExport[$kod] = $listing;
	}

	public function getImagesForListing(array $listingData)
	{
		$kod =  $listingData['kod'];
		return (isset($this->_listingsImages[$kod]['ids']) ? $this->_listingsImages[$kod]['ids'] : array());
	}

	public function sendBatch()
	{
		$this->_logCall(__METHOD__, true);
		if (!$this->_batchIsOpen) {
			throw new Dalten_Export_Exception_HumanReadable('Není otevřená dávka!');
		}
		$this->_batchIsOpen = false;
		$sentSomething = false;
		$this->_fillXML();
		if (count($this->_officesToExport)) {
			$sent = $this->_ftp->putContent(
				$this->_officesXML->getMultilineXML(),
				'XMLData/' . $this->_getFileName('O')
			);
			if (!$sent) {
				throw new Dalten_Export_Exception_HumanReadable('Nepodařilo se odeslat XML s kancelářemi.');
			}
			$sentSomething = true;
		}
		if (count($this->_agentsToExport)) {
			$sent = $this->_ftp->putContent(
				$this->_agentsXML->getMultilineXml(),
				'XMLData/' . $this->_getFileName('A')
			);
			if (!$sent) {
				throw new Dalten_Export_Exception_HumanReadable('Nepodařilo se odeslat XML s makléři.');
			}
			$sentSomething = true;
		}
		if (count($this->_listingsToExport)) {
			$sent = $this->_ftp->putContent(
				$this->_propertiesXML->getMultilineXml(),
				'XMLData/' . $this->_getFileName('P')
			);
			if (!$sent) {
				$this->_logResponse(__METHOD__, 'Nepodařilo se odeslat XML s nemovitostmi.');
				throw new Dalten_Export_Exception_HumanReadable('Nepodařilo se odeslat XML s nemovitostmi.');
			}
			$sentSomething = true;
		}
		if ($sentSomething) {
			$sent = $this->_ftp->putContent(
				$this->_createJobControlFile(),
				'XMLData/' . $this->_getFileName('JOB')
			);
			if (!$sent) {
				throw new Dalten_Export_Exception_HumanReadable('Nepodařilo se odeslat JOB control file.');
			}
		}
	}

	/**
	 * Nastaví seznam zaplých hacků.
	 *
	 * @param array $hacks Pole názvů hacků.
	 */
	public function setHacks(array $hacks)
	{
		$this->_hacks = $hacks;
		$this->_export->setHacks($hacks);
	}
	
	public function setDataPathPrefix($prefix)
	{
		$this->_dataPathPrefix = $prefix;
	}
}
