<?php
/**
 * Export do formátu globálního REMAXu.
 *
 * @category Dalten
 * @package  Export
 */
class Dalten_Export_Rex extends Dalten_Export_AbstractExport
{
	const ZEMEDELSKE_OBJEKTY = 1;
	const KOMERCNI_OBJEKTY = 2;
	const POZEMKY = 3;
	const BYTY = 4;
	const HISTORICKE_OBJEKTY = 5;
	const DOMY_A_VILY = 6;
	const HOTELY = 7;
	const NAJEMNI_DOMY = 8;
	const KOMERCNI_PROSTORY = 9;
	const CHATY = 10;
	const MALE_OBJEKTY = 11;

	const PODTYP_SKLAD = 1;
	const PODTYP_OBCHODNI_CENTRUM = 3;
	const PODTYP_NAKUPNI_STREDISKO = 4;
	const PODTYP_ADMINISTRATIVNI_BUDOVA = 7;

	const PRO_KOMERCNI_VYSTAVBU = 1;
	const PRO_BYDLENI = 2;
	const ZEMEDELSKA_PUDA = 3;
	const LES = 4;
	const LOUKA = 5;
	const ZAHRADA = 6;
	const OSTATNI = 7;

	const PODTYP_HOTEL=1;
	const PODTYP_PENZION=2;
	const PODTYP_RESTAURACE=3;

	const PODTYP_KP_KANCELARE = 1;
	const PODTYP_KP_OBCHODNI = 2;
	const PODTYP_KP_SKLADOVACI = 3;

	const POLOHA_RADOVA = 1;
	const POLOHA_ROHOVA = 2;
	const POLOHA_BLOKOVA = 3;
	const POLOHA_SEPARE = 4;

	const CIL_OBYTNY = 1;
	const CIL_KOMERCNI = 2;

	const CIL_O_OSTATNI=93;
	const CIL_O_BYT = 4;
	const CIL_O_CHATA = 5;
	const CIL_O_GARAZ = 16;
	const CIL_O_GARZONKA = 53;

	const CIL_O_RADOVKA = 38;
	const CIL_O_SAMOSTATNY_DUM = 12;
	const CIL_O_DVOUGENERACNI_DUM=40;
	const CIL_O_ROHOVY_DUM =58;
	const CIL_O_TOWNHOUSE = 39;


	const CIL_O_POZEMEK_KE_STAVBE = 28;
	const CIL_O_POZEMEK_K_ZEMEDELSTVI = 29;
	const CIL_O_POZEMEK = 21;
	const CIL_O_LES = 43;


	const CIL_O_BYTY = 98;

    const CIL_O_ZAMEK = 3;

	const CIL_K_OBCHOD = 1;
	const CIL_K_FARMA = 2;
	const CIL_K_PRUMYSL = 4;
	const CIL_K_POZEMEK = 6;
	const CIL_K_KANCELAR = 7;
	const CIL_K_HOTEL = 12;
	const CIL_K_RESTAURACE = 13;
	const CIL_K_SKLAD = 14;

	private $_REXDataConfig = array();

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

	/**
	 * Kontruktor. Nastavuje závislosti třídy.
	 *
	 * @param Serenity_Config_Config $codebooks     Číselníkové položky (nepoužívá se).
	 * @param Serenity_Config_Config $entities      Definice položek exportu.
	 * @param array                  $REXDataConfig Nastavení specifické pro REMAX Global.
	 *
	 * Například:
	 * <code>
	 * IntegratorID: 40001
	 * RegionID: 40
	 * LanguageID: 49
	 * agents:
	 *   prototype:
	 *     DateJoinedREMAX: "2001-01-01"
	 *     MainAgentSpecialization: 4
	 * offices:
	 *   prototype:
	 *     Latitude: "48.143889"
	 *     Longitude: "17.109722"
	 *     CityID: 6533115
	 * </code>
	 *
	 * Pro pochopení viz kód a dokumentaci exportu.
	 */
	function __construct(
		Serenity_Config_Config $codebooks,
		Serenity_Config_Config $entities,
		array $REXDataConfig)
	{
		parent::__construct($codebooks, $entities);
		if (!isset($REXDataConfig['offices'])) $REXDataConfig['offices'] = array();
		if (!isset($REXDataConfig['agents'])) $REXDataConfig['agents'] = array();
		if (!isset($REXDataConfig['offices']['prototype'])) $REXDataConfig['offices']['prototype'] = array();
		if (!isset($REXDataConfig['agents']['prototype'])) $REXDataConfig['agents']['prototype'] = array();
		$this->_REXDataConfig = $REXDataConfig;
	}

