<?

/**
 * $Id: Router.mod.php 394 2008-05-28 19:28:03Z dakl $
 * Router przetwarzajacy url na parametry
 *
 */
class Router {

	public static $ACT_URL = '__act_url_*&54__';
	public static $PREV_URL = '__prev_url_*&54__';
	/**
	 * Zdefiniowane urle
	 *
	 * @var array
	 */
	static public $route = array();
	/**
	 * Zdefiniowane urle
	 *
	 * @var array
	 */
	static public $routeDb = array();
	/**
	 * Zdefiniowane przekierowania
	 * @var array
	 */
	static public $redirect = array();
	/**
	 * Delimiter w urlach
	 *
	 * @var unknown_type
	 */
	static private $delimiter = URL_DELIMITER;
	/**
	 * Elementy stale do usuniecia z urli
	 *
	 * @var unknown_type
	 */
	static private $cutoff = array(APPLICATION_FILE_TYPE);
	/**
	 * Kontroler
	 *
	 * @var unknown_type
	 */
	static private $controller;
	/**
	 * Metoda
	 *
	 * @var unknown_type
	 */
	static private $method;
	/**
	 * Parametry
	 *
	 * @var unknown_type
	 */
	static private $param;
	/**
	 * Konfiguracja kontrolera
	 *
	 * @var unknown_type
	 */
	static private $config;
	/**
	 * Parametr odpowadajacy za zmuszenie kontrolera, by przepuszczal tylko zdefiniowane i zwalidowane urle
	 *
	 * @var unknown_type
	 */
	static public $forceExactRoute = false;
	/**
	 * Parametr odpowadajacy za odwrocenie tablicy z prametrami (akcje na poczatku a idki na koncu)
	 *
	 * @var boolean
	 */
	static public $reverseRoute = false;
	/**
	 * Parametr odpowadajacy za wycinanie z parama nazwy kontrolera i metody
	 *
	 * @var boolean
	 */
	static public $controllerMethodSeek = true;
	/**
	 * Parametr odpowadajacy za wycinanie z parama ostatniego pola gdy ilość jest nieparzysta
	 *
	 * @var boolean
	 */
	static public $parseLang = true;
	static public $curLang = 'pl';
	static public $arrayLang = array('pl' => 'pl', 'en' => 'en', 'ru' => 'ru', 'de' => 'de');// 'ua' => 'ua', 'fr' => 'fr');
	static public $curLabel = null;
	static public $popParamUnpaired = true;
	static public $xssRemover = false;
	static private $serializedParam = null;
	static public $dirRouterCache = '/Strona';
	static public $typeRouterCache = '1';

	/**
	 * Pusty konstruktor
	 *
	 */
	public function __construct() {

	}

	public static function GenerateDbRoutes() {
		$routes = MfRouterDAL::GetArrayObjAll(array());

		//var_dump($routes);
		$routesArray = array();

		if (is_array($routes)) {


			foreach ($routes as $route) {
				$unserialized = null;

				$unserialized = unserialize($route->GetConfig());
				$unserializedParam = unserialize($route->GetParam());
				$unserializedParam['idModule'] = $route->GetIdMfModule();
				$unserializedParam['location'] = $route->GetLocation();
				$lang = $route->GetLang();

				if ($route->GetLocation() == self::$typeRouterCache) {
					
				
				$routesArray[] = array('labelUrl' => $route->GetLabelUrl(), 'uri' => $route->GetUrl(), 'matchUri' => $route->GetMatchUri(), 'controller' => $route->GetController(), 'method' => $route->GetMethod(), 'paramMatrix' => $route->GetParamMatrix(), 'config' => $unserialized, 'paramPush' => $unserializedParam, 'lang' => $lang);
				}
			}
		}

		$file = new FileGenerator();
		$file->AddLine(serialize($routesArray));
		$file->SaveFile(Config::Get('PATH_CORE') . '/temp'.self::$dirRouterCache.'/Router.cache');
	}

