<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package clearFusionCMS\module\property
 * @copyright Copyright (c) 2016 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * propertyPublicController Class
 *
 * Public controller for property module.
 *
 * @package clearFusionCMS\module\property
 */
class propertyPublicController extends cfContentController {

	/**
	 * Storage for item data.
	 *
	 * @var array
	 */
	protected $itemData = null;

	/**
	 * Draw region data.
	 *
	 * @param string $category The type of property to show, buy or rent.
	 * @throws flExceptionNotFound
	 */
	protected function renderProperty($category) {

		// If matched request for an image
		$imageRoute = $this->content->getContainerRoute($this->pageData['id'], 'images/:size/:slug', array(), array('size' => '[tsmlo]', 'slug' => '[a-z0-9_-]+'), '.*');
		$galImageRoute = $this->content->getContainerRoute($this->pageData['id'], 'images/:size/:slug/:galID', array(), array('size' => '[tsmlo]', 'slug' => '[a-z0-9_-]+', 'galID' => '\d+'), '.*');

		if((($params = $imageRoute->match($this->request->getSegments())) || ($params = $galImageRoute->match($this->request->getSegments()))) && preg_match('/^(png|jpg|gif)$/', $params['extension'])) {

			// Convert slug to id
			if(!($propertyID = $this->db->fetchOne('SELECT propertyid FROM cf_property_' . clearFusionCMS::getSite() . ' WHERE regionid=? && slug=? && category=? && published', $this->pageData['container_extra'], $params['slug'], $category)))
				throw new flExceptionNotFound();

			// Get the name of the file
			$fileCfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');
			$idHash = md5($propertyID);
			$baseName = $fileCfg->privateStorage . '/property/' . clearFusionCMS::getSite() . '/' . $idHash[0] . '/' . $idHash[1] . '/' . $propertyID . (isset($params['galID']) ? "-$params[galID]" : '');
			$fileName = $baseName . ($params['size'] == 'o' ? '' : '_' . $params['size']) . '.' . $params['extension'];

			// If file not readable then we need to generate it
			if(!is_readable($fileName)) {
				$baseName .= '.' . $params['extension'];

				// If base file not present then we're done
				if($params['size'] == 'o' || !is_readable($baseName))
					throw new flExceptionNotFound();

				$cfg = clearFusionCMS::getSiteConfig('cfProperty');

				// Get the size information
				$s = $params['size'];
				$w = $cfg->get("{$s}w");
				$h = $cfg->get("{$s}h");
				$crop = $cfg->get("{$s}crop");

				// Scale and cache
				$img = new flImage($baseName);
				$ow = $img->getWidth();
				$oh = $img->getHeight();
				if($crop)
					$img->resizeCrop($w, $h);
				else
					$img->resize($w, $h);

				// If the size doesn't change then copy the original over as better quality
				if($ow == $img->getWidth() && $oh == $img->getHeight())
					@copy($baseName, $fileName);
				else
					$img->save($fileName);
			}

			// Send the file out
			$this->response->setContentType(flMimeTypes::getType($params['extension']))
				->compressOutput(false)
				->setHeader('Content-Disposition', 'inline; filename=' . $params['slug'] . '.' . $params['extension'])
				->setLastModified(filemtime($fileName))
				->setHeader('Expires', gmdate('D, d M Y H:i:s', time() + 608400) . ' GMT') // 1w
				->setHeader('Content-Length', filesize($fileName))
				->sendHeaders();

			readfile($fileName);
		}
		else {
			cfContentFilter::useTemplateEngine($tpl = new cfTemplateEngine($this));
			$infoRoute = $this->content->getContainerRoute($this->pageData['id'], ':slug', array(), array('slug' => '[a-z0-9_-]+'));

			// If property information
			if($params = $infoRoute->match($this->request->getSegments())) {
				$cfg = clearFusionCMS::getSiteConfig('cfProperty');

				// Build and cache the property data
				if(!($this->itemData = clearFusionCMS::getCache()->get($cacheID = '_cms_propertyInfoPage' . $this->request->getSelf()))) {

					// Get the data
					if (!($item = $this->db->fetchRow('SELECT p.*, t.title AS type FROM cf_property_' . clearFusionCMS::getSite() . ' AS p LEFT JOIN cf_property_type_' . clearFusionCMS::getSite() . ' AS t USING(typeid) WHERE slug=? && regionid=? && category=? && published', $params['slug'], $this->pageData['container_extra'], $category)))
						throw new flExceptionNotFound();

					$imgGalleryRoute['.png'] = $this->content->getContainerRoute($this->pageData['id'], "images/:size/$item[slug]/:galID", array(), array(), '.png');
					$imgGalleryRoute['.jpg'] = $this->content->getContainerRoute($this->pageData['id'], "images/:size/$item[slug]/:galID", array(), array(), '.jpg');
					$imgGalleryRoute['.gif'] = $this->content->getContainerRoute($this->pageData['id'], "images/:size/$item[slug]/:galID", array(), array(), '.gif');

					$mainImgRoute = $this->content->getContainerRoute($this->pageData['id'], 'images/o/:slug', array(), array(), $item['fileext']);

					$regions = new propertyRegions($this->db);
					$area = $regions->getNodeData($item['regionid'], array('title'));

					$addr = array();
					if(!empty($item['street1']))
						$addr[] = $item['street1'];
					if(!empty($item['street2']))
						$addr[] = $item['street2'];
					if(!empty($item['city']))
						$addr[] = $item['city'];
					if(!empty($item['state']))
						$addr[] = $item['state'];
					if(!empty($item['postcode']))
						$addr[] = $item['postcode'];
					$addr = join(', ', $addr);

					$period = '';
					if($item['category'] == 'rent') {
						if($item['price_period'] == 'per_week')
							$period = __(' p/w', 'property');
						else if($item['price_period'] == 'per_month')
							$period = __(' p/m', 'property');
					}

					$tenure = array(
						'freehold' => __('Freehold', 'property'),
						'leasehold' => __('Leasehold', 'property'),
						'sharedfreehold' => __('Shared Freehold', 'property'),
						'rental' => __('Rental', 'property')
					);

					$this->itemData = array(
						'property.id'   => $item['propertyid'],
						'property.title' => $item['title'],
						'property.address' => $addr,
						'property.price' => $cfg->curleft . number_format($item['price'], $cfg->numdecimals, $cfg->decpoint, $cfg->thoussep) . $cfg->curright . $period,
						'property.deposit' => $cfg->curleft . number_format($item['deposit'], $cfg->numdecimals, $cfg->decpoint, $cfg->thoussep) . $cfg->curright,
						'property.bedrooms' => $item['bedrooms'],
						'property.bathrooms' => $item['bathrooms'],
						'property.ensuite' => $item['ensuite'],
						'property.reception' => $item['reception'],
						'property.parking' => $item['parking'],
						'property.type' => $item['type'],
						'property.reference' => $item['reference'],
						'property.area' => $area['title'],
						'property.street1' => $item['street1'],
						'property.street2' => $item['street2'],
						'property.city' => $item['city'],
						'property.state' => $item['state'],
						'property.postcode' => $item['postcode'],
						'property.tenure' => $tenure[$item['tenure']],
						'property.shortdesc' => $item['shortdesc'],
						'property.category' => $item['category'],
						'property.regionid' => $item['regionid'],
						'property.lat' => $item['lat'],
						'property.lng' => $item['lng'],
						'property.countryCode' => $item['countrycode'],
						'property.sold' => $item['sold'],
						'property.soldLabel' => $item['category'] == 'buy' ? __('Sold', 'cfProperty') : __('Rented', 'cfProperty'),
						'meta_title' => $item['meta_title'],
						'meta_description' => $item['meta_description'],
						'meta_keywords' => $item['meta_keywords']
					);

					// Get the features
					$features = propertyFeatures::getInstance()->getFeatures($item['propertyid']);
					$html = '';
					foreach($features as $c) {
						$html .= '<li><strong>' . $c['title'] . '</strong><ul>';
						foreach($c['features'] as $f) {
							$html .= '<li>' . $f . '</li>';
						}
						$html .= '</ul></li>';
					}
					$this->itemData['property.features'] = empty($html) ? '' : "<ul>$html</ul>";

					// Get the field data
					$first = true;
					$fieldContent = $fieldMenu = '';
					$flds = $this->db->fetchAll('SELECT fldid,fieldname,snippet FROM cf_property_flds_' . clearFusionCMS::getSite() . ' ORDER BY disporder');
					foreach($flds as $f) {
						$this->itemData['property.field' . $f['fldid'] . 'Title'] = $f['fieldname'];
						$this->itemData['property.field' . $f['fldid'] . 'Content'] = cfContentFilter::apply($f['snippet'], $item["content$f[fldid]"]);

						if($first) {
							$this->itemData['property.description'] = cfContentFilter::apply($f['snippet'], $item["content$f[fldid]"]);
							$first = false;
						}
						else {
							$fieldContent .= $tpl->parseChunk('property.fieldItem', $d = array(
								'property.fieldTitle' => $f['fieldname'],
								'property.fieldContent' => cfContentFilter::apply($f['snippet'], $item["content$f[fldid]"]),
								'property.fieldID' => "propertyField$f[fldid]",
								'property.id' => $item['propertyid']
							));
							$fieldMenu .= $tpl->parseChunk('property.fieldMenuItem', $d);
						}
					}

					if(!empty($fieldContent)) {
						$this->itemData['property.fieldContents'] = $tpl->parseChunk('property.fieldWrap', array('items' => $fieldContent, 'property.id' => $item['propertyid']));
						$this->itemData['property.fieldMenu'] = $tpl->parseChunk('property.fieldMenuWrap', array('items' => $fieldMenu, 'property.id' => $item['propertyid']));
					}

					// Get the fields for the containing region
					$regionInfo = $this->db->fetchRow('SELECT * FROM cf_property_region_' . clearFusionCMS::getSite() . ' WHERE regionid=?', $item['regionid']);
					$flds = $this->db->fetchAll('SELECT rgnfldid,fieldname,snippet FROM cf_property_rgnflds_' . clearFusionCMS::getSite() . ' ORDER BY disporder');
					foreach($flds as $f) {
						$this->itemData['property.rgnField' . $f['rgnfldid'] . 'Title'] = $f['fieldname'];
						$this->itemData['property.rgnField' . $f['rgnfldid'] . 'Content'] = cfContentFilter::apply($f['snippet'], $regionInfo["content$f[rgnfldid]"]);
					}

					// Build OpenGraph data
					$imgs = "<meta property=\"og:image\" content=\"" . ($this->pageData['customfields']['social_image'] = $mainImgRoute->assemble(array('slug' => $item['slug']), true)) . "\" />\n";
					$result = $this->db->query('SELECT galid,fileext FROM cf_property_gal_' . clearFusionCMS::getSite() . ' WHERE propertyid=? ORDER BY disporder LIMIT 5', $item['propertyid']);
					while($row = $result->fetch())
						$imgs .= "<meta property=\"og:image\" content=\"" . $imgGalleryRoute[$row['fileext']]->assemble(array('size' => 'o', 'galID' => $row['galid']), true) . "\" />\n";
					$imgs .= "<meta name=\"twitter:image\" content=\"" . $this->pageData['customfields']['social_image'] . "\" />\n";

					$ogtitle = empty($item['ogtitle']) ? $item['title'] : $item['ogtitle'];
					$ogdesc = empty($item['ogdesc']) ? $item['shortdesc'] : $item['ogdesc'];

					$this->itemData['_property.openGraphMeta'] = $tpl->parseChunk('property.openGraphMeta', array(
						'locale' => fusionLib::getLocale(),
						'ogtitle' => $ogtitle,
						'ogdesc' => $ogdesc,
						'site' => clearFusionCMS::getSiteName(),
						'url' => $this->request->getSelf(true),
						'images' => $imgs,
						'twitter.site' => clearFusionCMS::getSiteTwitter(),
						'twitter.title' => empty($item['twittertitle']) ? $ogtitle : $item['twittertitle'],
						'twitter.desc' => empty($item['twitterdesc']) ? $ogdesc : $item['twitterdesc'],
						'property.lat' => $item['lat'],
						'property.lng' => $item['lng'],
						'property.placename' => $area['title'],
						'property.countryCode' => $item['countrycode']
					));

					clearFusionCMS::getCache()->store($cacheID, $this->itemData);
				}

				// Include JavaScript
				$tpl->getCodeBuffer()->bufferHeadJS('https://maps.googleapis.com/maps/api/js?key=' . cfGetApiKey::googleMaps())
					->bufferBodyJS('system/modules/property/js/property.js');

				$tpl->registerChunk('openGraphMeta', $this->itemData['_property.openGraphMeta']);

				$tpl->setPlaceholder($this->itemData);
				$this->pageData['title'] = $this->itemData['property.title'];
				$this->pageData['module'] = 'property';
				$this->pageData['contentid'] = $this->itemData['property.id'];
				$this->pageData['meta_description'] = $this->itemData['property.shortdesc'];
				$this->pageData['content'] = $tpl->getChunk('property.infoPage');
				$this->pageData['meta_title'] = $this->itemData['meta_title'];
				$this->pageData['meta_description'] = $this->itemData['meta_description'];
				$this->pageData['meta_keywords'] = $this->itemData['meta_keywords'];
			}
			// If child path data then 404
			else if(count($this->pageData['childpath']))
				throw new flExceptionNotFound();

			// Render the page
			if(!$this->content->renderPage($tpl, $this->pageData))
				throw new flExceptionNotFound();
		}
	}

	/**
	 * Action to draw region data for properties to buy.
	 */
	function buyAction() {
		$this->renderProperty('buy');
	}

	/**
	 * Action to draw region data for properties to rent.
	 */
	function rentAction() {
		$this->renderProperty('rent');
	}
}