	/**
	 * Přepřipraví data na další zpracování.
	 * Doplní různá IDčka hodnoty podle prototypů kanceláře a makléře.
	 *
	 * @param array  $values     Pole originálních hodnot.
	 * @param array  $config     Nepoužívá se.
	 *                           Jen pro dodržení rozhraní.
	 * @param string $entityName Jméno entity - Property (nemovitost), SalesAssociate (makléř) či Office (kancelář)
	 *
	 * @return array Upravené a doplněné pole.
	 */
	function _format(array $values, $config, $entityName)
	{
		$konfig = $this->_REXDataConfig;
		if ($entityName == 'Property' || $entityName == 'PropertyDescription') {
			$values['LanguageID'] = $konfig['LanguageID'];
		}

		if ($entityName == 'SalesAssociate') {
			$idUzivatele = $values['id'];

			$values['RegionID'] = $konfig['RegionID'];
			$values = $values + $konfig['agents']['prototype'];
			if (isset($konfig['agents'][$idUzivatele])) {
				$values =  $konfig['agents'][$idUzivatele] + $values;
			}
			$values['IntlAgentID'] = $values['jmeno'];
		}

		if ($entityName == 'Office') {
			$idFirma = $values['id_firma'];
			$values['RegionID'] = $konfig['RegionID'];
			$values = $values + $konfig['offices']['prototype'];
			if (isset($konfig['offices'][$idFirma])) {
				$values = $konfig['offices'][$idFirma] + $values;
			}

			if (isset($values['officepicture']) && file_exists($values['officepicture'])) {
				$values['ImageFileName'] = $values['officepicture'];
			}

			$values['IntlOfficeID']=$idFirma;
		}

		return $values;
	}

	/**
	 * Závěrečná funkce převodu.
	 *
	 * U nemovitosti se stará o převedení počtu podlaží, kategorií a ploch.
	 *
	 * U makléře se stará o detekci žen podle koncovky příjmení. (Fuj hack!)
	 *
	 * @param array  $convertedValues Data pozměněná převodem přes Newspeak.
	 * @param array  $originalvalues  Původní data.
	 * @param string $entityName      Jméno entity - Property=nemovitost, SalesAssociate=makléř
	 *
	 * @return array
	 */
	function _convert(array $convertedValues, array $originalvalues, $entityName)
	{
		$konfig = $this->_REXDataConfig;
		if ($entityName=='Property') {
			if (isset($convertedValues['FloorLevel'])) {
				$patro = $convertedValues['FloorLevel'];
				if ($patro == 1) {
					$convertedValues['FloorLevel'] = 21;
				} elseif (($patro > 1) and ($patro < 10)) {
					$convertedValues['FloorLevel'] = $patro + 2;
				} elseif (($patro > 10) or ($patro==10)) {
					$convertedValues['FloorLevel'] = 13;
				} else {
					$convertedValues['FloorLevel'] = 30;
				}
			}

			// nemovitost má mít stejné RegionID jako kancelář
			$convertedValues['RegionID'] = $konfig['RegionID'];

			$categories = $this->convertCategories($originalvalues);
			$areas = $this->convertAreas($originalvalues);

			$convertedValues['Features'] = $this->_convertFeatures($originalvalues);
			$roomNumber = $this->_getRoomCount($originalvalues);
			$convertedValues['TotalNumOfRooms'] = $roomNumber;
			$bedroomNumber = $this->_getBedroomCount($originalvalues);
			$convertedValues['NumberOfBedrooms'] = $bedroomNumber;

			$convertedValues = $convertedValues + $categories + $areas;
		}

		if ($entityName=='SalesAssociate') {
			// detekuje ženské přijmení - Nováková, Bzirská
			// pan Hrdlička či Veverka ovšem nebudou označeni jako ženy
			if (preg_match('~^.*(ov|OV)?(á|Á)\s*$~', $originalvalues['uzivatel_os_prijmeni'])) {
				$convertedValues['Gender'] = 2;
			}


			if (in_array('mazeme-dlouha-cisla-makleru', $this->_hacks)) {
				if (strlen($convertedValues['Phone'])>25) {
					unset($convertedValues['Phone']);
				}
			}
		}

		return $convertedValues;
	}

