<?php
/**
 * Třída zajišťující běh aplikace
 * 
 * @author milda
 * @copyright Milan Lempera  2009
 *
 */

class Application {

/**
 * instance registru
 * @var object
 */
  protected $registry = NULL;
  
/**
 * Pole udržující informace o hlavním controlleru
 * @var array
 */
  protected $controller = array();
  
/**
 * Pole s informacemi o subControllerech
 * @var array
 */
  protected $subcontrollers = array();
  
/**
 * Pole s názvy exception tříd (např. Appli, načte se AppliException.php)
 * @var array
 */
  protected $exceptiones = array('Appli');

 /**
 * Pole s externími knihovnami, které se načítají při inicializaci
 * @var array
 */
  protected $library = array('dibi.compact.php');
  
  function __construct() {
    
  }

  protected function setConstants() {
    
    if ($_SERVER['SERVER_ADDR'] == '127.0.0.1'){
      define('__LOCALTEST',true);
      define('__DEBUG',true);
    }
    else {
      define('__LOCALTEST',false);
      define('__DEBUG',true);
    }
    
    define('__MULTI_LANG',true);
    define('__DEFAULT_LANG','cs');

    define('DEFAULT_SUBSITE',2);
    define('CACHE', false);                           //  povolení Cache
    define('URL_REWRITE', true);
    define('SEND', 'send');
    define('VIEW', 'view.htm');
    define('ORDER','radit');
    define('ORDER_END','--');
    define('URL', 'http://mvc'.DIRSEP);
    define('DEFAULT_CONTROLLER','kategorie');          //  defaultní controller
    define('DEFAULT_CONTROLLER_ACTION','zobrazit');    //  defaultní akce
    define('ERROR_CONTROLLER', 'error');             //  chybový kontroler
    define('ERROR_CONTROLLER_ACTION', 'index');   //  chybová akce
    
    define('GENERATOR_NAME', 'Shopsys 2.0');
    define('GENERATOR_LINK', 'www.shopsys.web-systems.cz');
    
    define('TEMPLATE', 'templates');
    define('JS_PATH','jscript');
    define('CONTROLLER_SUFIX', 'Controller', false);
    
    define('CSS_ERR','err_mess');
    define('CSS_MESS','mess');
    
    define('ICO_PRIDAT_HODNOTU', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'20_pridat.png" title="Přidat hodnotu" alt="Přidat hodnotu"/>');
    define('ICO_UPRAVIT', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'20_upravit.png" title="Upravit záznam" alt="Upravit"/>');
    define('ICO_HODNOTY', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'20_sipka_vpravo.png" title="Zobrazit hodnoty" alt="Zobrazit hodnoty"/>');
    define('ICO_ZPET', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'20_sipka_vlevo.png" title="Zpět" alt="Zpět"/>');
    define('ICO_NAHORU', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'32_sipka_nahoru.png" width="24" title="Posunout nahoru" alt="Nahoru"/>');
    define('ICO_DOLU', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'32_sipka_dolu.png" width="24" title="Posunout dolů" alt="Dolu"/>');
    define('ICO_NAHLED', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'24_nahled.png" height="20" title="Náhled" alt="Zobrazit náhled"/>');
    define('ICO_SMAZAT', '<img src="'.URL.'image'.DIRSEP.'ico'.DIRSEP.'24_smazat.png" height="20" title="Odstranit záznam" alt="Odstranit záznam"/>');

    define('PATH_VYROBCE', 'uploaded'.DIRSEP.'vyrobce'.DIRSEP);
    define('PATH_PRODUKT', 'uploaded'.DIRSEP.'produkt'.DIRSEP);
    define('PATH_MINI', 'miniatury'.DIRSEP);
    define('PATH_NAHLED', 'nahled'.DIRSEP);
    
    define('MAX_PICT_WIDTH', 1024);
    define('MAX_PICT_HEIGHT', 1024);   

// systémové konstanty
    define('NEKONTROLOVAT', 0);
    define('POVINNY', 1);
    define('NEPOVINNY', 2);
    define('PRAZDNY', 3);
    
    define('NEWLINE',"\n");
    define('MY', 'my');
    define('HASH', 'hash');
    define('MY_URL_BACK', 'my_url_back');
    define('TINY_PRODUCT_INIT', '
    tinyMCE.init({
    	    language : \'en\',
            mode : "textareas",
            entity_encoding : "raw",
    		elements : "text",
            theme : "advanced",
            skin : "o2k7",
            editor_selector : "mceAdvanced",
    		convert_urls : false,
            relative_urls : false,
          	button_tile_map: true,
            paste_create_paragraphs : true,
          	theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6,div",
          	theme_advanced_toolbar_location : "top",
          	theme_advanced_toolbar_align : "left",
            theme_advanced_path_location : "bottom",
          	plugins :"advimage,layer,style,directionality,noneditable,directionality,visualchars,media,nonbreaking,xhtmlxtras,table,paste,advimage,iespell,insertdatetime,preview,print,fullscreen,inlinepopups,save,autosave",
          	file_browser_callback : "ajaxfilemanager",
          	theme_advanced_buttons1 :"save,newdocument,selectall,cut,copy,paste,pastetext,pasteword,media,formatselect,bold,italic,underline,strikethrough,sub,sup,separator,justifyleft, justifycenter, justifyright, justifyfull,separator,outdent,indent,separator,bullist,numlist,alist,ltr,rtl,separator,code,fullscreen",
            theme_advanced_buttons2 :"visualchars,nonbreaking,cite,ins,del,abbr,acronym,insertfile,codetag,charmap,separator,link,unlink,separator,undo,redo,separator,ibrowser,hr,separator,tablecontrols,separator,forecolor,backcolor",
            theme_advanced_buttons3 : "styleselect,styleprops,|,cleanup,image",
          	plugin_insertdate_dateFormat : "%d.%m.%Y",
          	plugin_insertdate_timeFormat : "%H:%M:%S",
          	extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
          	external_link_list_url : "example_data/example_link_list.js",
          	external_image_list_url : "example_data/example_image_list.js",
          	flash_external_list_url : "example_data/example_flash_list.js",
            theme_advanced_resize_horizontal : false,
          	theme_advanced_resizing : true,
          	verify_html : true,
          	imagemanager_handle: \'image\', // Let the imagemanager handle the media type
          	filemanager_handle: \'file,image,media\',
    		
    	});');
  }

  protected function setHandler() {
  	
/***** Exception handler *****/
    	function excHandler($e,$die = true) {
  		if ($e instanceof Appliexception) {
  			switch($e->level) {
  				case 1:
  				case 2:
  				case 3:
  					$excText = ('<div class="err_mess" style="text-align:center;"><h1 style="color:red;">Běh aplikace byl zastaven z důvodu chyby!</h1>
  						<h2 style="font-style:italic;">Chybové hlášení:</h2><h3>'.$e->getMessage().'</h3>
  						Pro odstranění chyby kontaktujte dodavatele systému.<br />Pro lepší identifikaci problému si prosím poznamenejte přesné znění chybového hlášaní. </div>');
  					break;
  				case 4:
  					$excText = ('<div style="text-align:center;"><h1 style="color:red;">Běh aplikace byl zastaven z důvodu chyby!</h1>
  						<h2 style="font-style:italic;">Chybové hlášení:</h2><h3>'.$e->getMessage().'</h3>
  						Pokud se bude chyba opakovat, kontaktujte administrátora.</div>');
  					break;
  					
  				case 5:
  					$excText = ('<div style="text-align:center;"><h1 style="color:red;">Pokoušíte se o operaci pro níž nemáte dostatečná oprávnění!</h1>
  						<h3>Byl zaznamenán pokus o narušení integrity aplikace. <br /> 
  						Chybová zpráva:</h3><h3>'.$e->getMessage().'</h3></div>');
  					break;
  			}
  		}
  		elseif ($e instanceof DibiException OR $e instanceof DibiDriverException ) {
  			if (__DEBUG) {
  				$excText = ('<div style="text-align:center;"><h1 style="color:red;">Běh aplikace byl zastaven z důvodu chyby!</h1>
  						<h3>Chyba při práci s databází: '.$e->getMessage().'</h3>
  						Pokud se bude chyba opakovat, kontaktujte administrátora.</div>');
  			}
  			else {
  				$excText = ('<div style="text-align:center;"><h1 style="color:red;">Běh aplikace byl zastaven z důvodu chyby!</h1>
  						<h3>Chyba při práci s databází</h3>
  						Pokud se bude chyba opakovat, kontaktujte administrátora.</div>');
  			}
  		}
  		else {
  			$excText = ('<div style="text-align:center;"><h1 style="color:red;">Běh aplikace byl zastaven z důvodu chyby!</h1>
  						<h3>Chybové hlášení:</h3><h3 style="font-style:italic;">'.$e->getMessage().'</h3>
  						Pokud se bude chyba opakovat, kontaktujte administrátora.</div>');
  		}
  		
  		Logger::error(1,$e->getMessage());
  		if ($die != false) {
  			die($excText);
  		}
  		else{
  			return $excText;
  		}
  	}
  	
  	set_exception_handler(excHandler);
  }

  protected function setErrorReporting() {
    
    if ( __LOCALTEST == true ) {
      error_reporting(E_ALL);
    }
    else {
      error_reporting(0);
    }
  }
  
  protected function setAutoload() {
    
    function __autoload($class_name) {

      $filename = ucfirst(strtolower($class_name)) . '.php';
      $file = __SITE_PATH.DIRSEP.'include'.DIRSEP.'classes'.DIRSEP.$filename;    
      Debug::addPoint( 'Autoload: '.$file );

      $ret = include($file);
      
      if ( $ret === false ){
        Debug::addPoint( 'Nelze načíst třídu '.$class_name );
        throw new AppliException(4, 'Nelze načíst třídu nutnou pro vykonání požadované operace.', 3);
      }
    }
  }

  protected function loadExceptionClasses() {
    
    foreach( $this->exceptiones as $except_class ) {
      $filename = ucfirst(strtolower($except_class)) . 'Exception.php';
      $file = __SITE_PATH . DIRSEP . 'include' . DIRSEP . 'exceptions' . DIRSEP . $filename;
      Debug::addPoint( 'ExceptionClass : '.$file );

      $ret = include($file);
      
      if ( $ret === false ) {
        Debug::addPoint( 'Nelze zahrnout exceptionClass '.$filename );
        throw new Exception('Nelze načíst třídu výjimek nutnou pro vykonání požadované operace.');
      }
    }

  }

  public function loadController($controller = '') {
    
    if ( empty($controller) ) {
      $name = $this->controller['name'];
    }
    else {
      $name = $controller . CONTROLLER_SUFIX;
    }

    Debug::addPoint('Controller loading:', $name);
    $file = __SITE_PATH . DIRSEP . 'controllers' . DIRSEP . $name . '.php';
    Debug::addPoint( 'Controller : '.$file );
   	$ret = include_once($file);

    if ( $ret === false ){
      Debug::addPoint( 'Nelze zahrnout Controller '.$name );
      Debug::getDebug();
      throw new Exception('Nelze načíst kontroler nutný pro vykonání požadované operace.');
    }
    
    return $name;
        
  }

  protected function loadLibrary() {
    
    foreach($this->library AS $lib){
      $lib_load = include( __SITE_PATH . DIRSEP . 'lib' . DIRSEP . $lib );
      Debug::addPoint( "Library $lib loaded" );

      if ( $lib_load === false ){
        Debug::addPoint( 'Nelze načíst '.$lib );
        throw new AppliException(4,'Nelze načíst knihovny nutné pro běh aplikace.',4);
      }
    }
    
  }
  
  protected function setDbConnection() {
    $xmlSett = new Xml();
    $settElements = array(
   	  'driver' => 'string',
   	  'host' => 'string',
      'username' => 'string',
      'password' => 'string',
	  	'database' => 'string',
      'charset' => 'string'     
      );

      $settings = $xmlSett->fileToArray('include' . DIRSEP  .'settings.php', 'database',$settElements);
      if ($settings === false)
        throw new AppliException(4,'Špatné nastavení databáze.',5);

      dibi::connect($settings, 'default');

  }
  
/**
 * Načtení nastavení z databáze do registry->nastaveni[]
 * @return bool
 */
  protected function loadSettings() {
    /* oblast 
     * 	0 -> nepřihlášený uživatel
     *  1 -> přihlášený uživatel
     *  2 -> admin
     */
    
    $area = 0;   
    if ( $this->registry->user->isLogin() ) {
      if ( $this->registry->admin === true ) {
        $area = 2;
      }
      else {
        $area = 1;
      }
    }
    $result = dibi::query('SELECT N.NAZEV, N.HODNOTA FROM NASTAVENI N WHERE OBLAST <= %i AND STAV = 1;', $area);
    if ($result->count() > 0) {
      $array = array();
      foreach ($result->fetchAssoc('NAZEV') AS $a) {
        $array[$a['NAZEV']] = $a['HODNOTA'];
      }
      $this->registry->nastaveni = $array;
      $this->registry->oblast    = $area;
    }

  }
  
  protected function checkAccess() {

    $result = dibi::query('SELECT
    	CA_ID 
    	,CA_CACHE_TYPE
    	,CA_CACHE_TIME
    FROM
    	UZIVATELE_AKCE 
    WHERE 
    	`CA_CONTROLLER` = %s AND 
    	`CA_AKCE` = %s AND 
    	`UR_UZIV` = %i'
    ,$this->controller['controller'], $this->controller['action'], $this->registry->user->id );  //$user->id

    if ( $result->count() == 0 ) {
    	
    	$log_id = Logger::error(7,'Uživatel nemá oprávnění k provedení požadavku.');
    	if ($this->registry->admin) {
    		$this->controller['controller'] = 'adminerror';
    	}
    	else {
    		$this->controller['controller'] = 'error';
    	}
      $this->controller['name']       = $this->controller['controller'] . 'Controller';
      $this->controller['action']    = 'index';
      $this->controller['args']      = array(403,@$log_id);
      $this->controller['URL']       = $this->controller['controller'].'/'.$this->controller['action'].'/'.@$this->controller['args'][0];

    }
    else {

      list($case_settings) = $result->fetchAll();

      $this->registry->ca_id = $case_settings['CA_ID'];

      if ($case_settings['CA_CACHE_TYPE'] == 0) {
        $this->controller['cache'] = false;
      }
      else {         
        $this->controller['cache'] = true;
        $cache = array();
        $this->registry->cache_type   = $case_settings['CA_CACHE_TYPE'];
        $this->registry->cache_time   = $case_settings['CA_CACHE_TIME'];
        $this->registry->toCache      = true;
      }

    }
    Debug::addPoint('checkAccess - OK');
  }
  
  function unserialize($item){
    if (isset($_SESSION[$item])) {
      return unserialize($_SESSION[$item]);
    }
    else {
      return false;
    } 
  }

  protected function init() {
    
    session_start();
    session_regenerate_id();

    $this->setConstants();
    $this->setHandler();
    $this->setAutoload();
    $this->setErrorReporting();
    $this->loadExceptionClasses();
    $this->loadLibrary();
    
    if (!strstr(@$_GET['route'],'clrReg')) {
      $this->unserialize('registry');
    }
    $this->registry = Registry::getInstance();

    $template = new Template();
    $this->registry->template = $template;
    $jscript = new Jscript();
    $jscript->addFile('jquery-1.3.2.min.js');
    $jscript->addFile('jquery-ui-1.7.1.custom.min.js');
    $jscript->addFile('jquery.datepicker-cs.js');
    $jscript->addFile('jquery.tablesorter.min.js');
    $jscript->addFile('thickbox-compressed.js');
    $jscript->addJqFunction('document', 'ready', '', '', true, true);
    $jscript->addScript('var tb_pathToImage = "'.URL.'image/loadingAnimation.gif";');
    $this->registry->jscript     = $jscript;

    $this->registry->application = $this;
    $this->registry->admin       = false;
//    $this->registry->message     = '';  // zrušeno kvuli message přes persistent registry

    $this->setDbConnection();  
    Debug::addPoint( 'Init - OK' );

  }

  protected function routing() {
    
    $router = new Router();
    $this->controller = $router->setPath(@$_GET['route']);
    $this->checkAccess();
    Debug::addPoint( 'Router ', $this->controller);

  }
  
  protected function checkCache() {
    if ( count($this->controller['args']) <= 1 ) {
      switch ($this->registry->cache_type) {
        case 1:
            $cache_type = ' `TYPE` = 1';
          break;

        case 2:
            $cache_type = ' `TYPE` = 2';
          break;

        case 3:
            $cache_type = ' `TYPE` IN (1,2)';
          break;
      }
      $result = dibi::query('SELECT * FROM `CACHE` WHERE `URL` = %s AND `EXPIRED` > UNIX_TIMESTAMP() AND '.$cache_type.' ORDER BY `TYPE` ASC LIMIT 1', $this->controller['URL'] );
      if ( $result->count() == 1 ) {
        list($cache) = $result->fetchAll();
        $this->registry->toCache = false;
        switch($cache['TYPE']) {
          case 2:
              $this->registry->html_view = $cache['HTML'];
              if ($this->registry->cache_type == 3) {
                $this->registry->cache_type = 1;
                $this->registry->toCache = true;
              }
            break;
          case 1:
              $this->registry->html_page = $cache['HTML'];
            break;
        }
        
        return $cache['TYPE'];
      }
    }
    return false;
  }
  
  protected function loadControllerPost($controller) {
  	if ($this->registry->controller_post_name == $controller ){
  		$_POST = $this->registry->controller_post_array;
  	}
  	else {
  		$this->registry->unsetPersistent('controller_post_array');
  		$this->registry->unsetPersistent('controller_post_name');
  	}
  }
  
  protected function saveControllerPost($controller) {
		$this->registry->addPersistent('controller_post_name',$controller);
  	$this->registry->addPersistent('controller_post_array',$_POST);
  }

  protected function getController() {

    $this->loadController('base');
    if ($this->registry->admin == true) {
      $this->loadController('baseadmin');
    }
    $this->loadController();

		try {

      if (!class_exists($this->controller['name'])) {
      	throw new AppliException(3,'Požadovaný controller není k dispozici. 
      		<b>Controller: </b>'.$this->controller['controller'].'
      		<b>Action: </b>'.$this->controller['action'], 8);
      }

      $controller = new $this->controller['name']();
      $action = $this->controller['action'];
  
      if($action == 'seznam') {	// záloha postu pro nastavení filtru
/*
	     	if (count($_POST) == 0) {
      		echo 'loadControllerPost';
      		$this->loadControllerPost($this->controller['name']);
					Debug::addPoint('Controller: LoadPOST' );
      	}
      	else
*/
      	if (count($_POST) > 0) {
      		$this->saveControllerPost($this->controller['name']);
      		Debug::addPoint('Controller: SavePOST' );
      	}
      }

      if (!method_exists($controller,$action)) {
      	throw new AppliException(3,'Požadovaná funkce controlleru neexistuje!<br />
      		<b>Controller: </b>'.$this->controller['controller'].'<br />
      		<b>Action: </b>'.$this->controller['action'].'<br />', 8);
      }
      Debug::addPoint('Controller: '.$this->controller['name'].'->'.$action );
      $controller->$action($this->controller['args']);

		}
		catch(Appliexception $e){

			$e->checkLevel(3,true);

		}

    if ($this->registry->page_view) {
    	Debug::addPoint( 'echo html_view' );
    	echo $this->registry->html_view;
    	die;
    }
//    $controller->getSubsite();
    Debug::addPoint( 'controller' );

  }
  
  public function errDisplay($e, $arg = array()) {

		if ($this->registry->admin) {
    	$class = 'adminerrorController';
    	$file  = 'adminerror';
    }
    else {
    	$class = 'errorController';
      $file  = 'error';
    }
    $this->registry->html_view = excHandler($e, false);
    $this->loadController($file);
    $controller = new $class();
    $controller->index($arg);

  }
  
  protected function getMenu() {
    
    $this->getUserMenu();
    
    if (!$this->registry->admin) {
    	$this->getCategory();
    }

  }
  
  protected function getUserMenu() {

  	if ($this->registry->admin == true) {
  		$sql = ' AND CA.ID_CA_MENU != 14';
  	}
  	else {
  		$sql = '';
  	}
  	
    $result = dibi::query('SELECT CA.ID, CA.CONTROLLER, CA.AKCE, CA.MENU_USER, CAM.NAZEV AS MENU_SKUPINA
		FROM UZIVATEL U
		INNER JOIN UZIVATEL_ROLE UR ON UR.ID_UZIV = U.ID AND UR.STAV = 1
		INNER JOIN ROLE R ON R.ID = UR.ID_ROLE AND R.STAV = 1
		INNER JOIN ROLE_CAKCE RC ON RC.ID_ROLE = R.ID AND RC.STAV = 1
		INNER JOIN CONTROLLER_AKCE CA ON CA.ID = RC.ID_CAKCE AND CA.STAV = 1 AND CA.MENU_USER IS NOT NULL
		INNER JOIN CA_MENU CAM ON CAM.ID = CA.ID_CA_MENU
		WHERE U.ID = %i '.$sql.'
		ORDER BY CAM.PRIORITA DESC, CA.PRIORITA DESC'
    , $this->registry->user->id);

    if ($result->count() > 0) {
      $res = $result->fetchAssoc('ID');
      $umenu = array();
      $skupina = '';
      foreach($res AS $r) {
        $row = $r->getArrayCopy();
        $echo_skupina = '';
        if ($row['MENU_SKUPINA'] !==  $skupina) {
          if ( !empty($row['MENU_SKUPINA'])) {
            $skupina = $row['MENU_SKUPINA'];
            $echo_skupina = '<li class="umenu_group"><span>'.$skupina.'</span></li>';
          }
        }
        $li = array();
        $li['group'] = $echo_skupina;
        $li['link'] = Tools::umenuLink($r);
        $li['text'] = $row['MENU_USER'];
        $li['li_class'] = 'umenu_li';
        $umenu[] = $li;
      }
      $this->registry->template->setHTML('umenu', $umenu);
    }
  }

  protected function getCategory() {

  	$js = $this->registry->jscript;
  	$js->addFunction('openBranch', 'jQueryElement, noAnimation', "
				jQueryElement.addClass('OPEN').removeClass('CLOSE');
				if(noAnimation)
					jQueryElement.parent().find('ul:first').show();
				else
					jQueryElement.parent().find('ul:first').slideDown();
					");

  	$js->addFunction('closeBranch','jQueryElement, noAnimation',"
			jQueryElement.addClass('CLOSE').removeClass('OPEN');
			if(noAnimation)
				jQueryElement.parent().find('ul:first').hide();
			else
				jQueryElement.parent().find('ul:first').slideUp();
				");

  	$js->addFunction('toggleBranch', 'jQueryElement, noAnimation',"
			if(jQueryElement.hasClass('OPEN'))
				closeBranch(jQueryElement, noAnimation);
			else
				openBranch(jQueryElement, noAnimation);
				");
//.before('<span class=\"grower OPEN\">&nbsp;&nbsp;&nbsp;</span>');
  	$js->addScript("
				if(!$('ul.tree.dhtml').hasClass('dynamized')) {

					$('ul.tree.dhtml span.grower.OPEN').addClass('CLOSE').removeClass('OPEN').parent().find('ul:first').hide();
					$('ul.tree.dhtml').show();
					$('ul.tree.dhtml .selected').parents().each( function() {
						if ($(this).is('ul')) {
							toggleBranch($(this).prev().prev(), true);
						}
					});
					
					$('ul.tree.dhtml .selected').children().each( function() {
						if ($(this).is('ul')) {
							toggleBranch($(this).prev().prev(), true);
						}
					});
					toggleBranch( $('ul.tree.dhtml .selected').prev(), true);
				
					$('ul.tree.dhtml span.grower').click(function(){
						toggleBranch($(this));
					});
					$('ul.tree.dhtml').addClass('dynamized');
				}",'document_ready');

  	$akt_kat = $this->registry->kategorie;

    $result = dibi::query('SELECT K.*,
    		(ROUND((K.PRAVA - K.LEVA -1)/2)) AS DETI,
        IF(K.LEVA <= %i AND K.PRAVA >= %i, 1, 0) AS ROZBALENA
    	FROM KATEGORIE_AKTIVNI K;',$akt_kat['leva'], $akt_kat['prava']);

    if ($result->count() > 0) {

      $res = $result->fetchAssoc('ID');
      $kat = array();
      $deti = array();
      $kategorie = '';
      $hloubka = 1;
      $count = 0;
      $last_id = 0;

      $show_ul = false;
      $show_ul2 = false;
      foreach($res AS $r) {
      	$row = $r->getArrayCopy();
				$class = '';
				$a_class = '';
				$show_ul = false;

				$itemHTML = '';
				$li_end = '</li>';

				if ($count == 0) {
					$li_end = '';
				}

        if ($row['DETI'] == 0) {
        	$class = 'last';
        }
        elseif ($row['ROZBALENA'] == 1) {       	
        	$show_ul = true;
        }

        if ($row['ID'] == $akt_kat['id']) {
        	$class .= ' selected';
        	$a_class = 'class="current"';
        	$show_ul = true;
        }
      
        if ($row['HLOUBKA'] > $hloubka) {
        	$itemHTML .= '<ul'.(($show_ul2)? ' class="show"':''.' id="par_'.$last_id).'"><li class="'.$class.'">';
        	$hloubka++;
        }
        elseif ($row['HLOUBKA'] < $hloubka) {
        	for($i = $hloubka; $i > $row['HLOUBKA']+1; $i--) {
						$hloubka--;
        		$kategorie .= '</ul></li>';
        	}
        	$itemHTML .= '</li></ul>'.$li_end.'<li class="'.$class.'">'; //'.' class="'.$class.'"'.'  id="'.$row['ID'].'"
        	$hloubka--;
        }
        else {
					$itemHTML .= $li_end.'<li class="'.$class.'">';
        }

        $itemHTML .= '<span class="grower">&nbsp;&nbsp;&nbsp;</span><a '.$a_class.' href="'.Tools::CategoryLink($row['REWRITE_LINK']).'">'.$row['NAZEV'].'</a>'.NEWLINE;
        $kategorie .= $itemHTML;
        $last_id = $row['ID'];
        $count++;
        $show_ul2 = $show_ul;
      }	

      for($i = $hloubka; $i > 1;$i--) {
      	$kategorie .= $li_end.'</ul>';
      }

      if ($count > 0) {
					$kategorie .= $li_end;
			}

      $this->registry->template->setHTML('kategorie', $kategorie);
    }
  }
  
  protected function setTemplateConst() {

    $this->registry->template->set('url', URL );

  }

  protected function getTemplate() { 

    $this->registry->template->set('meta_title',        implode(' - ', array($this->registry->meta_title, $this->registry->subsite['server_title']) ) );
    $this->registry->template->set('meta_description',  empty($this->registry->meta_description) ? $this->registry->subsite['server_description'] : $this->registry->meta_description );
    $this->registry->template->set('meta_keywords',     implode(', ', array($this->registry->meta_keywords, $this->registry->subsite['server_keywords']) ) );
    $this->registry->template->set('meta_autor',        $this->registry->nastaveni['autor'] );
    $this->registry->template->set('meta_generator',    GENERATOR_NAME.' - '.GENERATOR_LINK );
    $this->registry->template->set('meta_copyright',    $this->registry->nastaveni['copyright'] );
    $this->registry->template->set('meta_robots',       $this->registry->subsite['robots'] );

    $this->registry->template->setHTML('kosik', $this->registry->kosik->souhrn() );

    $this->registry->template->set('user_is_login', $this->registry->user->login, TRUE);
    if ($this->registry->user->login) {
    	$this->registry->template->set('user_name', $this->registry->user->getName() );
    	$this->registry->template->set('user_aktivni', Tools::dateToCZ($this->registry->user->dt_aktivni) );
    }
    $this->registry->template->setHTML('jsfiles', $this->registry->jscript->JSFile());
    $this->registry->template->setHTML('jscript', $this->registry->jscript->parse());
    
    $this->registry->template->setHTML('content', $this->registry->html_view);
    $this->registry->html_page = $this->registry->template->fetch('master.tpl', true, true);
    Debug::addPoint( 'Template' );

  }

  protected function getHTML() {
    
    echo $this->registry->html_page;
    Debug::addPoint( 'HTML' );

  }
  
  protected function toCache() {

    if ($this->registry->toCache == true) {
      // časem předělat jako proceduru a volat pomocí CRONE 
      dibi::query('DELETE FROM `CACHE` WHERE `EXPIRED` <= UNIX_TIMESTAMP();');
      switch ( $this->registry->cache_type ) {
        case 1:
          dibi::query('INSERT INTO `CACHE` SET `TYPE` = %s, `URL` = %s, `HTML` = %s, `EXPIRED` = %i', 1, $this->controller['URL'], $this->registry->html_page, time() + ($this->registry->cache_time * 60));
          Debug::addPoint( 'Cache page' );
          break;

        case 2:
          dibi::query('INSERT INTO `CACHE` SET `TYPE` = %s, `URL` = %s, `HTML` = %s, `EXPIRED` = %i', 2, $this->controller['URL'], $this->registry->html_view, time() + ($this->registry->cache_time * 60));
          Debug::addPoint( 'Cache view' );
          break;

        case 3:
          dibi::query('INSERT INTO `CACHE` (`TYPE`, `URL`, `HTML`, `EXPIRED`)  VALUEs( %i, %s, %s, %i),( %i, %s, %s, %i)',
            2, $this->controller['URL'], $this->registry->html_view, time() + ($this->registry->cache_time * 60),
            1, $this->controller['URL'], $this->registry->html_page, time() + ($this->registry->cache_time * 60)
          );
          Debug::addPoint( 'Cache page a view' );
          break;
      }
    }
    Debug::addPoint( 'toCache', $this->registry->cache_type );

  }  
  
  public function run() {
    
    $this->init(); 
    $user = $this->unserialize('user');
    if ( $user === false ) {
      $user = new User();
    }
    $this->registry->user = $user;

    $kosik = $this->unserialize('kosik');
    if ( $kosik === false ) {
      $kosik = new Kosik();
    }
    $this->registry->kosik = $kosik;

    $this->routing();
    $this->loadSettings();
    
    $cache_ret = 0;
/*
    if ( CACHE == true and $this->controller['cache'] ==  true ) {
     if (array_search('nocache', $this->controller['args']) === false) {
       $cache_ret = $this->checkCache();
       Debug::addPoint( 'Prohledávám CACHE', $cache_ret );
     }
     else {
       Debug::addPoint( 'NOCACHE');
     }
    }
    $this->setTemplateConst();
    
    switch($cache_ret) {
      
      case 0: //  stránka není/nemůže být v CACHE
      case 2: //  v CACHE je pouze view
        $this->getController();
        $this->getMenu();
        $this->getTemplate();
        break;
        
      case 1: // v CACHE je celá stránka
        break;
        
    }

    
    $this->getHTML();

    if (CACHE == true)
      $this->toCache();   
*/    
    $this->setTemplateConst();

    $this->getController();
    $this->getMenu();
    $this->getTemplate();
    
    $this->getHTML();

  }  

  static function myController($key) {
    $reg = Registry::getInstance();
    $appl = $reg->application;
    return $appl->controller[$key];
  }  
}
?>