<?
/**
 * Klasa FrontControllera
 *
 */
class FrontController {

	private $loadError = false;
	/**
     * Parametry przekazane przez Router
     *
     * @var array
     */
	private $route;
	/**
     * Katalog z kontrolerami
     *
     * @var string
     */
	private $directory = 'controller';
	/**
     * Kontroler do uruchomienia
     *
     * @var string
     */
	private $controller;
	/**
     * Metoda do wywolania
     *
     * @var string
     */
	private $method;
	/**
     * Parametry dla metody
     *
     * @var array
     */
	private $param;
	/**
     * Obiekt kontrolera
     *
     * @var Object
     */
	private $controllerObj;
	/**
     * Domyslny kontroler
     *
     * @var string
     */
	private $defaultController = 'IndexController';
	/**
     * Konfiguracja kontrolera
     *
     * @var array
     */
	private $config;
	/**
     * Delimiter tytulu strony
     *
     * @var string
     */
	private $titleDelimiter;
	/**
     * Czy tytul ma byc generowany w odwrotnej kolejnosci
     *
     * @var bool
     */
	private $titleReverse = false;


	/**
     * Konstruktor
     *
     */
	public function __construct() {
		$this->route = Router::GetParam();
		//print_r($this->route);
		if(isset($this->route['controller'])) {
			$this->controller = ucfirst($this->route['controller']);
		}
		if(isset($this->route['param'])) {
			$this->param = $this->route['param'];
		}

		if(isset($this->route['method'])) {
			$this->method = ucfirst($this->route['method']);
			$this->param['methodToRun'] = $this->method;
		}
		if(isset($this->route['config'])) {
			$this->config = $this->route['config'];
		}

	}

	public static function dispatchChecker($smarty, $tplFile, $param, $lifetime) {
		if(!$smarty->CacheControl($tplFile, array('cache_id'=> md5($param), 'lifetime'=>$lifetime)) && !Core::GetAppSafeMode()) {
			$smarty->CacheControl($tplFile, array('cache_id'=> md5($param), 'write'=>true));
			return true;
		} else {
			return false;
		}
	}

	public function dispatchTemplate($smarty, $tplFile, $param, $lifetime) {

	}

	/**
     * Zmienia domyslny katalog z kontrolerami
     *
     * @param string $dir
     */
	public function SetDirectory($dir) {
		$this->directory = $dir;
	}

	/**
     * Laduje plik z klasa kontrolera
     *
     */
	private function LoadController() {
		if(is_file($this->directory.'/'.str_replace('_', '/', ucfirst($this->controller)).'.php')) {
			Core::RequireOnce($this->directory.'/'.str_replace('_', '/', ucfirst($this->controller)).'.php');
			Core::RequireOnce($this->directory.'/SharedController.php');
			MFLog::Debug('Loading controller: '.$this->controller);
		} else {
			Core::RequireOnce($this->directory.'/'.ucfirst($this->defaultController).'.php');
			Core::RequireOnce($this->directory.'/SharedController.php');
			MFLog::Debug('Unable to load controller: '.$this->controller.' Loading controller: '.$this->defaultController);
			$this->controller = $this->defaultController;
			$this->loadError = true;
		}
	}

	/**
     * Laduje plik z klasa kontrolera
     *
     */
	private function LoadModule() {
		if(is_file($this->directory.'/'.$this->config['module'].'/'.str_replace($this->config['module'].'_', '', ucfirst($this->controller)).'.php')) {
			Core::RequireOnce($this->directory.'/'.$this->config['module'].'/'.str_replace($this->config['module'].'_', '', ucfirst($this->controller)).'.php');
			Core::RequireOnce($this->directory.'/SharedController.php');
			MFLog::Debug('Loading module: '.$this->config['module'].': '.$this->controller);
		} else {
			Core::RequireOnce($this->directory.'/'.ucfirst($this->defaultController).'.php');
			Core::RequireOnce($this->directory.'/SharedController.php');
			$this->controller = $this->defaultController;
			MFLog::Debug('Unable to load module, Loading controller: '.$this->controller);
		}
	}

	/**
     * Uruchamia obiekt kontrolera
     *
     */
	private function RunController() {
		$exp = explode('_', $this->controller);

		$className = $this->controller;

		if ($this->ValidControllerClass($className)) {
			$this->controllerObj = new $className();
			$method = $this->method;

			if((!method_exists($this->controllerObj, $method) && !method_exists($this->controllerObj, $method.'Action'))) {
				$this->method = 'Index';
			}
			if($this->loadError && ($this->method=='Index' && $this->route['param']['urlParam']!='')) {
				//Utils::ArrayDisplay( $this->route['param']['urlParam']);
				$this->method = 'Error404';
			}
		} else {
			throw new Exception('Brak klasy lub brak dziedziczenia!');
		}
	}