	/**
	 * Laduje tablice sciezek z pliku
	 *
	 * @return array
	 */
	static private function GetCacheRoutes() {
		$file = Config::Get('PATH_CORE') . '/temp'.self::$dirRouterCache.'/Router.cache';

		if (is_file($file)) {
			$array = unserialize(file_get_contents($file));
			return $array;
		} else {
			$routes = self::GenerateDbRoutes();

			return $routes;
		}
	}

	/**
	 * Parsuje url
	 *
	 * @return unknown
	 */
	static public function ParseUri() {
		$logger = LoggerManager::getLogger(__CLASS__);

		if (isset($_SERVER['REQUEST_URI'])) {
			if (self::$xssRemover) {
				$preParsed = Utils::RemoveXss($_SERVER['REQUEST_URI']);
			} else {
				$preParsed = $_SERVER['REQUEST_URI'];
			}

			//$parsed = explode('/', $preParsed);
			//echo $preParsed;
			$logger->info($preParsed);
			

			if (Config::Get('APPLICATION_FILE_TYPE')) {
				$exp = explode(Config::Get('APPLICATION_FILE_TYPE'), $preParsed);
				$preParsed = $exp[0];
			}

			$preParsed = str_replace(self::$delimiter, '|', $preParsed);

			//$parsed=str_replace(str_replace('/index.php', '', urlencode($_SERVER['PHP_SELF'])), '', urlencode($preParsed));

			$parsed = str_replace('index.php', '', str_replace(self::$delimiter, '|', $_SERVER['PHP_SELF']));

			if ($parsed != '|') {
				$parsed = str_replace($parsed, '', $preParsed);
			} else {
				if ($preParsed{0} == '|')
				$parsed = substr($preParsed, 1, strlen($preParsed));
				else
				$parsed = $preParsed;
			}

			if (is_array($parsed)) {
				$parsed = end($parsed);
			}

			$parsed = str_replace('|', self::$delimiter, $parsed);

			foreach (self::$cutoff as $cutoff) {
				$parsed = str_replace($cutoff, "", $parsed);
			}

			if (strpos($parsed, "?") !== false) {
				$parsed = substr($parsed, 0, strpos($parsed, "?"));
			}

			if ($parsed == "/") {
				$parsed = "";
			}

			$request = explode(self::$delimiter, $parsed);

			if (self::$reverseRoute == true) {
				$request = array_reverse($request);
			}
			
			$logger->info(serialize($request));

			//print_r($request);
			return $request;
		} else {
			return false;
		}
	}

	/**
	 * Pobiera parametry z urla
	 *
	 * @return unknown
	 */
	static public function GetParam() {
		$logger = LoggerManager::getLogger(__CLASS__.' - '.__METHOD__);
		
		$dbRouting = self::GetCacheRoutes();
		if (is_array($dbRouting)) {

			foreach ($dbRouting as $route) {
				if (!isset($route['lang'])) {
					$route['paramPush']['lang'] = self::$curLang;
					$array['lang'] = self::$curLang;
				} else {
					$route['paramPush']['lang'] = $route['lang'];
					$array['lang'] = $route['lang'];
				}

				$array['controller'] = $route['controller'];
				$array['method'] = $route['method'];
				$array['push'] = $route['paramPush'];
				if (isset($route['paramPush']['paged'])) {
					$array['paged'] = $route['paramPush']['paged'];
				}
				
				//Utils::ArrayDisplay($array);

				//self::AddRoute($route['labelUrl'], $route['uri'], $array);

				if (isset($route['labelUrl'])) {
					self::AddRouteFromDb($route['labelUrl'] ,$route['uri'], $array);
				} else {
					self::AddRouteFromDb('dbRouting_'.$key ,$route['uri'], $array);
				}
			}
		}

		$param = self::ParseUri();

		if (isset($param) && $param != false) {
			if (self::$parseLang == true) {
				if (self::$reverseRoute == true) {
					$lang = array_pop($param);
				} else {
					$lang = array_shift($param);
				}
				if (!key_exists($lang, self::$arrayLang)) {
					$lang = self::$curLang;
				} else {
					$lang = $lang ? $lang : self::$curLang;
				}				
			} else {
				$lang = self::$curLang;
			}


			self::ParseRoute($param);
			
			self::CheckRouting($lang);

			if (is_array(self::$serializedParam) && is_array(self::$param)) {
				self::$param = array_merge(self::$param, self::$serializedParam);
			}

			self::$param['urlParam'] = implode(",", $param);

			if (self::$parseLang == true) {
				self::$param['lang'] = $lang;
				self::$curLang = $lang;

				if (!key_exists(self::$param['lang'], self::$arrayLang)) {
					self::$param['lang'] = self::$curLang;
					self::$curLang = self::$curLang;
				}

				if (!self::$param['lang']) {
					self::$param['lang'] = self::$curLang;
					self::$curLang = self::$curLang;
				}
			} else {
				self::$param['lang'] = self::$curLang;
			}
			$logger->debug('param '.serialize($param));
			$logger->debug('info: '.serialize(array('controller'=>self::$controller, 'method'=>self::$method, 'param'=>self::$param, 'config'=>self::$config)));
			//print_r(array('controller'=>self::$controller, 'method'=>self::$method, 'param'=>self::$param, 'config'=>self::$config));
			//print_r($param);

			return array('controller' => self::$controller, 'method' => self::$method, 'param' => self::$param, 'config' => self::$config);
		} else {
			return false;
		}
	}

