<?php
/**
 * Goweb Sitemanager 5 Framework
 *
 * Bootstrap
 *
 * @version    5.0.25
 * @category   Goweb
 * @package    Goweb_Application
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2010 (c) Goweb (http://www.goweb.pt)
 *
 */

class Goweb_Application {
    /**
     * Constructor
     * @return void
     */
    public function __construct($controller = APPLICATION_PATH){
        if (strcmp($controller, APPLICATION_PATH) !== 0) set_include_path(get_include_path() . 
        PATH_SEPARATOR . $controller);
        include_once 'Zend/Loader.php';
        /**
         * registerAutoload problemático, com a forma como as classes são carregadas
         */
        //Zend_Loader::registerAutoload();
        // Load configuration
        Zend_Loader::loadClass('Zend_Config_Ini');
        Zend_Loader::loadClass('Zend_Db');
        Zend_Loader::loadClass('Zend_Db_Table_Abstract');
        Zend_Loader::loadClass('Zend_Controller_Front');
        Zend_Loader::loadClass('Goweb_View');
        Zend_Loader::loadClass('Zend_Controller_Action_Helper_ViewRenderer');
        Zend_Loader::loadClass('Goweb_Config');
        Zend_Loader::loadClass('Goweb_Config_Ini');
        Zend_Loader::loadClass('Zend_Locale');
        Zend_Loader::loadClass('Zend_Log');
        Zend_Loader::loadClass('Zend_Log_Writer_Firebug');
        $this->_config = new Zend_Config_Ini(ROOT_PATH.'/config.ini', 'production', true);
        $this->_config->database->type = $this->_config->database->type == 'mysql' ? 'pdo_mysql' : $this->_config->database->type; 
        Zend_Registry::set('config', $this->_config);
        $frontendOptions = array('lifetime' => $this->_config->cache->lifetime ? $this->_config->cache->lifetime : 3600, 'automatic_serialization' => true);

        $backendOptions  = array('cache_dir' => ROOT_PATH . '/cache/zend');
        goweb::loadClass('Zend_Cache');
        $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
        Zend_Registry::set('cache', $cache);
        define('URL_REWRITE', ((int) $this->_config->url->rewrite > 0) ? true : false);

        define('RELACOES', ((int) $this->_config->relacoes->activo > 0) ? $this->_config->relacoes->nivel : false);
        
        //$this->_config->debug &&
        if (!$this->_config->debug && $controller == APPLICATION_PATH && (is_null($this->_config->cache->pages) || $this->_config->cache->pages)){
            /**
             * Fazer cache das páginas em front office
             */
            $frontendOptions = array(
                                'lifetime' => 1080,
                                'debug_header' => false, // for debugging
                                'default_options' => array(
                                'cache' => true,
                                'cache_with_get_variables' => true,
                                'make_id_with_get_variables' => true,
                                'cache_with_cookie_variables' => true,
                                'make_id_with_cookie_variables' => true),
                                'memorize_headers' => array('Content-Language', 'Content-Type', 'X-UA-Compatible'));
            $backendOptions = array(
                                'cache_dir' => ROOT_PATH . '/cache/zend',
                                'file_name_prefix' => 'paginas');
            
            $pageCache = Zend_Cache::factory('Page', 'File', $frontendOptions, $backendOptions);
            $pageCache->start();
            Zend_Registry::set('page_cache', $pageCache);
        }        

        // Next, set the cache to be used with all table objects
        Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
        Zend_Locale::setCache($cache);
        Zend_Registry::set('cache', $cache);
        goweb::loadClass('Zend_Translate');
        Zend_Translate::setCache($cache);
        
        // configure database and store to the registry
        $db = Zend_Db::factory($this->_config->database->type, $this->_config->database);
        
        if ($this->_config->database->profiler){
            Zend_Loader::loadClass('Zend_Db_Profiler_Firebug');
            $profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
            $profiler->setEnabled(true);
            $db->setProfiler($profiler);
        }

        Zend_Db_Table_Abstract::setDefaultAdapter($db);
        Zend_Registry::set('db', $db);
        
        
        // set dispatcher
        Goweb::loadClass('Goweb_Controller_Dispatcher');
        $dispatcher = new Goweb_Controller_Dispatcher();
        $dispatcher->setControllerDirectory($controller);
        Zend_Controller_Front::getInstance()->setDispatcher($dispatcher);
        Zend_Controller_Front::getInstance()->setParam('useDefaultControllerAlways', true);
        Zend_Controller_Front::getInstance()->setParam('useCaseSensitiveActions', true);


        //Zend_Controller_Front::getInstance()->throwExceptions(true);
        $view = new Goweb_View();
        $view->setScriptPath(ROOT_PATH . '/views');
        $view->setHelperPath(ROOT_PATH . '/views/helpers');
        if ($this->_config->zfdebug) {
            $options = array(
                //'jquery_path' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js',
                'plugins' => array('Variables', 
                                   'Html', 
    //                               'Database' => array('adapter' => array('standard' => $db)), 
                                   'File' => array('basePath' => Zend_Controller_Front::getInstance()->getInstance()->getBaseUrl()), 
                                   'Memory', 
                                   'Time', 
                                   'Registry', 
                                   'Cache' => array('backend' => $cache->getBackend()), 
                                   'Exception')
            );
            Goweb::loadClass('ZFDebug_Controller_Plugin_Debug_Plugin_Interface');
            Goweb::loadClass('ZFDebug_Controller_Plugin_Debug_Plugin_Log');
            Goweb::loadClass('ZFDebug_Controller_Plugin_Debug_Plugin_Log_Writer');
            Goweb::loadClass('ZFDebug_Controller_Plugin_Debug_Plugin');
            //Goweb::loadClass('');
            
            Goweb::loadClass('ZFDebug_Controller_Plugin_Debug');
            
            
            $debug = new ZFDebug_Controller_Plugin_Debug($options);
            Zend_Controller_Front::getInstance()->registerPlugin($debug);
            $view->headScript()->appendFile('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js');
        }
        $view->doctype('XHTML1_TRANSITIONAL');
        
        $view->addHelperPath(ROOT_PATH . '/library/Goweb/View/Helper', 'Goweb_View_Helper');
        $view->addHelperPath(ROOT_PATH . '/library/Custom/Goweb/View/Helper', 'Custom_Goweb_View_Helper');
        Zend_Registry::set('view', $view);
        Zend_Controller_Action_HelperBroker::addPrefix('Goweb_Controller_Action_Helper');

        $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
        $viewRenderer->setViewSuffix('tpl');
        
        $viewRenderer->setView($view);
        Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
        
        $writer = new Zend_Log_Writer_Firebug();
        $logger = new Zend_Log($writer);
        goweb::register('Log_Firebug', $logger);
    }
    