	/**
     * Uruchamia obiekt modulu
     *
     */
	private function RunModule() {
		$className = $this->controller;

		if ($this->ValidControllerClass($className, true)) {
			$this->controllerObj = new $className();
			$method = $this->method;

			if(!method_exists($this->controllerObj, $method) && !method_exists($this->controllerObj, $method.'Action')) {
				$this->method = 'Index';
			}
		} else {
			throw new Exception('Brak klasy lub brak dziedziczenia!');
		}
	}
	/**
     * Przypisuje delimiter tytulu strony
     *
     * @param string $titleDelimiter
     */
	public function SetTitleDelimiter($titleDelimiter) {
		$this->titleDelimiter = $titleDelimiter;
	}

	/**
     * Dodaje element tytulu strony
     *
     * @param string $title
     */
	public function AddTitle($title) {
		//$t = Registry::Get('title');
		//$t[] = $title;
		//Registry::Remove('title');
		//Registry::Set('title', $t);

		$headers = Registry::Get('headers');
		$headers['title'][] = $title;
		Registry::Remove('headers');
		Registry::Set('headers', $headers);
	}

	private function GenerateScriptsVar($t) {
		$script = array();

		if ($t && is_array($t) && sizeof($t)) {
			ksort($t);

			if (count($t)>0) {
				foreach($t as $prio) {
					if ( $prio && is_array($prio) && sizeof($prio) > 0) {
						foreach ($prio as $item) {
							//Utils::ArrayDisplay($item);
							if(isset($item['file']) && $item['file']!='' && !preg_match("((http)(.*))", $item['file'])) {
								$item['file'] = URL_STATIC_CONTENT.'/script/'.$item['file'];
							}
							$script[] = $item;
						}
					}
				}
			}
		} else {
			$script = array();
		}

		return $script;
	}


	private function GenerateCSSVar($t) {
		$script = array();

		if ($t && is_array($t) && sizeof($t)) {
			ksort($t);

			if (count($t)>0) {
				foreach($t as $prio) {
					if ( $prio && is_array($prio) && sizeof($prio) > 0) {
						foreach ($prio as $item) {
							if($item['file']!='' && !preg_match("((http)(.*))", $item['file'])) {
								$item['file'] = URL_STATIC_CONTENT.'/css/'.$item['file'];
							}
							$script[] = $item;
						}
					}
				}
			}
		} else {
			$script = array();
		}

		return $script;
	}
	/**
     * Generuje liste skryptow do wyswietlenia w naglowku
     *
     */
	public function GenerateScripts() {
		$t = Registry::Get('javascript');
		$script = $this->GenerateScriptsVar($t);
		$smarty = Registry::Get('smarty');
		$smarty->assign('javaScript', $script);

		$t = Registry::Get('footerJavascript');
		$script = $this->GenerateScriptsVar($t);
		$smarty = Registry::Get('smarty');
		$smarty->assign('footerJavaScript', $script);


	}


	/**
     * Generuje liste CSS do wyswietlenia w naglowku
     *
     */
	public function GenerateCSS() {

		$t = Registry::Get('headerCSS');
		$script = $this->GenerateCSSVar($t);
		$smarty = Registry::Get('smarty');
		$smarty->assign('headerCSS', $script);

	}
	/**
	 * Generuje opis strony
	 *
	 * @return string
	 */
	private function GenerateDescription() {

		$headers = Registry::Get('headers');

		if(isset($headers['description'])) {
			$desc = $headers['description'];
			$headers['description']=null;
			Registry::Remove('headers');
			Registry::Set('headers', $headers);
			if(is_array($desc[0])) {
				return "";
			} else {
				$desc = strtr($desc[0], "'", "`");
				$desc = stripslashes($desc);
				return $desc;
			}
		}
	}

	/**
     * Odwraca kolejnosc generowania tytulu strony
     *
     */
	private function ReverseTitle() {
		$headers = Registry::Get('headers');
		$t = $headers['title'];
		if(is_array($t)) {
			$t = array_reverse($t);
		}
		$headers['title']=$t;
		Registry::Remove('headers');
		Registry::Set('headers', $headers);
	}

	/**
     * Zmienia parametr generowania tytulu strony
     *
     */
	public function FlipTitle() {
		$this->titleReverse = true;
	}