	/**
	 * Dodaje url do zdefiniowanych
	 *
	 * @param unknown_type $uri
	 * @param unknown_type $controller
	 * @param unknown_type $method
	 * @param unknown_type $paramMatrix
	 * @param unknown_type $config
	 */
	static public function AddRoute($label, $uri, $param) {
		$controller = null;
		$method = null;
		$paramMatrix = null;
		$config = null;
		$paramPush = null;
		$lang = null;
		$paramPaged = null;
		$paramSorted = null;

		if (isset($param['controller'])) {
			$controller = $param['controller'];
		}
		if (isset($param['method'])) {
			$method = $param['method'];
		}
		if (isset($param['matrix'])) {
			$paramMatrix = $param['matrix'];
		}
		if (isset($param['config'])) {
			$config = $param['config'];
		}
		if (isset($param['push'])) {
			$paramPush = $param['push'];
		}
		if (isset($param['lang'])) {
			$lang = $param['lang'];
		}

		if (isset($param['paged'])) {
			$paramPaged = $param['paged'];
		}
		if (isset($param['sorted'])) {
			$paramSorted = $param['sorted'];
		}

		$matchUriArray = self::UriSerializer($uri, $paramMatrix);
		//Utils::ArrayDisplay('cvb'.$label);

		if (!isset(self::$route[$label])) {
			self::$route[$label] = array('uri' => $uri, 'matchUri' => $matchUriArray[0], 'controller' => $controller, 'method' => $method, 'paramMatrix' => $paramMatrix, 'config' => $config, 'param' => $paramPush, 'variables' => $matchUriArray[1], 'paged' => $paramPaged, 'sorted' => $paramSorted);
		} else {
			throw new CoreException("Label '$label' already defined in routes");
		}
	}