    /**
     * Metodo para iniciar o objecto de sessao.
     *
     * @return  Goweb_Session
     */
    public function initSession($postfix, $start = false, $db = null) {
        // inicia o session
        if ($this->_config->session->db > 0) {
            throw new Goweb_Exception('Not implemented');
            Goweb::loadClass('Goweb_Session_Db');
            $session = new Goweb_Session_Db($this->_config->session->name . $postfix,
                                            ($db) ? $db : 'db',
                                            $this->_config->session->table,
                                            $this->_config->session->expire);
        } else {
            Goweb::loadClass('Goweb_Session');
            $session = new Goweb_Session($this->_config->session->name . $postfix);

        }
        if ($session->lang && $session->langs && Zend_Controller_Front::getInstance()->getRequest()){
            /**
             * workaround para o translater,
             */
            $uri = ltrim(Zend_Controller_Front::getInstance()->getRequest()->getPathInfo(), '/');
            if (substr($uri, -1) != '/') $uri .= '/';
            $lang = substr($uri, 0, strpos($uri, '/'));
            if ($session->lang != $lang && in_array($lang, $session->langs)){
                $session->lang = $lang;
                $_GET['lang'] = $lang;
            }
        }
        Goweb::register('session', $session);
        return $session;
    }
    
    public function initPainel(){
        $this->_configModel = Goweb::getModelInstance('Painel_Model_Config', 'db');
        $db = Zend_Registry::get('db');
       	$cache = Zend_Registry::get('cache');
        if (!$tables = $cache->load('listTables')){
            $tables = $db->listTables();
            $cache->save($tables, 'listTables');
        }
        if (in_array($this->_configModel->getTableName(), $tables)){
            if (!$this->_configModel->find('1')) {
                throw new Goweb_Exception('As configuracoes do "Painel" nao existem no sistema.');
            }
            $this->_config->painel = $this->_configModel->toArray();
        }
        Zend_Registry::set('config', $this->_config);
    }
    
    
    /**
     * Metodo para iniciar a linguagem
     */
    public function initLanguage($lang = null, $initTranslator = true, $adminMode = true) {
        $session = Goweb::registry('session');
        if (!$session->lang) {
            if ($adminMode) {
                $langs = explode(',', $this->_config->languages->available);
            } else {
                if ($this->_config->painel && strpos($this->_config->painel->linguas_activas, 'a:') === 0) {
                    $langs = unserialize($this->_config->painel->linguas_activas);
                } else {
                    echo '<b>N&atilde;o existe nenhuma l&iacute;ngua activa no sistema. &Eacute; favor instalar o projecto pelo backoffice</b>';
                    throw new Goweb_Exception('Nao existe nenhuma lingua activa no sistema.');
                }
            }
            if (Zend_Controller_Front::getInstance()->getRequest()) {
                $uri = ltrim(Zend_Controller_Front::getInstance()->getRequest()->getPathInfo(), '/');
            } elseif (isset($_SERVER['REQUEST_URI'])) {
                $uri = ltrim($_SERVER['REQUEST_URI'], '/');
            }
            if (isset($uri)) {
                if (substr($uri, -1) != '/') $uri .= '/';
                $lang = substr($uri, 0, strpos($uri, '/'));
                if ($lang == 'admin') {
                    $lang = substr($uri, strlen($lang)+1, strlen($langs[0]));
                }
                if ($lang && in_array($lang, $langs)){
                    $session->lang = $lang;
                    $_GET['lang'] = $lang;
                }
            }
            if (!$session->lang){
                goweb::loadClass('Zend_Locale');
                $locale = Zend_Locale::getBrowser();
                if (count($locale) > 0){
                    foreach ($locale as $local => $value){
                        $Lang_split = explode('_', $local);
                        $Lang_pre = trim($Lang_split[0]);
                        if (in_array($Lang_pre, $langs)) {
                            $session->lang = $Lang_pre;
                            break;
                        }
                    }
                } else if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && $_SERVER['HTTP_ACCEPT_LANGUAGE']){
                    $acceptlang = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                    for ($i = 0; $i < count($acceptlang);  $i++){
                        $Lang = explode(';', $acceptlang[$i]);
                        $acceptlang[$i] = trim($Lang[0]);
                    }
                    for ($i = 0; $i < count($acceptlang);  $i++){
                        $Lang_split = explode('-', $acceptlang[$i]);
                        $Lang_pre = trim($Lang_split[0]);
                        if (in_array($Lang_pre, $langs)) {
                            $session->lang = $Lang_pre;
                            $i = count($acceptlang)+1;
                        }
                    }
                }
            }

            /**
             * failsave
             */
            if (!$session->lang){
                if (in_array('en', $langs)) {
                    $session->lang = 'en';
                } elseif (in_array('pt', $langs)) {
                    $session->lang = 'pt';
                } else {
                    $session->lang = $langs[0];
                }
            }

            $session->langs = $langs;
        }
        if ($lang) {
            if (is_array($session->langs) && in_array($lang, $session->langs)) {
                $session->lang = $lang;
            }
        }
        if ($initTranslator) {
            Goweb::loadClass('Goweb_Translator');
            $translator = new Goweb_Translator($session->lang, $session->langs, LANG_PATH);
            Goweb::register('translator', $translator);
        }
        $router = Zend_Controller_Front::getInstance()->getRouter();
        goweb::loadClass('Zend_Controller_Router_Route');
        $translateModel = goweb::getModelInstance('Sistema_Model_Modulo', 'db', false);
        if (is_numeric(strpos(ADMIN_PATH, 'application_admin')) || !$translateModel->colExists('nome_traduzido') ){ 
            $route = new Zend_Controller_Router_Route(
                      ':lang/:controller/:action/*',array(
                          'lang'   => $session->lang,
                          'module'     => 'default',
                          'controller' => 'index',
                          'action'     => 'index'));
        } else {
            $cache = Zend_Registry::get('cache');
            $langs = explode(',', $this->_config->languages->available);
            $count = 0;
            foreach ($langs as $lang){
                $cacheId = 'traducoes_' . $lang ;

                if (!$data = $cache->load($cacheId)){
                    $translateModel = goweb::getModelInstance('Sistema_Model_Modulo', 'db', false);
                    $translateModel->setLang($lang);
                    $translateModel->initLang();
                    $result = $translateModel->fetchAll();
                    $data = array();
                    if ($result){
                        foreach ($result as $item){
                            if (!array_key_exists($item->nome, $data)){
                                $data[strtolower($item->nome)] = strtolower($item->nome_traduzido);
                            }
                        }
                    }

                    $translateModel = goweb::getModelInstance('Sistema_Model_Action', 'db', false);
                    $translateModel->setLang($lang);
                    $translateModel->initLang();
                    $result = $translateModel->fetchAll();
                    if ($result){
                        foreach ($result as $item){
                            if (!array_key_exists($item->nome, $data)){
                                $data[$item->nome] = $item->nome_traduzido;
                            }
                        }
                    }
                    $cache->save($data, $cacheId);
                }
                $count++;
                if ($count == 1){
                    $translator = new Zend_Translate('array', $data, $lang, array('disableNotices' => true));
                } else {
                    $translator->addTranslation($data, $lang);
                }
            }
            $translator->setLocale($session->lang);
            Zend_Controller_Router_Route::setDefaultTranslator($translator);
            $route = new Zend_Controller_Router_Route(
                      ':lang/:@controller/:@action/*',array(
                              'lang'   => $session->lang,
                              '@locale'   => $session->lang,
                              'module'     => 'default',
                              'controller' => 'index',
                              'action'     => 'index'));
            
        }
        $router->addRoute('lang_default', $route);