	/**
	 * Pomocná funkce. Převádí plochu do jejich typů ploch.
	 *
	 * @param array $originalValues Pole s původními informacemi o nemovitosti.
	 *
	 * @return array Pole obsahující všechny nalezené plochy podle jejich systému ploch.
	 */
	function convertAreas($originalValues)
	{
		$typ = $originalValues['nemovitost_typ'];
		$plochy = array();
		switch ($typ) {
			case self::ZEMEDELSKE_OBJEKTY:
				$plochy['LotSizeM2'] = $originalValues['nemovitost_plocha_uzitna'];
				break;
			case self::KOMERCNI_OBJEKTY:
				$plochy['TotalArea'] = $originalValues['nemovitost_plocha_celkova'];
				break;
			case self::POZEMKY:
				$plochy['LotSizeM2'] =  $originalValues['nemovitost_plocha_celkova'];
				break;
			case self::BYTY:
				$plochy['TotalArea'] = $originalValues['nemovitost_plocha_celkova'];
				break;
			case self::HISTORICKE_OBJEKTY:
				//oni nemaji pro egyeb kategorii plochy
				break;
			case self::DOMY_A_VILY:
				$plochy['TotalArea'] = $originalValues['nemovitost_plocha_uzitna'];
				$plochy['LotSizeM2'] = $originalValues['nemovitost_plocha_parcely'];
				break;
			case self::HOTELY:
				$plochy['TotalArea'] = $originalValues['nemovitost_plocha_uzitna'];
				break;
			case self::NAJEMNI_DOMY:
			case self::KOMERCNI_PROSTORY:
			case self::CHATY:
				$nenulove = ( $originalValues['nemovitost_plocha_uzitna']
					? $originalValues['nemovitost_plocha_uzitna'] : (
					$originalValues['nemovitost_plocha_parcely']
						? $originalValues['nemovitost_plocha_parcely'] : 1)
				);
				$plochy['TotalArea'] = $nenulove;
				break;
			case self::MALE_OBJEKTY:
				$plochy['TotalArea'] = $originalValues['nemovitost_plocha_zastavena'];
				break;
			default:
				break;
		}
		if (isset($plochy['TotalArea']) && $plochy['TotalArea']==0) {
			$plochy['TotalArea'] = 1; //plocha nesmí být 0
		}

		return $plochy;
	}