	/**
	 * Dodaje url do zdefiniowanych
	 *
	 * @param unknown_type $uri
	 * @param unknown_type $controller
	 * @param unknown_type $method
	 * @param unknown_type $paramMatrix
	 * @param unknown_type $config
	 */
	static public function AddRouteFromDb($label, $uri, $param) {
		$controller = null;
		$method = null;
		$paramMatrix = null;
		$config = null;
		$paramPush = null;
		$lang = null;
		$paramPaged = null;
		$paramSorted = null;
		//Utils::ArrayDisplay($param);
		if(isset($param['controller'])) {
			$controller = $param['controller'];
		}
		if(isset($param['method'])) {
			$method= $param['method'];
		}
		if(isset($param['matrix'])) {
			$paramMatrix = $param['matrix'];
		}
		if(isset($param['config'])) {
			$config = $param['config'];
		}
		if(isset($param['push'])) {
			$paramPush = $param['push'];
		}
		if(isset($param['lang'])) {
			$lang = $param['lang'];
		}
		if (isset($param['paged'])) {
			$paramPaged = $param['paged'];
		}
		if (isset($param['sorted'])) {
			$paramSorted = $param['sorted'];
		}
		if(isset($param['lang'])) {
			$lang = $param['lang'];
		}

		

		$matchUriArray = self::UriSerializer($uri, $paramMatrix);

		if(!isset(self::$routeDb[$label])) {
			if (self::$parseLang == true) {
				self::$routeDb[$lang][$label] = array('uri'=>$uri, 'matchUri'=>$matchUriArray[0], 'controller'=>$controller, 'method'=>$method, 'paramMatrix'=>$paramMatrix, 'config'=>$config, 'param'=>$paramPush, 'variables'=>$matchUriArray[1], 'paged' => $paramPaged, 'sorted' => $paramSorted, 'lang' => $lang);
			} else {
				self::$routeDb[$label] = array('uri'=>$uri, 'matchUri'=>$matchUriArray[0], 'controller'=>$controller, 'method'=>$method, 'paramMatrix'=>$paramMatrix, 'config'=>$config, 'param'=>$paramPush, 'variables'=>$matchUriArray[1], 'paged' => $paramPaged, 'sorted' => $paramSorted, 'lang' => $lang);
			}
			//Utils::ArrayDisplay(self::$routeDb);
		} else {
			//	throw new CoreException('Label alredy defined in routes');
		}
	}

	/**
	 * Dodaje przekierowanie.
	 * Wykorzystyje regexpowy mechanizm.
	 * @see http://pl.php.net/manual/pl/function.preg-match.php
	 *
	 * @param $code int, kod przekierowania
	 * @param $fromUrl
	 * @param $toUrl
	 *
	 * @example
	 *
	 */
	static public function AddRedirect($code, $fromUrl, $toUrl, $assign = null) {
		self::$redirect[] = array('code' => $code, 'fromUrl' => $fromUrl, 'toUrl' => $toUrl, 'assign' => $assign);
		}

	/**
	 * Zmienia parametr $forceExactRoute
	 *
	 * @param unknown_type $param
	 */
	static public function ForceRouting($param) {
		self::$forceExactRoute = $param;
	}

	/**
	 * Wyciaga dane z urla (kontroler, metode i parametry)
	 *
	 * @param unknown_type $param
	 */
	static private function ParseRoute($param) {
		$logger = LoggerManager::getLogger(__CLASS__.' - '.__METHOD__);
		//print_r($param);
		if (self::$popParamUnpaired == true) {
			if (count($param) % 2 != 0) {
				array_pop($param);
			}
		}



		//na potrzeby admina
		$tempParam = $param;
		if (self::$controllerMethodSeek != true) {
			$controller = array_pop($param);
			if ($controller != '') {
				self::$controller = $controller . 'Controller';
			} else {
				self::$controller = null;
			}
			$method = array_pop($param);
			if ($method != '') {
				self::$method = $method;
			} else {
				self::$method = 'Index';
			}
			//na ptrzeby admina - przywrocenie zpopowanych wartosci w przypadku gdy do URLA w dosi jest doklejone cos
			$param = $tempParam;
		}

		$x = 0;

		if (self::$reverseRoute == true) {
			$param = array_reverse($param);
		}

		foreach ($param as $value) {
			if ($x == 0) {
				$x++;
				$key = $value;
			} else {
				self::$param[$key] = $value;
				$x = 0;
			}
		}
		//Utils::ArrayDisplay($param);
		//self::$method = ucfirst(self::$param['m']);
		//unset(self::$param['m']);
	}

