<?php

/**
 * Parser class.
 *
 * @author Eugene I. Nezhuta
 */
class RCMS_Object_Parser_Parser {

	/**
	 * Content for parsing
	 *
	 * @var string
	 */
	private $_content = '';

	/**
	 * Config array
	 *
	 * @var string
	 */
	private $_configArray = '';

	/**
	 * Neccessary page data
	 *
	 * @var array
	 */
	private $_pageData = '';

	/**
	 * Cache object
	 *
	 * @var Zend_Cache
	 */
	private $_cache = '';

	/**
	 * No cached widgets
	 *
	 * @var array
	 */
	private $_noCache = array();

	/**
	 * Generator object. Generates all neccessary data
	 *
	 * @see application/app/objects/Generator
	 * @var RCMS_Object_Generator_Generator
	 */
	private $_generator = null;

	/**
	 * Allow parser to add links (Add/Edit) to generated content
	 *
	 * @var boolean
	 */
	private $_addLinks = true;

	/**
	 * SeoParser for SEO operations
	 *
	 * @var RCMS_Object_Parser_SeoParser
	 */
	private $_seoParser = null;

	/**
	 * Search result
	 *
	 * @var RCMS_Object_Parser_SeoParser
	 */
	private $_searchResult = null;

	/**
	 * Is caching disabled
	 *
	 * @var boolean
	 */
	private $_cacheDisabled = false;

	/**
	 * Parser's model
	 *
	 * @var RCMS_Object_Parser_ParserModel
	*/
	protected $_model;

	/**
	 * Constructor
	 *
	 * @param boolean $allowModification
	 * @param string $content
	 * @param array $pageData
	 */
	public function  __construct($content = '', $pageData = '', $allowModification = true, $searchResult = null, $languageId = '') {
//		if(empty ($content)) {
//			throw new Exception ('No content to parse');
//		}
		$this->_addLinks = $this->_cacheDisabled = $allowModification;
		$this->_generator = new RCMS_Object_Generator_Generator($this->_addLinks, null, $languageId);
		$this->_pageData = $pageData;
		$this->_content = RCMS_Tools_Tools::stripSlashesIfQuotesOn($content);
		$this->_searchResult = $searchResult;
		$this->_model = new RCMS_Object_Parser_ParserModel();
		$this->_configArray = $this->_model->selectAllConfigData();

		if(empty ($this->_configArray)) {
			$this->_configArray = null;
		}
		//setting up caching
		$frontendOptions = array(
			'lifetime' => 7200, // cache lifetime of 2 hours
			'automatic_serialization' => true
		);
		$backendOptions = array(
			'cache_dir' => '../public/tmp/cache/' // Directory where to put the cache files
		);
		$this->_cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
	}

	/**
	 * Main entry point for parser
	 *
	 * @return string
	 */
	public function processContent($parseNewsListFlag = null, $isNews = false) {
		if($isNews) {
			$this->_changeMediaPathes();
			$this->_changeCssPath();
			$this->_changeJsPass();
			$this->_parse($parseNewsListFlag,$isNews);
		}
		else {
			$this->_parse();
			$this->_changeMediaPathes();
			$this->_changeCssPath();
			$this->_changeJsPass();
			//lounch pr sculpting
			if((isset($this->_pageData['silo_id']) && $this->_pageData['silo_id']) && !$this->_pageData['is_404page']) {
				$this->_seoParser = new RCMS_Object_Parser_SeoParser($this->_content);
				$this->_content = $this->_seoParser->runPRSculpting($this->_pageData['silo_id']);
			}
		}
		return $this->_content;
	}