	/**
	 * Odvodí jejich zatřídění nemovitosti do kateghorií dle našich původních informací.
	 *
	 * @param array $originalValues Původní informace o nemovitosti.
	 *
	 * @return array Jejich zatřídění nemovitosti - pole obsahující klíče CommercialResidential a PropertyType.
	 */
	function convertCategories(array $originalValues)
	{
		$c=self::CIL_OBYTNY;
		$p=self::CIL_O_OSTATNI;

		switch ($originalValues['nemovitost_typ']) {
			case self::ZEMEDELSKE_OBJEKTY:
				$c=self::CIL_KOMERCNI;
				$p=self::CIL_K_FARMA;
				break;
			case self::KOMERCNI_OBJEKTY:
				$c=self::CIL_KOMERCNI;
				$p=self::CIL_K_PRUMYSL;
				switch($originalValues['nemovitost_ucel_budovy']) {
					case self::PODTYP_SKLAD:
						$p=self::CIL_K_SKLAD;
						break;
					case self::PODTYP_OBCHODNI_CENTRUM:
					case self::PODTYP_NAKUPNI_STREDISKO:
						$p=self::CIL_K_OBCHOD;
						break;
					case self::PODTYP_ADMINISTRATIVNI_BUDOVA:
						$p=self::CIL_K_KANCELAR;
						break;
					default:
						break;
				}
				break;
			case self::POZEMKY:
				$p=self::CIL_O_POZEMEK;
				switch ($originalValues['nemovitost_druh_pozemku']) {
					case self::PRO_KOMERCNI_VYSTAVBU:
						$c=self::CIL_KOMERCNI;
						$p=self::CIL_K_POZEMEK;
						break;
					case self::PRO_BYDLENI:
						$p=self::CIL_O_POZEMEK_KE_STAVBE;
						break;
					case self::ZEMEDELSKA_PUDA:
						$p=self::CIL_O_POZEMEK_K_ZEMEDELSTVI;
						break;
					case self::LES:
						$p=self::CIL_O_LES;
						break;
					case self::LOUKA:
					case self::ZAHRADA:
					case self::OSTATNI:
						break;
					default:
						break;

				}
				break;
			case self::BYTY:
				$c=self::CIL_OBYTNY;
				if ($originalValues['nemovitost_dispozice']==1 or $originalValues['nemovitost_dispozice']==2) {
					$p=self::CIL_O_GARZONKA;
				} else {
					$p=self::CIL_O_BYT;
				}
				break;
			case self::HISTORICKE_OBJEKTY:
                $c=self::CIL_OBYTNY;
                $p=self::CIL_O_ZAMEK;
                break;
			case self::DOMY_A_VILY:
				switch ($originalValues['nemovitost_poloha_objektu']) {
					case self::POLOHA_RADOVA:
						$p=self::CIL_O_RADOVKA;
						break;
					case self::POLOHA_ROHOVA:
						$p=self::CIL_O_ROHOVY_DUM;
						break;
					case self::POLOHA_BLOKOVA:
						$p=self::CIL_O_TOWNHOUSE;
						break;
					default:
						$p=self::CIL_O_SAMOSTATNY_DUM;
						break;
				}
				break;
			case self::HOTELY:
				$c=self::CIL_KOMERCNI;
				switch ($originalValues['nemovitost_typ_zarizeni']) {
					case self::PODTYP_PENZION:
					case self::PODTYP_HOTEL:
						$p=self::CIL_K_HOTEL;
						break;
					case self::PODTYP_RESTAURACE:
						$p=self::CIL_K_RESTAURACE;
						break;
					default:
						break;
				}
				break;
			case self::NAJEMNI_DOMY:
				$p=self::CIL_O_BYTY;
				break;
			case self::KOMERCNI_PROSTORY:
				$c=self::CIL_KOMERCNI;
				$p=self::CIL_K_PRUMYSL;
				switch ($originalValues['nemovitost_druh_prostor']) {
					case self::PODTYP_KP_KANCELARE:
						$p=self::CIL_K_KANCELAR;
						break;
					case self::PODTYP_KP_OBCHODNI:
						$p=self::CIL_K_OBCHOD;
						break;
					case self::PODTYP_KP_SKLADOVACI:
						$p=self::CIL_K_SKLAD;
						break;
					default:
						break;
				}
				break;
			case self::CHATY:
				$p=self::CIL_O_CHATA;
				break;
			case self::MALE_OBJEKTY:
				$p=self::CIL_O_GARAZ;
				break;
			default:
				break;
		}

		return array('CommercialResidential'=>$c, 'PropertyType'=>$p);
	}