	/**
     * Generuje tytul strony
     *
     * @return string
     */
	private function GenerateTitle() {
		$headers = Registry::Get('headers');
		//Utils::ArrayDisplay($headers);
		$t = $headers['title'];
		if(count($t)>1) {
			$title = implode($this->titleDelimiter, $t);
		} else if (count($t) == 1) {
			$title = $t[0];
		} else {
			$title = '';
		}
		$headers['title']=null;
		Registry::Remove('headers');
		Registry::Set('headers', $headers);

		return $title;
	}

	/**
     * Generuje strone
     *
     * @return string
     */
	public function Dispatch() {
		$contentCheckout = true;
		$smarty = Registry::Get('smarty');

		$smarty->assign('controller', strtolower(str_replace('Controller', '', $this->controller)));
		$smarty->assign('method', strtolower($this->method));

		if(is_array($this->param)) {
			$cacheParam = implode('-', $this->param);
		} else {
			$cacheParam = $this->method;
		}

		if(isset($_POST)) {
			foreach($_POST as $postParam=>$postValue) {
				//Utils::ArrayDisplay($postParam);
				//Utils::ArrayDisplay($postValue);
				if (!is_array($postValue)) {
					$cacheParam.='-'.$postParam.'-'.$postValue;
				}
				
			}
		}

		$cacheParam = md5($cacheParam);

		if(isset($this->config['module']) && $this->config['module'] != '') {
			$this->LoadModule();
			$this->RunModule();
			$partialPath = ucfirst($this->config['module']).'/';
			$executeAdditional = true;
			if(isset($this->config['actionSet']) && is_array($this->config['actionSet'])) {
				$this->controllerObj->SetActionSet($this->config['actionSet']);
			}
		} else {
			$partialPath = null;
			$this->LoadController();
			$this->RunController();
			$executeAdditional = false;
			if(isset($this->config['actionSet']) && is_array($this->config['actionSet'])) {
				$this->controllerObj->SetActionSet($this->config['actionSet']);
				$executeAdditional = true;
			}
		}

		$method = $this->method;

		$this->controllerObj->SetSmarty($smarty);
		$this->controllerObj->partialTemplate = $method.'.tpl';

		$templatePartialPath = null;
		if(isset($this->config['module'])) {
			$templatePartialPath = $this->config['module'].'/'.str_replace($this->config['module'].'_', '', str_replace('Controller', '', $this->controller));
		} else {
			$templatePartialPath = str_replace('Controller', '', $this->controller);
		}

		$this->controllerObj->templatePath = 'partial/' . str_replace('_', '/', $templatePartialPath) . '/';

		if(Config::Get('SMARTY_INTERNAL_CACHING') == false) {
			$smarty->caching = Config::Get('SMARTY_CACHING_METHOD');
		}

		$template = Registry::Get('smartyTemplate');

		if((Config::Get('SMARTY_INTERNAL_CACHING') == false && !$smarty->CacheControl($template, array('cache_id'=>$this->controller.$this->method.md5($cacheParam), 'lifetime'=>CacheParam::Get('global')))) || Config::Get('SMARTY_INTERNAL_CACHING') != false) {
			//echo"pyk";
			if(Config::Get('SMARTY_INTERNAL_CACHING') == false) {
				$smarty->caching = 0;

			}

			$this->controllerObj->preDispatch($this->param);

			//$smarty->cache_lifetime = CacheParam::Get('global');



			if($this->controllerObj->GetActionRedirect()!=true && $this->controllerObj->GetActionRedirect()!=false) {
				$method = $this->controllerObj->GetActionRedirect();
			}

			$initMethod = $method . 'Init';

			if (method_exists($this->controllerObj, $initMethod)) {
				$this->controllerObj->$initMethod($this->param);
			}

			// -->
			
			//--MAKL: odpalam wczesniej 
			if($executeAdditional == true) {
				$this->controllerObj->ExecuteAdditionalActions($this->param);
			}

			if((!$this->controllerObj->Init($method, $cacheParam) || $this->controllerObj->CheckLiveMethod($method, $this->param)) && $this->controllerObj->GetActionRedirect()!=true) {

				if($this->controllerObj->CheckLiveMethod($method, $this->param)) {
					$smarty->cache_lifetime = 0;
				}

				$methodAction = $method . 'Action';
				$this->controllerObj->$methodAction($this->param);
				$methodRun = true;
				Registry::Set('methodRun',$methodRun);

			} else {
				$cachedMethod = $method . 'Cached';

				if (method_exists($this->controllerObj, $cachedMethod)) {
					$this->controllerObj->$cachedMethod($this->param);
				}
			}
			$redirectArray = $this->controllerObj->GetRedirect();

			//--MAKL: Przniosłem do odpalenia wczesniej 
			
			

			if(!isset($this->controllerObj->content) && ($redirectArray['time']==='' || ($redirectArray['time']!=='' && $redirectArray['time']>0))){
				//$smarty->assign('breadCrumbs', $this->controllerObj->GetBreadCrumbs());
				//$smarty->cache_lifetime = $this->controllerObj->cacheTime;
				//echo $smarty->cache_lifetime;
				$this->controllerObj->content = $smarty->fetch($this->controllerObj->templatePath.$this->controllerObj->partialTemplate, md5($method.$cacheParam));
				//echo $this->controllerObj->templatePath.$this->controllerObj->partialTemplate;

			}
			$contentCheckout = true;

			if($this->controllerObj->content=='') {
				$contentCheckout = false;
			}

			$smarty->assign('content', $this->controllerObj->content);

			$this->controllerObj->postDispatch($this->param);
		} else {
			if(Config::Get('SMARTY_INTERNAL_CACHING') == false) {
				if($executeAdditional == true) {
					$actionSet = $this->controllerObj->GetActionSet();
					$newActionSet = array();
					foreach($actionSet as $set) {
						if(isset($set['liveMethod']) && $set['liveMethod']==1) {
							$newActionSet[] = $set;
						}
					}
					if(count($newActionSet)>0) {
						$this->controllerObj->SetActionSet($newActionSet);
						$this->controllerObj->ExecuteAdditionalActions($this->param);
					}
				}
			}
		}
		// -->
		$redirectArray = $this->controllerObj->GetRedirect();

		$smarty->assign('headerRedirect', $redirectArray);

		if(isset($redirectArray['time']) && $redirectArray['time']==0 && isset($redirectArray['url']) && $redirectArray['url']!='') {
			// Header('Location: '.$redirectArray['url']);
			Header('Location: '.$redirectArray['url'], true, $redirectArray['code']);
			die();
		}

		if($this->titleReverse == true) {
			$this->ReverseTitle();
		}
		$smarty->assign('pageTitle', $this->GenerateTitle());
		$smarty->assign('pageDescription', $this->GenerateDescription());

		$smarty->assign('pageHeaders', Registry::Get('headers'));





		$this->GenerateScripts();
		//echo $smarty->cache_lifetime;
		$template = Registry::Get('smartyTemplate');

		if(Config::Get('SMARTY_INTERNAL_CACHING') == false) {
			$smarty->caching = Config::Get('SMARTY_CACHING_METHOD');
		}

		if($this->controllerObj->disableTemplates == false && ($this->controllerObj->CheckLiveMethod($method, $this->param) || !$smarty->CacheControl($template, array('cache_id'=>$this->controller.$this->method.md5($cacheParam), 'lifetime'=>CacheParam::Get('global'))))) {
			if(!Core::GetAppSafeMode()) {
				//if($contentCheckout!=false) {//echo"renegerate";
				$smarty->CacheControl($template, array('cache_id'=>$this->controller.$this->method.md5($cacheParam), 'write'=>true,'methodRun' => true));
				//} else {
				//	$cacheFile = $smarty->generateFileName($this->controller.$this->method.md5($cacheParam), $template);
				//	$smarty->touchCacheFile($cacheFile);
				//}
				//return $smarty->Display($template, $this->controller.$this->method.md5($cacheParam), $this->controller.$this->method.md5($cacheParam));
				//if($this->controllerObj->CheckLiveMethod($method, $this->param)) {

				//$a = $this->controllerObj->content;
				//} else {
				$a = $smarty->Fetch($template, $this->controller.$this->method.md5($cacheParam));
				//}

				if ($this->controllerObj->utf8) {
					$a = iconv('iso-8859-2', 'utf-8', $a);
				}

				echo $a;
			} else {
				//totalny wylot
				Header('Location: '.Config::Get('FATAL_ERROR_URL'));
			}

		} else if($this->controllerObj->disableTemplates == false) {

			$a = $smarty->Fetch($template, $this->controller.$this->method.md5($cacheParam));
			if ($this->controllerObj->utf8) {
				$a = iconv('iso-8859-2', 'utf-8', $a);
			}
			echo $a;
		}
	}

	/**
	 * Sprawdza czy klasa istnieje i ma poprawne dziedziczenie.
	 *
	 */
	private function ValidControllerClass($className, $module = false) {
		if (!class_exists($className)) {
			return false;
		}

		if (!class_parents($className) == Array('MainController'=>'MainController', 'Controller'=>'Controller')) {
			if ($module !== true || !class_parents($className) == Array('ModuleController' => 'ModuleController', 'MainController'=>'MainController', 'Controller'=>'Controller')) {
				return false;
			}
		}

		if (!class_implements($className) == Array('ControllerInterface'=>'ControllerInterface')) {
			return false;
		}

		return true;
	}
}

?>