	/**
	 * Parse method. Replace containers, variables, etc...
	 *
	 */
	private function _parse($parseNewsListFlag = null, $isNews = false) {
		$variables = $this->_findSysVars();
		$containers = (!$isNews) ? $this->_findContainers() : '';
		if(empty ($variables) && empty ($containers)) {
			return;
		}
		if(!empty($variables)) {
			foreach ($variables as $variable) {
				if($this->_cacheDisabled) {
					$variableCachedContent = '';
				}
				else {
					$variableCachedContent = $this->_loadFromCache($variable . $this->_pageData['id']);
				}
				switch ($variable) {
					case 'page_title':
						$this->_noCache[] = 'page_title';
						if(!$isNews) {
							$replacement = (isset($this->_pageData['header_title']) ? $this->_pageData['header_title'] : '');
						}
						else {
							if(isset($this->_pageData['newsTitle'])) {
								$replacement = $this->_pageData['newsTitle'];
							}
							else {
								$replacement = "News";
							}
						}
					break;
					case 'page_h1':
						if(!$isNews) {
							$this->_noCache[] = 'page_h1';
							$replacement = (isset($this->_pageData['h1']) ? $this->_pageData['h1'] : '');
						}
						else {
							$replacement = '';
						}
					break;
					case 'main_menu':
						$replacement = (!$variableCachedContent) ? $this->_generator->generateMainMenu(false, array(), false) : $variableCachedContent;
					break;
					case 'main_menu_jq':
						$replacement = (!$variableCachedContent) ? $this->_generator->generateMainMenuAccordion(false) : $variableCachedContent;
					break;
					case 'main_menu_exp':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateMainMenu(true, $this->_pageData, false): $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'static_menu':
						$replacement = (!$variableCachedContent) ? $this->_generator->generateStaticMenu() : $variableCachedContent;
					break;
					case 'meta_keywords' :
						$this->_noCache[] = 'meta_keywords';
						if(!$isNews) {
							$replacement = (isset($this->_pageData['meta_keywords']) ? $this->_pageData['meta_keywords'] : '');
						}
						else {
							$replacement = (isset($this->_pageData['newsMetaKeywords']) ? $this->_pageData['newsMetaKeywords'] : '');
						}
					break;
					case 'meta_description':
						$this->_noCache[] = 'meta_description';
						if(!$isNews) {
							$replacement = (isset($this->_pageData['meta_description']) ? $this->_pageData['meta_description'] : '');
						}
						else {
							$replacement = (isset($this->_pageData['newsMetaDescription']) ? $this->_pageData['newsMetaDescription'] : '');
						}
					break;
					case 'pages_list':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generatePagesList($this->_pageData) : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'pages_list_img':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generatePagesListImg($this->_pageData) : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'categories_list':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateCategoriesList(false, false) : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'categories_list_img':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateCategoriesList(true, false) : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'sitemap':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateSiteMap($this->_pageData) : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'category_name':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateCategoryName($this->_pageData['id']) : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'website_url':
						$this->_noCache[] = 'website_url';
						$replacement = $this->_pageData['websiteUrl'];
					break;
					case 'newsscroller':
						if(!$isNews) {
							$this->_noCache[] = 'newsscroller';
							$replacement = $this->_generator->generateNewsScroller();
						}
						else {
							$replacement = '';
						}
					break;
					case 'seotop':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateSeoVar($this->_pageData['id'], 'top') : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'seobottom':
						if(!$isNews) {
							$replacement = (!$variableCachedContent) ? $this->_generator->generateSeoVar($this->_pageData['id'], 'bottom') : $variableCachedContent;
						}
						else {
							$replacement = '';
						}
					break;
					case 'news_folder_url':
						$replacement = $this->_generator->generateNewsFolderUrl();
						break;
					
					case 'search_result':
						if(!$isNews) {
							if($this->_searchResult != null && $this->_searchResult != "Nothing found") {
								$replacement = $this->_generator->generateSearchResult($this->_searchResult);
							}
							if($this->_searchResult== "Nothing found") {
								$replacement = $this->_searchResult;
							}
							if($this->_searchResult == null) {
								$replacement = '';
							}
						}
						else {
							$replacement = '';
						}
					break;
					case 'search_result_img':
						if(!$isNews) {
							if($this->_searchResult != null && $this->_searchResult!= "Nothing found") {
								$replacement = $this->_generator->generateSearchResultImg($this->_searchResult);
							}
							if($this->_searchResult== "Nothing found") {
								$replacement = $this->_searchResult;
							}
							if($this->_searchResult == null) {
								$replacement = '';
							}
						}
						else {
							$replacement = '';
						}
					break;
					case 'newslist':
						if($parseNewsListFlag && $isNews) {
							$replacement = $this->_generator->generateNewsList();
						}
						else {
							$replacement = '';
						}
					break;
					case 'newsitem':
						if(!$parseNewsListFlag && $isNews) {
							$replacement = $this->_generator->generateNewsItem('', '', $this->_pageData);
						}
						else {
							$replacement = '';
						}
					break;

					case 'social_bookmarks_block':
						if(!$isNews) {
							$replacement = $this->_generator->generateSocialBookmarksBlock($this->_pageData);
						}
						else {
							$replacement = '';
						}
					break;

					case 'news_aggregator_block':
						if(!$isNews) {
							$replacement = $this->_generator->generateNewsAggregatorBlock($this->_pageData);
						}
						else {
							$replacement = '';
						}
					break;
					
					default:
						//try to find varriable in varrable_content table
						$this->_noCache[] = $variable;
						$replacement = $this->_generator->generateUnknown($variable);
						if(empty ($replacement)) {
							$replacement = 'unsupported varriable: ' . $variable;
						}
					break;
				}
				if(!$this->_cacheDisabled) {
					$this->_saveToCache($replacement, $variable . $this->_pageData['id']);
				}
				$this->_replaceSysVar($variable, $replacement);
			}
		}

		if(!empty ($containers)) {
			foreach ($containers as $container) {
				$containerParams = $this->_processContainer($container);
				if(!$this->_cacheDisabled) {
					$cacheContainerName = preg_replace('/[^a-zA-Z0-9_]/', '_', $containerParams['name']);
					$containerCachedContent = $this->_loadFromCache($containerParams['type'] . '_' . $cacheContainerName . '_' . $this->_pageData['id']);
				}
				else {
					$containerCachedContent = '';
					$cacheContainerName = $containerParams['name'];
				}
				switch($containerParams['type']) {
					case 'content':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateContentContainer($containerParams['name'], $containerParams['options'], $this->_pageData) : $containerCachedContent;
					break;
					case 'static':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateStaticContent($containerParams['name']) : $containerCachedContent;
					break;
					case 'header':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateHeaderContent($containerParams['name'], $this->_pageData) : $containerCachedContent;
					break;
					case 'staticheader':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateStaticHeaderContent($containerParams['name'], $this->_pageData) : $containerCachedContent;
					break;
					/*case 'googlemap':
						$replacedContent = $this->_generator->generateGoogleMap($containerParams['name']);
					break;*/
					case 'code':
						$this->_noCache[] = 'code_' . $cacheContainerName;
						$replacedContent = $this->_generator->generateCodeContent($containerParams['name'], $this->_pageData);
					break;
					case 'featuredarea':
						$replacedContent =  $this->_generator->generateFeaturedAreaContent($containerParams['name'], $containerParams['options'], $this->_pageData) ;
					break;
					case 'featuredareaimg':
						$replacedContent = $this->_generator->generateFeaturedAreaImgContent($containerParams['name'], $containerParams['options'], $this->_pageData) ;
					break;
					case 'page_list':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateListPages($containerParams['name'], $containerParams['options']) : $containerCachedContent;
					break;
					case 'related':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateRelatedPages($containerParams['name'], $containerParams['options'], $this->_pageData) : $containerCachedContent;
					break;
					case 'relatedimg':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateRelatedPages($containerParams['name'], $containerParams['options'], $this->_pageData, true) : $containerCachedContent;
					break;
					case 'gallery':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateGallery($containerParams) : $containerCachedContent;
					break;
					case 'comments':
						$this->_noCache[] = 'comments_' . $cacheContainerName;
						$replacedContent = $this->_generator->generateComments($containerParams['name'], $containerParams['options'], $this->_pageData,$this->_addLinks);
					break;
					case 'paymentbutton':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generatePaymentButton($containerParams) : $containerCachedContent;
					break;
					case 'rssfeed':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateRssFeedLink($containerParams) : $containerCachedContent;
					break;
					case 'newslist':
						$this->_noCache[] = 'newslist_' . $cacheContainerName;
						$replacedContent = $this->_generator->generateRegularNewsList($containerParams['name'], $containerParams['options'], $this->_pageData);
					break;
					case 'form':
						$this->_noCache[] = 'form_' . $cacheContainerName;
						$replacedContent = $this->_generator->generateForm($containerParams['name'],$containerParams['options'],$this->_pageData);
					break;
					case 'search_form':
						$replacedContent = (!$containerCachedContent) ? $this->_generator->generateSearchForm($containerParams['name']) : $containerCachedContent;
					break;
					case 'plugin':
						//$pluginCacheFlag = $this->_configArray['plugin_cache'];
						$pluginCacheFlag = $this->_model->selectPluginCache($cacheContainerName);
						if($pluginCacheFlag == 0) {
							$this->_noCache[] = 'plugin_' . $cacheContainerName;
							$replacedContent = $this->_generator->generatePluginContent($containerParams['name'], $containerParams['options'], $this->_pageData);
						}
						else{
							$replacedContent = (!$containerCachedContent) ? $this->_generator->generatePluginContent($containerParams['name'], $containerParams['options'], $this->_pageData) : $containerCachedContent;
						}
					break;
					case 'swapper':
					case 'imgrotator':
						$this->_noCache[] = 'imgrotator_' . $cacheContainerName;
						$replacedContent = $this->_generator->generateSwapper($containerParams, md5(microtime()));
					break;
					case 'pageslist':
						$this->_noCache[] = 'pageslist_' . $cacheContainerName;
						$replacedContent = $this->_generator->generateListPages($containerParams['name'], $containerParams['options']);
					break;
					case 'xrss':
						$replacedContent =  $this->_generator->generateExternalRSS($containerParams['name'], $containerParams['options'], $this->_pageData);
					break;
                    case 'product':
                        $replacedContent = $this->_generator->generateProductContent($containerParams);
                        break;
                    case 'productlist':
                        $replacedContent = $this->_generator->generateProductListContent($containerParams);
                        break;
					default:
						$replacedContent = 'wrong container type';
					break;
				}
				if(!$this->_cacheDisabled) {
					$this->_saveToCache($replacedContent, $containerParams['type'] . '_' . $cacheContainerName . '_' . $this->_pageData['id']);
				}
				$this->_replaceContainer($containerParams, $replacedContent);
			}
		}

		$this->_parse($parseNewsListFlag,$isNews);
	}

