<?php

/**
 * Backend exportu na RealityMorava.
 *
 * @category   Dalten
 * @package    Export
 * @subpackage Api
 */
class Dalten_Export_Api_Backend_RealityMorava implements Dalten_Export_Api_Backend_LoggableBackendInterface
{
	const EOL = PHP_EOL; //"\r\n";

	private $_ftpClient = null;
	private $_httpClient = null;
	private $_importURL = '';
	private $_uploadedMaklerPhotos = array();

	/**
	 * Konstruktor.
	 *
	 * @param Dalten_Ftp_ConnectorInterface $ftp       Připojený FTP klient.
	 * @param Dalten_Http_ClientInterface   $http      HTTP klient.
	 * @param string                        $importURL Základ endpoint URL importu.
	 */
	function __construct(Dalten_Ftp_ConnectorInterface $ftp, Dalten_Http_ClientInterface $http, $importURL)
	{
		$this->_ftpClient = $ftp;
		$this->_httpClient = $http;
		$this->_importURL = $importURL;
	}

	/**
	 * Zkontroluje platnost přihlašovacích údajů
	 *
	 * @param string $username Uživatelské jméno.
	 * @param string $password Heslo.
	 *
	 * @return Dalten_Export_Api_ServerResponse Zda se povedlo přihlásit případně proč ne.
	 */
	function checkLogin($username, $password)
	{
		try {
			$this->_ftpClient->getConnection();
		} catch (Dalten_Ftp_Exception_Connect $e) {
			return new Dalten_Export_Api_ServerResponse(false, 500, 'Nelze se připojit k FTP serveru!');
		}

		$rawResponse = $this->_httpClient->get(
			sprintf(
				'%scheck_login.php?name=%s&pwd=%s',
				$this->_importURL,
				urlencode($username),
				urlencode($password)
			)
		);

		$responseLines = explode(self::EOL, $rawResponse);
		if ($responseLines[0]=='OK') {
			return new Dalten_Export_Api_ServerResponse(true);
		} else {
			$message = (isset($responseLines[1]) ? $responseLines[1] : 'Chyba při přihlášení!');
			return new Dalten_Export_Api_ServerResponse(false, 401, $message);
		}
	}

	/**
	 * Přidá nebo smaže nabídku.
	 *
	 * Zda se maže se rozhoduje podle $listingData['akce_exportu'] ('update' nebo 'delete')
	 *
	 * @param string $username         Uživatelské jméno.
	 * @param string $password         Heslo.
	 * @param array  $listingData      Informace o nabídce.
	 * @param array  $userData         Informace o makléři.
	 * @param array  $images           Informace o obrázcích.
	 * @param array  $additionalParams Další informace (skrývání ceny a tak).
	 *
	 * @return Dalten_Export_Api_ServerResponse Zda se povedlo případně proč ne.
	 */
	function addAdvert(
		$username,
		$password,
		array $listingData,
		array $userData,
		array $images,
		array $additionalParams
	)
	{
		$fname = $username . '_'  . $listingData['intid'] . '_' . Date('YmdHis') . '.txt';

		$autorizace = array(
			'name' => $username,
			'pwd' => $password
		);
		$obrazky = $this->_uploadImages($images, $listingData['intid'], $username, $password);

		if (isset($userData['makler_foto'])) {
			$userData['makler_foto'] = $this->_uploadBrokerFoto($userData['makler_foto'], $username);
		}

		$data = $autorizace + $listingData + $this->_formatImages($obrazky) + $userData;
		$txt = $this->_array2txt($data);
		$txt = iconv("utf-8", 'windows-1250//TRANSLIT', normalizer_normalize($txt));

		$this->_ftpClient->putContent($txt, $fname);
		$rawResponse = $this->_httpClient->get(
			sprintf(
				'%simport.php?name=%s&pwd=%s&file=%s',
				$this->_importURL,
				urlencode($username),
				urlencode($password),
				urlencode($fname)
			)
		);
		$resp = explode(self::EOL, $rawResponse);
		if ($resp[0] == 'OK') {
			$return = new Dalten_Export_Api_ServerResponse(true);
            if (isset($resp[1])) {
                $respDetaily = explode('|',$resp[1]);
                if (isset($respDetaily[3])) {
                    $return->setData([
                        'detailUrl' => $respDetaily[3]
                    ]);
                }
            }
            return $return;
		}
		if (isset($resp[1])) {
			$err = $resp[1];
		} else {
			$err = 'Nějaká neznámá chybka.';
		}
		return new Dalten_Export_Api_ServerResponse(false, 100, $err);
	}