	/**
	 * Serializuje podany url <- experimental
	 *
	 * @param string $uri
	 * @return string
	 */
	static private function UriSerializer($uri, $paramMatrix) {

		$matchUri = $uri;
		$variables = array();
		$itemCount = 0;

		foreach (self::$cutoff as $cutoff) {
			$parsed = str_replace($cutoff, "", $uri);
		}

		$uriArray = array_filter(explode(self::$delimiter, $parsed), create_function('$x', 'return ($x != "");'));

		foreach ($uriArray as $item) {

			if ($item{0} == ':') {
				$itemName = str_replace(":", "", $item);
				$variables[$itemCount] = $itemName;
				if (isset($paramMatrix[$itemName])) {
					$item = $paramMatrix[$itemName];
				} else {
					$item = "(?P<$itemName>[^" . self::$delimiter . "]*)";
				}
			}

			if (isset($itemName)) {
				$matchUri = str_replace(":" . $itemName, $item, $matchUri);
			}

			$itemName = null;
			$itemCount++;
		}

		if (!isset($matchUri)) {
			$matchUri = $uri;
		}


		return array($matchUri, $variables);
	}

	/**
	 * Weryfikuje url ze zdefiniowanymi, parsuje parametry
	 *
	 * @return true/false (pasuj�cy/niepasuj�cy)
	 */
	static private function CheckRouting($lang) {
		$logger = LoggerManager::getLogger(__CLASS__.' - '.__METHOD__);

		self::CheckRedirecting();

		if (self::$parseLang == true) {
			$arrayRoute = array();
			if (isset(self::$routeDb[$lang])) {
				$arrayRoute = self::$routeDb[$lang];
			}
		} else {
			$arrayRoute = self::$routeDb;

		}
		
		//Utils::ArrayDisplay($arrayRoute);

		self::$route = array_merge(self::$route, $arrayRoute);

		foreach (self::$route as $label => $row) {
			$notMatched = false;
			//Utils::ArrayDisplay($row);
			if (self::$forceExactRoute == true) {
				self::$method = null;
				self::$controller = null;
			}

			if (preg_match('(' . $row['matchUri'] . ')', $_SERVER['REQUEST_URI'], $varMatches)) {
				foreach (self::$cutoff as $cutoff) {
					$parsed = str_replace($cutoff, "", $_SERVER['REQUEST_URI']);
				}
				$logger->debug(' '.serialize($parsed));
				//TO JEST POTRZEBNE MAKL
				if(strpos($parsed, "?") !== false) {
					$parsed = substr($parsed, 0, strpos($parsed, "?"));
				}
				$logger->debug(' '.serialize($parsed));
				//MAKL: obcinam url jezli $delimiter jest "/", eliminuje parsowanie url'a
				if (self::$delimiter == "/" && $_SERVER['PHP_SELF'] != '/index.php') {
					$parsedCut =  str_replace('index.php', '', $_SERVER['PHP_SELF']);
					if ($parsed != ''){
						$parsed = str_replace($parsedCut, '', $parsed);
					}
				}
				if ($_SERVER['PHP_SELF'] == '/index.php') {
					$parsed = substr($parsed, 1);
				}
				if(self::$parseLang == true && self::$curLang) {

					$langUrl = $lang.self::$delimiter;

					$parsed = str_replace($langUrl, '', $parsed);

				}
				$logger->debug('sprawdzenie: parsed '.$parsed);
				$logger->debug('z marchUri: '.$row['matchUri']);
				//wycinam koniec znaku '$' zeby można było doklejać dodatkowe parametry 
				if(!preg_match('(^'.$row['matchUri'].')', $parsed)) {
					continue;
				}
				//KONIEC
				$logger->debug('na koiec '.serialize($parsed));
				
				if (is_array($row['paramMatrix'])) {



					$serializedParam = self::$param;
					if (is_array($row['variables'])) {

						foreach ($row['variables'] as $varName) {
							if (isset($varMatches[$varName])) {
								self::$serializedParam[$varName] = $varMatches[$varName];
							}
							//	self::$param[$pkey] = $pvalue;
						}
					}

					foreach ($row['paramMatrix'] as $type => $condition) {
						$validator = new Validator(array('param' => $serializedParam[$type]));
						$validator->AddValidator('param', $condition, '');
						$validator->Validate();
						if ($validator->IsError()) {

							//if(!preg_match($condition, self::$param[$type])) {
							$notMatched = true;
							//}
						}
					}
				}


				if (!$notMatched) {
					if ($row['controller'] != '') {
						self::$controller = $row['controller'];
					}
					if ($row['method'] != '') {
						self::$method = $row['method'];
					}
					if ($row['config'] != '') {
						self::$config = $row['config'];
					}
					if (is_array($row['param'])) {
						foreach ($row['param'] as $pkey => $pvalue) {
							self::$param[$pkey] = $pvalue;
						}
					}
					if (is_array($row['variables'])) {

						foreach ($row['variables'] as $varName) {
							if (isset($varMatches[$varName])) {
								self::$serializedParam[$varName] = $varMatches[$varName];
							}
							//	self::$param[$pkey] = $pvalue;
						}
					}

					self::$curLabel = $label;

					return true;
				} else {
					self::$method = null;
					self::$controller = null;
				}

				return false;
			}
		}

		return false;
	}