	/**
	 * Replace system varriables
	 *
	 * @param string $variable
	 * @param string $replace
	 */
	private function _replaceSysVar($variable, $replace) {
		$this->_content = str_replace('{$'.$variable.'}', $replace, $this->_content);
	}

	/**
	 * Find containers in content
	 *
	 * @return array
	 */
	private function _findContainers() {
		preg_match_all('/{\$([\w]+:[\w\s-:,\p{L}\p{M}\p{P}\?\&=~+@#\&\/]+)}/u', $this->_content, $found);
		return $found[1];
	}

	/**
	 * Find system varriables in content
	 *
	 * @return array
	 */
	private function _findSysVars() {
		preg_match_all('/{\$([^:][\w]+)}/', $this->_content, $found);
		return $found[1];
	}


	/**
	 * Prepare containers for parsing
	 *
	 * @param array $containers
	 * @return array
	 */
	private function _processContainer($container) {
		$exploded = explode(':', $container);
		$containerData = array(
			'type' => $exploded[0],
			'name' => $exploded[1],
			'options' => array_slice($exploded, 2)
		);
		return $containerData;
	}

	/**
	 * Change pathes of your media to correct ones.
	 *
	 * (i.e. <img src="images/my-image.phg" /> to <img src="PATH_TO_THEME/images/my-image.phg" />)
	 */
	private function _changeMediaPathes() {
		$this->_content = preg_replace('/"\/{0,1}images\/(.*)"/U', '"themes/'. $this->_pageData['currentTheme'] .'/images/$1"', $this->_content);
		$this->_content = preg_replace("/'\/{0,1}images\/(.*)'/U", "'themes/". $this->_pageData['currentTheme'] ."/images/$1'", $this->_content);
	}