	/**
	 * Zjistí podle hashe které obrázky už jsou na serveru, a ty co ješte nejsou uploaduje.
	 *
	 * @param array  $images   Pole s obrázky.
	 * @param string $id       ID vyexportované nabídky.
	 * @param string $username Uživatelské jméno
	 * @param string $password Heslo.
	 *
	 * @return array Pozměněné pole s obrázky, přidává se md5 souboru a klíč soubor obsahuje jméno na serveru.
	 */
	private function _uploadImages(array $images, $id, $username, $password)
	{
		$imagesOnServerRaw = $this->_httpClient->get(
			sprintf(
				'%sget_fotolist.php?name=%s&pwd=%s&id_exported=%s',
				$this->_importURL,
				urlencode($username),
				urlencode($password),
				urlencode($id)
			)
		);

		$imagesOnServer = explode(self::EOL, $imagesOnServerRaw);
		$remotesHashes = array();
		if ($imagesOnServer[0]=='OK') {
			array_shift($imagesOnServer);
			foreach ($imagesOnServer as $image) {
				$tmp = explode('|', $image);
				if (isset($tmp[2])) {
					$remotesHashes[ $tmp[2] ] = true;
				}
			}
		}

		foreach ($images as $ord=>$image) {
			$fileHash = md5_file($image['soubor']);
			$images[$ord]['md5'] = $fileHash;
			$remoteFn = $this->_hashWithLoginAndExt($image['soubor'], $username, $fileHash);
			if (!isset($remotesHashes[$fileHash])) {
				$this->_ftpClient->put($image['soubor'], $remoteFn, FTP_BINARY);
				//nezapomenout binary, nechceme Glitch art
			}
			$images[$ord]['soubor'] = $remoteFn;
		}

		return $images;
	}

	/**
	 * Zformátuje informace o souboru do formátu pro funkci _array2txt.
	 *
	 * @param array $images Pole informací o obrázcích.
	 *
	 * @return array Převedené pole.
	 */
	private function _formatImages(array $images)
	{
		$ret = array();
		foreach ($images as $i=>$image) {
			$ret[sprintf('obrazek%stitle', $i+1)] = $image['soubor'];
			$ret[sprintf('obrazek%shash', $i+1)] = $image['md5'];
			$ret[sprintf('obrazek%stext', $i+1)] = $image['popis'];
		}
		return $ret;
	}

	/**
	 * Převede pole do textového formátu:
	 *
	 * <pre>
	 * klíč1: hodnota1
	 * klíč2: hodnota2
	 * ...
	 * </pre>
	 *
	 * Pokud je obsahuje hodnota znaky nových řádků jsou převedeny na mezery.
	 *
	 * @param array $data Pole vstupních dat.
	 *
	 * @return string Zformátovaný text.
	 */
	private function _array2txt(array $data)
	{
		$ret = '';
		foreach ($data as $k=>$v) {
			if (!is_null($v) && $v!='') {
				$ret .= $k . ': ' . str_replace(array("\r\n","\r","\n"), array(' ', ' ', ' '), $v) . PHP_EOL;
			}
		}
		return $ret;
	}