        Zend_Controller_Front::getInstance()->setRouter($router);

        if (!$this->_config->languages->{$session->lang}){
            throw new Goweb_Exception('&Eacute; necess&aacute;rio definir o locale "' . $session->lang . '" no config.ini em "languages.' . $session->lang . '".');
        }
        goweb::loadClass('Zend_Locale');
        $locale = new Zend_Locale($this->_config->languages->{$session->lang});
        Goweb::register('Zend_Locale', $locale);
        Zend_Loader::loadClass('Zend_Search_Lucene');
        try {
            $gowebSearch = new Zend_Search_Lucene(ROOT_PATH. '/cache/search/' . $session->lang);
        } catch (Exception $e){
            $gowebSearch = new Zend_Search_Lucene(ROOT_PATH. '/cache/search/' . $session->lang, true);
        }
        Goweb::register('Goweb_Search', $gowebSearch);
        if ($this->_config->timezone) date_default_timezone_set($this->_config->timezone);
    }
    
    /**
     * Metodo para iniciar a linguagem
     */
    public function initLanguageAdmin($lang = null, $initTranslator = true, $adminMode = true) {
        $session = Goweb::registry('session');
      
        if(isset($session->utilizador['lingua']['perfix'])){
	        $lang = $session->utilizador['lingua']['perfix'];
        }
        if (!$session->langAdmin) {
            if ($adminMode) {
                $langs = explode(',', $this->_config->languages->available);
            } else {
                if (strpos($this->_config->painel->linguas_activas, 'a:') === 0) {
                    $langs = unserialize($this->_config->painel->linguas_activas);
                } else {
                    throw new Goweb_Exception('Nao existe nenhuma lingua activa no sistema.');
                }                
            }
            
            if (in_array('en', $langs)) {
                $session->langAdmin = 'en';
            }elseif (in_array('pt', $langs)) {
                $session->langAdmin = 'pt';
            } else {
                $session->langAdmin = $langs[0];
            }
             
            $session->langs = $langs;
        }
        if ($lang) {
            if (is_array($session->langs) && in_array($lang, $session->langs)) {
                $session->langAdmin = $lang;          
            }
        }
        if ($initTranslator) {
            Goweb::loadClass('Goweb_TranslatorAdmin');
            $translatorAdmin = new Goweb_TranslatorAdmin($session->langAdmin, $session->langs, LANG_PATH);
            Goweb::register('translatorAdmin', $translatorAdmin);
        }
        $langsNames = array('pt' => translateAdmin('Portugu&ecirc;s'),
                                   'en' => translateAdmin('Ingl&ecirc;s'),
                                   'fr' => translateAdmin('Franc&ecirc;s'),
                                   'de' => translateAdmin('Alem&atilde;o'),
                                   'es' => translateAdmin('Espanhol'),
                                   'ru' => translateAdmin('Russo'));

        goweb::register('langsNames', $langsNames);
    }

    public function runApp(){
        $frontController = Zend_Controller_Front::getInstance();
        $frontController->dispatch();
    }
}