	/**
	 * Weryfikuje url z przekierowaniami
	 *
	 * @author Krku
	 */
	private static function CheckRedirecting() {
		//Utils::ArrayDisplay(self::$redirect);
		
		foreach (self::$redirect as $redirect) {
//			Utils::ArrayDisplay(preg_match('(' . $redirect['fromUrl'] . ')', $_SERVER['REQUEST_URI'], $redirectVars));
//		Utils::ArrayDisplay('(' . $redirect['fromUrl'] . ')   '. $_SERVER['REQUEST_URI']);
//		Utils::ArrayDisplay(Config::Get('URL_MAIN'));
		//die();
			if (preg_match('(' . $redirect['fromUrl'] . ')', $_SERVER['REQUEST_URI'], $redirectVars)) {
				$newUrl = $redirect['toUrl'];
				//Utils::ArrayDisplay('new: '.$newUrl);

				/* Kawa�ek kodu pozwalaj�cy na uzyskanie takich rzeczy jak np. tytu� artyku�u podczas gdy nie jest on dost�pny
				 * z stargo url'a a w nowym powinien (jesli nie musi:P) wyst�powa�.
				 */
				if ($redirect['assign']) {
					foreach ($redirect['assign'] as $name => $value) {
						if (is_array($value)) {
							if (isset($value['eval'])) {
								foreach ($redirectVars as $rk => $rv) {
									$value['eval'] = str_replace("\$$rk", $rv, $value['eval']);
								}

								$redirectVars[$name] = eval($value['eval']);
							} else if (isset($value['static'])) {
								$redirectVars[$name] = $value;
							}
						} else {
							$redirectVars[$name] = $value;
						}
					}
				}
			//die();
//				foreach ($redirectVars as $rk => $rv) {
//					$newUrl = str_replace("\$$rk", $rv, $newUrl);
//				}

				$fDoBreak = false;
				switch ($redirect['code']) {
					case 301:
						$description = 'HTTP/1.1 301 Moved Permanently';
						break;
					case 302:
						$description = 'HTTP/1.1 301 Found';
						break;
					default:
						$fDoBreak = true;
				}

				if ($fDoBreak) {
					break;
				}
				
				//Utils::ArrayDisplay($newUrl);

				header($description);
				header('Location: ' . Config::Get('URL_MAIN') .'/'. $newUrl);
				header('Connection: close');
				die();
			}
		}
	}