	/**
	 * Složí nový název souboru z předaného hashe a přípony souboru a loginu.
	 *
	 * @param string $fname Původní název souboru.
	 * @param string $login Uživatelské jméno.
	 * @param string $hash  Hash souboru.
	 *
	 * @return string Nový název ve tvaru <$login>_<$hash>.<$ext>
	 */
	private function _hashWithLoginAndExt($fname, $login, $hash)
	{
		$matches = array();
		preg_match('/.*\.(\w+)$/', $fname, $matches); // bere příponu souboru
		return sprintf('%s_%s.%s', $login, $hash, $matches[1]);
	}

	/**
	 * Odešle foto makléře (ale pouze pokud už ho neposílala) a vrátí název odeslaného souboru.
	 *
	 * @param string $fname Jméno souboru s fotkou makléře.
	 * @param string $login Login uživatele (skládá z něj jméno fotky).
	 *
	 * @return string Jméno odeslaného souboru nebo NULL pokud neexistuje.
	 */
	private function _uploadBrokerFoto($fname, $login)
	{
		if (!file_exists($fname)) {
			return null;
		}
		$fileHash = md5_file($fname);
		$newFname = $this->_hashWithLoginAndExt($fname, $login, $fileHash);
		if (!in_array($newFname, $this->_uploadedMaklerPhotos)) {
			$this->_ftpClient->put($fname, $newFname, FTP_BINARY);
			$this->_uploadedMaklerPhotos[] = $newFname;
		}
		return $newFname;
	}

    /**
     * Stáhne seznam nabídek (s URL nabídek)
     *
     * @param string $username Přihlašovací jméno.
     * @param string $password Heslo.
     *
     * @return Dalten_Export_Api_ServerResponse Odpověď serveru.
     */
    public function listListings($username, $password)
    {
        $rawResponse = $this->_httpClient->get(
            sprintf(
                '%simport.php?name=%s&pwd=%s&url=1',
                $this->_importURL,
                urlencode($username),
                urlencode($password)
            )
        );
        $resp = explode(self::EOL, $rawResponse);
        if ($resp[0] == 'OK') {
            array_shift($resp); // odstraní OK
            $listingList = [];
            foreach ($resp as $line) {
                $fields = explode('|', $line);
                $listingList[] = [
                    'id' => $fields[0],
                    'detailUrl' => $fields[1]
                ];
            }
            return new Dalten_Export_Api_ServerResponse(true, 200, 'OK', $listingList);
        }
        if (isset($resp[1])) {
            $err = $resp[1];
        } else {
            $err = 'Nějaká neznámá chybka.';
        }
        return new Dalten_Export_Api_ServerResponse(false, 500, $err);
    }

    public function topListing($username, $password, array $listingData, array $additionalParams = array())
    {
        $fname = $username . '_'  . $listingData['intid'] . '_' . Date('YmdHis') . '.txt';

        $data = [
            'name' => $username,
            'pwd' => $password,
            'intid' => $listingData['kod'],
            'akce' => 'top'
        ];
        $txt = $this->_array2txt($data);

        $this->_ftpClient->putContent($txt, $fname);
        $rawResponse = $this->_httpClient->get(
            sprintf(
                '%simport.php?name=%s&pwd=%s&file=%s',
                $this->_importURL,
                urlencode($username),
                urlencode($password),
                urlencode($fname)
            )
        );
        $resp = explode(self::EOL, $rawResponse);
        if ($resp[0] == 'OK') {
            if (isset($resp[1])) {
                // níže údaje o utracených penězích za topování, kdyby se do budoucna hodily
                $respDetaily = explode('|',$resp[1]);
                $cenaTopovani = $respDetaily[2];
                $zustatekPoTopovani = $respDetaily[3];
            }
            return new Dalten_Export_Api_ServerResponse(true, 200, 'Úspěšně topováno.');
        }

        return new Dalten_Export_Api_ServerResponse(false, 500, 'Nabídku se nepodařilo vytopovat.');
    }

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

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