	/**
	 * Zjistí počet místností u nemovitosti.
	 *
	 * @param array $originalValues Původní informace o nemovitosti.
	 *
	 * @return int|null Počet místností nebo null pokud se ho nepodařilo zjistit.
	 */
	protected function _getRoomCount(array $originalValues)
	{
		$ciselnikDispozic = array(
			1 => 1, // Garsoniéra
			2 => 1, // 1+kk
			3 => 2, // 2+kk
			4 => 3, // 3+kk
			5 => 4, // 4+kk
			6 => 5, // 5+kk
			7 => 6, // 6+kk
			8 => 7, // 7+kk
			9 => 2, // 1+1
			10 => 3, // 2+1
			11 => 4, // 3+1
			12 => 5, // 4+1
			13 => 6, // 5+1
			14 => 7, // 6+1
			15 => 8 //7+1
			// 16 => 0, // Atypický
			// 17 => 0 // Jiný
		);

		if ($originalValues['nemovitost_typ']==self::BYTY) {
			$dispozice = $originalValues['nemovitost_dispozice'];
			if (isset($ciselnikDispozic[$dispozice])) {
				return $ciselnikDispozic[$dispozice];
			}
		}
		return null;
	}

	/**
	 * Zjistí počet ložnic u nemovitosti.
	 *
	 * @param array $originalValues Původní informace o nemovitosti.
	 *
	 * @return int|null Počet místností nebo null pokud se ho nepodařilo zjistit.
	 */
	protected function _getBedroomCount(array $originalValues)
	{
		$ciselnikDispozic = array(
			1 => 1, // Garsoniéra
			2 => 1, // 1+kk
			3 => 1, // 2+kk
			4 => 2, // 3+kk
			5 => 3, // 4+kk
			6 => 4, // 5+kk
			7 => 5, // 6+kk
			8 => 6, // 7+kk
			9 => 1, // 1+1
			10 => 2, // 2+1
			11 => 3, // 3+1
			12 => 4, // 4+1
			13 => 5, // 5+1
			14 => 6, // 6+1
			15 => 7 //7+1
			// 16 => 0, // Atypický
			// 17 => 0 // Jiný
		);

		if ($originalValues['nemovitost_typ']==self::BYTY) {
			$dispozice = $originalValues['nemovitost_dispozice'];
			if (isset($ciselnikDispozic[$dispozice])) {
				return $ciselnikDispozic[$dispozice];
			}
		}
		return null;
	}