	/**
	 * Funkcja generuje url.
	 *
	 * @param <string> $label
	 * @param <array> $param
	 * @param <string> $where
	 * @return <string>
	 */
	static public function UrlForLang($label, $lang) {
		if (!isset(self::$routeDb[$lang]) || !$label) {
			return URL_MAIN . '/'. $lang.'/';
		}
		$route = self::$routeDb[$lang];
		
		if (isset($route[$label])) {
			$url = $route[$label]['uri'];

			if (is_array($route[$label]['variables'])) {
				//Utils::ArrayDisplay(self::$route[$label]);
				$tempVariables = $route[$label]['variables'];

				foreach ($tempVariables as $varName) {
					if (isset($param[$varName])) {
						$url = str_replace(':' . $varName, $param[$varName], $url);
						//						$url = preg_replace('/\:' . $varName . '([^\\' . self::$delimiter . '])/', "$param[$varName]$1", $url);
					} else {
						throw new UserException('Mising param: ' . $varName);
					}
				}
			}

			if (self::$parseLang == true) {
				if (!isset($lang)) {
					$langUrl = self::$curLang . self::$delimiter;
				} else {
					$langUrl = $lang . self::$delimiter;
				}
			} else {
				$langUrl = '';
			}

			return URL_MAIN . '/' . $langUrl . $url;
		}
	}
/**
	 * Funkcja generuje url.
	 *
	 * @param <string> $label
	 * @param <array> $param
	 * @param <string> $where
	 * @return <string>
	 */
	static public function GenerateUrl($label = null, $param = null, $where = URL_MAIN) {

		if ($label == null && $param == null) {
			return Config::Get('URL_MAIN');
		}

		if ($label == "current") {
			if (isset($param['label'])) {
				unset($param['label']);
			}

			if (self::$curLabel && self::$curLabel != "current") {
				$label = self::$curLabel;
				$current = true;
			} else {
				$label = null;
			}
		} else {
			$current = false;
		}

		if ($current) {
			if (!is_array($param)) {
				$param = self::$param;
			} else {
				$param = $param + self::$param;
			}
		}

		if ($label == null && sizeof($param) && isset($param['lang'])) {
			return $where . self::$delimiter . (self::$parseLang ? $param['lang'] . self::$delimiter : '') . 'index';
		} else if ($label == null && $param == null) {
			return $where . self::$delimiter . (self::$parseLang ? self::$curLang . self::$delimiter : '') . 'index';
		}
		
		//Utils::ArrayDisplay(self::$route);

		if (isset(self::$route[$label])) {
			$url = self::$route[$label]['uri'];

			if (is_array(self::$route[$label]['variables'])) {
				//Utils::ArrayDisplay(self::$route[$label]);
				$tempVariables = self::$route[$label]['variables'];

				if (isset(self::$route[$label]['sorted'])) {
					if (isset($param[ROUTER_DIR_LABEL])) {
						$tempVariables[] = ROUTER_DIR_LABEL;
						$url = ROUTER_DIR_LABEL . self::$delimiter . ':' . ROUTER_DIR_LABEL . self::$delimiter . $url;
					}
					if (isset($param[ROUTER_SORT_LABEL])) {
						$tempVariables[] = ROUTER_SORT_LABEL;
						$url = ROUTER_SORT_LABEL . self::$delimiter . ':' . ROUTER_SORT_LABEL . self::$delimiter . $url;
					}
				}

				if (isset(self::$route[$label]['paged'])) {
					if (isset($param[ROUTER_PAGE_LABEL])) {
						$tempVariables[] = ROUTER_PAGE_LABEL;
						$url = ROUTER_PAGE_LABEL . self::$delimiter . ':' . ROUTER_PAGE_LABEL . self::$delimiter . $url;
					}
				}

				if ($current) {
					$param2 = explode(",", self::$param['urlParam']);
					$param = $param + $param2;
				}
				if (isset($param[ROUTER_SORT_LABEL])) {
					$tempVariables[] = ROUTER_SORT_LABEL;
					$url = ROUTER_SORT_LABEL . self::$delimiter . ':' . ROUTER_SORT_LABEL . self::$delimiter . $url;
				}

				foreach ($tempVariables as $varName) {
					if (isset($param[$varName])) {
						$url = str_replace(':' . $varName, $param[$varName], $url);
						//						$url = preg_replace('/\:' . $varName . '([^\\' . self::$delimiter . '])/', "$param[$varName]$1", $url);
					} else {
						throw new UserException('Mising param: ' . $varName);
					}
				}
			}

			if (self::$parseLang == true) {
				if (!isset($param['lang'])) {
					$langUrl = self::$curLang . self::$delimiter;
				} else {
					$langUrl = $param['lang'] . self::$delimiter;
				}
			} else {
				$langUrl = '';
			}

			return $where . '/' . $langUrl . $url;
		} else {


			$returnAdd = null;

			$firstFlag = true;

			if ($param == null) {
				return Config::Get('URL_MAIN');
			}

			if (isset($param) && is_array($param)) {

				if (isset($param['_current'])) {
					$tempParam = explode(',', self::$param['urlParam']);

					$oldParam = $param;
					$param = array();

					for ($i = sizeof($tempParam) - 2; $i >= 0; $i -= 2) {
						if (self::$reverseRoute)
						$param[$tempParam[$i + 1]] = $tempParam[$i];
						else
						$param[$tempParam[$i]] = $tempParam[$i + 1];
					}

					$firstFlag = false;

					$param = array_merge($param, $oldParam);

					unset($param['_current']);
				}

				$urlArray = array();

				if (isset($param['_value'])) {//Stara wersja
					$return = explode(',', $param['_value']);

					$controller = array_shift($return);
					$model = array_shift($return);

					if (!empty($model)) {
						$return[] = $model;
					}
					$return[] = $controller;

					unset($param['_value']);

					$returnAdd = implode(self::$delimiter, $return);
				}

				if (isset($param[0]) && count(array_values($param)) == 1) {
					$urlArray = $param;
				} else {

					if (isset($param['_controller'])) {
						$firstFlag = false;
						$urlArray = array_merge(array((isset($param['_action']) ? $param['_action'] : "Index") . URL_DELIMITER . $param['_controller']), $urlArray);
					}

					foreach ($param as $k => $v) {
						if ($k == 'lang') {

							self::$curLang = $v;
						} else {
							if (substr($k, 0, 1) == '_') {
								continue;
							}

							if ($v === null) {
								continue;
							}

							if (in_array($k, $urlArray)) {
								$urlArray[$k] = $v;
							}

							if ($v !== false) {
								if ($firstFlag && self::$controllerMethodSeek == true) {
									$imp = $v . URL_DELIMITER . $k;

									$firstFlag = false;
								} else {
									$imp = $k . URL_DELIMITER . $v;
								}
							} else {
								$firstFlag = false;
								$imp = $k;
							}
						}
						if (isset($imp)) {
							$urlArray = array_merge(array($imp), $urlArray);
						}
					}
				}

				//reakcja na ustawienia routera
				if (self::$reverseRoute == true) {
					$urlArray = array_reverse($urlArray);
				}

				if ($returnAdd != '') {

					$result = implode(self::$delimiter, $urlArray);
					if ($result != '') {
						$return = $returnAdd . self::$delimiter . $result;
					} else {
						$return = $returnAdd;
					}
				} else {
					$return = implode(self::$delimiter, $urlArray);
				}
			} else {
				$current = self::$param['urlParam'];
				$current = str_replace(',', self::$delimiter, $current);
				$return = $current;
			}

			if (self::$parseLang == true) {

				$langUrl = self::$curLang . self::$delimiter;
			} else {
				$langUrl = null;
			}

			$return = $langUrl . $return;
			if ($where == false) {
				return $return . (isset($param['_extension']) ? '.' . $param['_extension'] : Config::Get('APPLICATION_FILE_TYPE'));
			} else {
				if ($return != '') {
					$parentExtension = Config::Get('APPLICATION_FILE_TYPE');
				} else {
					$parentExtension = null;
				}
				return $where . '/' . $return . (isset($param['_extension']) ? '.' . $param['_extension'] : $parentExtension);
			}
		}
	}
	
	

	static public function SaveUrl($param = array()) {
		if (is_array($param) && key_exists('urlParam', $param) && count($param) == 1) {
			$param[$param['urlParam']] = null;
			unset($param['urlParam']);
		}
		$la = SessionProxy::GetValue(self::$ACT_URL);
		SessionProxy::SetValue(self::$PREV_URL, $la);
		SessionProxy::SetValue(self::$ACT_URL, $param);
	}

	static public function DeleteThisUrl() {
		$la = SessionProxy::GetValue(self::$PREV_URL);
		SessionProxy::SetValue(self::$ACT_URL, $la);
	}

	static public function CleanUrlHistory() {
		SessionProxy::SetValue(self::$PREV_URL, array());
		SessionProxy::SetValue(self::$ACT_URL, array());
	}

	static public function GetArrayLang() {
		return self::$arrayLang;
	}

}
?>