	/**
	 * Change path of css to correct one.
	 *
	 */
	private function _changeCssPath() {
		$this->_content = preg_replace('/(<link.*href=")(\/{0,1}.*\.css)(".*>)/U','$1' . $this->_pageData['websiteUrl'] . 'themes/'. $this->_pageData['currentTheme'].'/$2' . '$3' , $this->_content);
	}

	/**
	 * Change path of javascripts to correct one.
	 *
	 */
	private function _changeJsPass() {
		$this->_content = preg_replace('/(<script.*src=")(\/{0,1}[A-Za-z0-9-_.]+\.js)(".*>)/U', '$1' . $this->_pageData['websiteUrl'] . 'themes/' . $this->_pageData['currentTheme'] . '/$2' . '$3' , $this->_content);
	}

	/**
	 * Replace container
	 *
	 * @param string $container
	 * @param string $replace
	 */
	private function _replaceContainer($containerParams, $replace) {
		$opts = '';
		if(isset ($containerParams['options'])) {
			if(is_array($containerParams['options'])) {
				foreach ($containerParams['options'] as $option) {
					$opts .= ':' . $option;
				}
			}
			else {
				$opts = $containerParams['options'];
			}
		}
		else {
			$opts = '';
		}
		$this->_content = str_replace('{$'.$containerParams['type'].':'. $containerParams['name']. $opts .'}', $replace, $this->_content);
	}

	private function _loadFromCache($cacheId) {
		$content = $this->_cache->load($cacheId);
		if(!$content) {
			return false;
		}
		return $content;
	}

	private function _saveToCache($content, $cacheId) {
		if(!in_array($cacheId, $this->_noCache)) {
			$this->_cache->save($content, $cacheId);
		}
	}
}