	/**
	 * Najde z původních hodnot seznam Features.
	 *
	 * @param array $originalValues Pole původních hodnot.
	 *
	 * @return array IDčka features.
	 */
	private function _convertFeatures(array $originalValues) {
		$poslanoNejaketopeni = false;
		$features = array();

		// Rozvody
		if ($this->_isAnyChecked($originalValues, 'nemovitost_voda')) {
			$features[] = 302;
		}
		if ($this->_isAnyChecked($originalValues, 'nemovitost_plyn')) {
			$features[] = 276;
		}
		if ($this->_isAnyChecked($originalValues, 'nemovitost_elektrina')) {
			$features[] = 274;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_odpad', 0)) {
			$features[] = 298;
		}

		// Topení
		if ($this->_isAnyChecked($originalValues, 'nemovitost_topeni')) {
			if ($this->_isMultiChecked($originalValues, 'nemovitost_topeni', 6)) {
				$features[] = 286;
				$poslanoNejaketopeni = true;
			}
			if ($this->_isMultiChecked($originalValues, 'nemovitost_topeni', 1) || $this->_isMultiChecked($originalValues, 'nemovitost_topeni', 4)) {
				$features[] = 292;
				$poslanoNejaketopeni = true;
			}
			if ($this->_isMultiChecked($originalValues, 'nemovitost_topeni', 2) || $this->_isMultiChecked($originalValues, 'nemovitost_topeni', 5)) {
				$features[] = 287;
				$poslanoNejaketopeni = true;
			}
			if (!$poslanoNejaketopeni) {
				$features[] = 283;
			}
		}

		// Druh objektu
		if ($this->_isMultiChecked($originalValues, 'nemovitost_druh_objektu', 4)) {
			$features[] = 123;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_druh_objektu', 2)) {
			$features[] = 144;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_druh_objektu', 3)) {
			$features[] = 152;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_druh_objektu', 1)) {
			$features[] = 154;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_druh_objektu', 5)) {
			$features[] = 308;
		}

		// Stav objektu
		if ($this->_isMultiChecked($originalValues, 'nemovitost_stav_objektu', 9)) {
			$features[] = 66;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_stav_objektu', 8)) {
			$features[] = 67;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_stav_objektu', 6)) {
			$features[] = 115;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_stav_objektu', 4)) {
			$features[] = 117;
		}

		// Doprava
		if ($this->_isMultiChecked($originalValues, 'nemovitost_doprava', 1)) {
			$features[] = 139;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_doprava', 3)) {
			$features[] = 140;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_doprava', 0)) {
			$features[] = 100;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_doprava', 4)) {
			$features[] = 102;
		}

		// Občanská vybavenost
		if ($this->_isMultiChecked($originalValues, 'nemovitost_obcanska_vybavenost', 2)) {
			$features[] = 203;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_obcanska_vybavenost', 0)) {
			$features[] = 204;
		}
		if ($this->_isMultiChecked($originalValues, 'nemovitost_obcanska_vybavenost', 4) || $this->_isMultiChecked($originalValues, 'nemovitost_obcanska_vybavenost', 4)) {
			$features[] = 205;
		}

		// Garáž
		if (
			$this->_isChecked($originalValues, 'nemovitost_garaz') ||
			$this->_isMultiChecked($originalValues, 'nemovitost_dalsi_nebytove_prostory', 0) ||
			$this->_isMultiChecked($originalValues, 'nemovitost_ostatni', 3)
		) {
			$features[] = 63;
		}

		// Dvougaráž
		if ($this->_isMultiChecked($originalValues, 'nemovitost_dalsi_nebytove_prostory', 1)) {
			$features[] = 32;
		}

		// Výtah
		if (
			$this->_isChecked($originalValues, 'nemovitost_vytah') ||
			$this->_isMultiChecked($originalValues, 'nemovitost_ostatni', 4)
		) {
			$features[] = 56;
		}

		// Bezbariérový
		if (
			$this->_isChecked($originalValues, 'nemovitost_bezbarierovy') ||
			$this->_isMultiChecked($originalValues, 'nemovitost_ostatni', 1)
		) {
			$features[] = 310;
		}

		//Zbytek
		if ($this->_isChecked($originalValues, 'nemovitost_bazen')) $features[] = 22;
		if ($this->_isChecked($originalValues, 'nemovitost_terasa')) $features[] = 24;
		if ($this->_isChecked($originalValues, 'nemovitost_balkon')) $features[] = 143;
		if ($this->_isMultiChecked($originalValues, 'nemovitost_ostatni_rozvody', 0)) $features[] = 297;

		return $features;
	}

	/**
	 * Vrací je-li v poli $data zaškrtnuté pole $fieldName jako multicheckbox na hodnotě $value.
	 *
	 * @param array  $data      Pole s daty.
	 * @param string $fieldName Název políčka.
	 * @param int    $value     Pořadí zašktávátka.
	 *
	 * @return bool Je to tak?
	 */
	private function _isMultiChecked(array $data, $fieldName, $value) {
		if (isset($data[$fieldName])) {
			if (substr($data[$fieldName], $value, 1)==1) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Vrací je-li v poli $data zaškrnuté cokoliv z multicheckboxu $fieldName.
	 *
	 * @param array  $data      Pole s daty.
	 * @param string $fieldName Název políčka.
	 *
	 * @return bool Je to tak?
	 */
	private function _isAnyChecked(array $data, $fieldName) {
		if (isset($data[$fieldName])) {
			if (strpos($data[$fieldName], '1')===false) {
				return false;
			}
			return true;
		}
		return false;
	}

	/**
	 * Vrací je-li v poli $data zaškrnutá položka $fieldName.
	 *
	 * @param array  $data      Pole s daty.
	 * @param string $fieldName Název políčka.
	 *
	 * @return bool Je to tak?
	 */
	private function _isChecked(array $data, $fieldName) {
		if (isset($data[$fieldName])) {
			return ($data[$fieldName]==1);
		}
		return false;
	}

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