<?php

/*
 * FrontControllerCore is overriden by ThemeEditro module to use preview theme template files in Designer
 */
class FrontController extends FrontControllerCore
{
    public function init()
    {
        parent::init();
        
        // PrestaShop removes such declaration before class
        require_once(dirname(__FILE__).'../../../../modules/designer/designer.php');

        $css_dir = _THEME_CSS_DIR_;
        $img_dir = _THEME_IMG_DIR_;
        $js_dir = _THEME_JS_DIR_;
        if (isPreviewTheme())
        {
            $css_dir = getPreviewCssDir();
            $img_dir = getPreviewImgDir();
            $js_dir = getPreviewJsDir();
        }
        
        $this->context->smarty->assign(array(
            // Usefull for layout.tpl
            'tpl_dir' => getThemeDir(),
            'img_dir' => $img_dir,
            'css_dir' => $css_dir,
            'js_dir' => $js_dir,
        ));
        
        // needed in shopping cart Designer control - blockcart.php
        $param = array('cookie' => $this->context->cookie, 'cart' => $this->context->cart);
        $this->getCartProducts($param);
        // needed in shopping cart link Designer control - blockuserinfo.php
        $this->context->smarty->assign(array(
            'bd_order_process' => Configuration::get('PS_ORDER_PROCESS_TYPE') ? 'order-opc' : 'order',
            'bdImageHomeSize' => Image::getSize('home_default'),
            'bdImageLargeSize' => Image::getSize('large_default'),
            'bdImageMediumSize' => Image::getSize('medium_default'), // Image::getSize(ImageType::getFormatedName('medium')) used themeName, so we use getSize at once
        ));
        // using full urls for media files in tests
        if (Tools::getValue('test_theme', false))
        {
            $this->context->smarty->assign(array(
                'shop_url_full' => (Tools::usingSecureMode() ?  Tools::getShopDomainSsl(true) : Tools::getShopDomain(true))
            ));
        }
        // needed fo horizontal category menu in Designer. Moved here from display() method
        Designer::buildCategoryMenu();
        // needed to output header search form in Designer theme.
        $this->calculSearchCommon();
        // needed to output blockcms in footer in Designer theme.
        $this->prepareHook();
    }

    /**
     * @@deprecated 1.5.0
     */
    public function displayHeader($display = true)
    {
        parent::displayHeader();
        $this->smartyOutputContent(getThemeDir().'header.tpl');
    }

    /**
     * @@deprecated 1.5.0
     */
    public function displayFooter($display = true)
    {
        // This method will be removed in 1.6
        parent::displayFooter();
        $this->smartyOutputContent(getThemeDir().'footer.tpl');
    }

    public function display()
    {
        require_once(dirname(__FILE__).'../../../../modules/designer/designer.php');
        Tools::safePostVars();

        // assign css_files and js_files at the very last time
        if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache'))
        {
            // CSS compressor management
            if (Configuration::get('PS_CSS_THEME_CACHE'))
                $this->css_files = Media::cccCSS($this->css_files);
            //JS compressor management
            if (Configuration::get('PS_JS_THEME_CACHE'))
                $this->js_files = Media::cccJs($this->js_files);
        }
        
        // needed in Designer breadcrumbs control
        $this->modifyBreadcrumbs();
        
        $this->context->smarty->assign('css_files', $this->css_files);
        $this->context->smarty->assign('js_files', array_unique($this->js_files));
        $this->context->smarty->assign(array(
            'errors' => $this->errors,
            'display_header' => $this->display_header,
            'display_footer' => $this->display_footer,
        ));
        
        $live_edit_content = '';
        // Don't use live edit if on mobile device
        if (!$this->context->getMobileDevice() && $this->checkLiveEditAccess())
            $live_edit_content = $this->getLiveEditFooter();
        
        $layout = $this->getLayout();
        if ($layout)
        {
            if ($this->template)
                $this->context->smarty->assign('template', $this->context->smarty->fetch($this->template).$live_edit_content);
            else // For retrocompatibility with 1.4 controller
            {
                ob_start();
                $this->displayContent();
                $template = ob_get_contents();
                ob_clean();
                $this->context->smarty->assign('template', $template.$live_edit_content);
            }
            $this->smartyOutputContent($layout);
        }
        else
        {
            // BEGIN - 1.4 retrocompatibility - will be removed in 1.6
            Tools::displayAsDeprecated('layout.tpl is missing in your theme directory');
            if ($this->display_header)
                $this->smartyOutputContent(getThemeDir().'header.tpl');

            if ($this->template)
                $this->smartyOutputContent($this->template);
            else // For retrocompatibility with 1.4 controller
                $this->displayContent();

            if ($this->display_footer)
                $this->smartyOutputContent(getThemeDir().'footer.tpl');
            // END - 1.4 retrocompatibility - will be removed in 1.6
        }
                
        return true;
    }

    /* Display a specific page if the user country is not allowed */
    protected function displayRestrictedCountryPage()
    {
        parent::displayRestrictedCountryPage();
        $this->smartyOutputContent(getThemeDir().'restricted-country.tpl');
        exit;
    }

    public function setMedia()
    {
        // if website is accessed by mobile device
        // @@see FrontControllerCore::setMobileMedia()
        if ($this->context->getMobileDevice() != false)
        {
            $this->setMobileMedia();
            return true;
        }
        
        require_once(dirname(__FILE__).'../../../../modules/designer/defines.inc.php');
        $css_dir = isPreviewTheme() ? getPreviewCssDir() : _THEME_CSS_DIR_;
        $this->addCSS($css_dir.'global.css', 'all');
        $this->addjquery();
        $this->addjqueryPlugin('easing');
        $this->addJS(_PS_JS_DIR_.'tools.js');

        if (Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
        {
            $this->addJqueryUI('ui.sortable');
            $this->addjqueryPlugin('fancybox');
            $this->addJS(_PS_JS_DIR_.'hookLiveEdit.js');
            $this->addCSS(_PS_CSS_DIR_.'jquery.fancybox-1.3.4.css', 'all'); // @@TODO
        }
        if ($this->context->language->is_rtl)
            $this->addCSS($css_dir.'rtl.css');

        // Execute Hook FrontController SetMedia
        Hook::exec('actionFrontControllerSetMedia', array());
    }

    /**
     * Add one or several CSS for front, checking if css files are overriden in theme/css/modules/ directory
     *
     * @@see Controller::addCSS()
     */
    public function addCSS($css_uri, $css_media_type = 'all')
    {
        if (!is_array($css_uri))
            $css_uri = array($css_uri => $css_media_type);

        $list_uri = array();
        foreach ($css_uri as $file => $media)
        {
            $different = 0;
            $override_path = str_replace(__PS_BASE_URI__.'modules/', _PS_ROOT_DIR_.'/themes/'.getThemeName().'/css/modules/', $file, $different);
            if ($different && file_exists($override_path))
                $file = str_replace(__PS_BASE_URI__.'modules/', __PS_BASE_URI__.'themes/'.getThemeName().'/css/modules/', $file, $different);
            else
            {
                $override_path = str_replace(_THEME_CSS_DIR_, _PS_ROOT_DIR_.'/themes/'.getThemeName().'/css/', $file, $different);
                if ($different && file_exists($override_path))
                    $file = str_replace(_THEME_CSS_DIR_, __PS_BASE_URI__.'themes/'.getThemeName().'/css/', $file, $different);
            }
            $list_uri[$file] = $media;
        }

        return parent::addCSS($list_uri, $css_media_type);
    }

    /**
     * Add one or several JS files for front, checking if js files are overriden in theme/js/modules/ directory
     *
     * @@see Controller::addJS()
     */
    public function addJS($js_uri)
    {
        if (!is_array($js_uri))
            $js_uri = array($js_uri);

        foreach ($js_uri as $key => &$file)
        {
            if (!preg_match('/^http(s?):\/\//i', $file))
            {
                $different = 0;
                $override_path = str_replace(__PS_BASE_URI__.'modules/', _PS_ROOT_DIR_.'/themes/'.getThemeName().'/js/modules/', $file, $different);
                if ($different && file_exists($override_path))
                    $file = str_replace(__PS_BASE_URI__.'modules/', __PS_BASE_URI__.'themes/'.getThemeName().'/js/modules/', $file, $different);
                else
                {
                    $override_path = str_replace(_THEME_JS_DIR_, _PS_ROOT_DIR_.'/themes/'.getThemeName().'/js/', $file, $different);
                    if ($different && file_exists($override_path))
                        $file = str_replace(_THEME_JS_DIR_, __PS_BASE_URI__.'themes/'.getThemeName().'/js/', $file, $different);
                }
            }
        }

        return parent::addJS($js_uri);
    }

    /**
     * Returns the layout corresponding to the current page by using the override system
     * Ex:
     * On the url: http://localhost/index.php?id_product=1&controller=product, this method will
     * check if the layout exists in the following files (in that order), and return the first found:
     * - /themes/default/override/layout-product-1.tpl
     * - /themes/default/override/layout-product.tpl
     * - /themes/default/layout.tpl
     *
     * @@since 1.5
     * @@return bool|string
     */
    public function getLayout()
    {
        $entity = Tools::getValue('controller');
        $id_item = (int)Tools::getValue('id_'.$entity);

        $layout_dir = getThemeDir();
        $layout_override_dir  = _PS_THEME_OVERRIDE_DIR_;
        if ($this->context->getMobileDevice() != false)
        {
            $layout_dir = _PS_THEME_MOBILE_DIR_;
            $layout_override_dir = _PS_THEME_MOBILE_OVERRIDE_DIR_;
        }

        $layout = false;
        if ($entity)
        {
            if ($id_item > 0 && file_exists($layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl'))
                $layout = $layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl';
            elseif (file_exists($layout_override_dir.'layout-'.$entity.'.tpl'))
                $layout = $layout_override_dir.'layout-'.$entity.'.tpl';
        }

        if (!$layout && file_exists($layout_dir.'layout.tpl'))
            $layout = $layout_dir.'layout.tpl';

        return $layout;
    }

    /**
     * This is overrided to manage is behaviour
     * if a customer access to the site with mobile device.
     */
    public function setTemplate($default_template)
    {
        require_once(dirname(__FILE__).'../../../../modules/designer/defines.inc.php');
        $preview_template = str_replace(_PS_THEME_DIR_, getThemeDir(), $default_template);
        parent::setTemplate($preview_template);
    }

    private function modifyBreadcrumbs()
    {
        $path = $this->context->smarty->getTemplateVars('path');
        $linkClass = " class=\"PS_LINK\"";
        $textClass = " class=\"PS_TEXT\"";
        
        // last breadcrumb item as active
        $result = preg_replace('~([^>]+)$~', '<li class="active"><span' . $textClass . '>$1</span></li>', $path);
        // all items wrapped in <li>
        $result = preg_replace('~<a(.*?)>(.*?)</a><span(.*?)>(.*?)</span>~', '<li><div' . $linkClass .'><a$1>$2</a></div></li>', $result);
        
        $this->context->smarty->assign('path', $result);
        $this->context->smarty->assign('ps_link', $linkClass);
        $this->context->smarty->assign('ps_text', $textClass);
    }

    protected function getCartProducts(&$params)
    {
        global $errors;
        
        // Set currency
        if ((int)$params['cart']->id_currency && (int)$params['cart']->id_currency != $this->context->currency->id)
            $currency = new Currency((int)$params['cart']->id_currency);
        else
            $currency = $this->context->currency;

        $taxCalculationMethod = Group::getPriceDisplayMethod((int)Group::getCurrent()->id);

        $useTax = !($taxCalculationMethod == PS_TAX_EXC);

        $products = $params['cart']->getProducts(true);
        
        $nbTotalProducts = 0;
        foreach ($products as $product)
            $nbTotalProducts += (int)$product['cart_quantity'];
        $cart_rules = $params['cart']->getCartRules();

        $shipping_cost = Tools::displayPrice($params['cart']->getOrderTotal($useTax, Cart::ONLY_SHIPPING), $currency);
        $shipping_cost_float = Tools::convertPrice($params['cart']->getOrderTotal($useTax, Cart::ONLY_SHIPPING), $currency);
        $wrappingCost = (float)($params['cart']->getOrderTotal($useTax, Cart::ONLY_WRAPPING));
        $totalToPay = $params['cart']->getOrderTotal($useTax);

        if ($useTax && Configuration::get('PS_TAX_DISPLAY') == 1)
        {
            $totalToPayWithoutTaxes = $params['cart']->getOrderTotal(false);
            $this->smarty->assign('tax_cost', Tools::displayPrice($totalToPay - $totalToPayWithoutTaxes, $currency));
        }
        
        // The cart content is altered for display
        foreach ($cart_rules as &$cart_rule)
        {
            if ($cart_rule['free_shipping'])
            {
                $shipping_cost = Tools::displayPrice(0, $currency);
                $shipping_cost_float = 0;
                $cart_rule['value_real'] -= Tools::convertPrice($params['cart']->getOrderTotal(true, Cart::ONLY_SHIPPING), $currency);
                $cart_rule['value_tax_exc'] = Tools::convertPrice($params['cart']->getOrderTotal(false, Cart::ONLY_SHIPPING), $currency);
            }
            if ($cart_rule['gift_product'])
            {
                foreach ($products as &$product)
                    if ($product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute'])
                    {
                        $product['total_wt'] = Tools::ps_round($product['total_wt'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
                        $product['total'] = Tools::ps_round($product['total'] - $product['price'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
                        $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
                        $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'] - $product['price'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
                    }
            }
        }
        
        $this->context->smarty->assign(array(
            'bd_products' => $products,
            'bd_customizedDatas' => Product::getAllCustomizedDatas((int)($params['cart']->id)),
            'bd_CUSTOMIZE_FILE' => _CUSTOMIZE_FILE_,
            'bd_CUSTOMIZE_TEXTFIELD' => _CUSTOMIZE_TEXTFIELD_,
            'bd_discounts' => $cart_rules,
            'bd_nb_total_products' => (int)($nbTotalProducts),
            'bd_shipping_cost' => $shipping_cost,
            'bd_shipping_cost_float' => $shipping_cost_float,
            'bd_show_wrapping' => $wrappingCost > 0 ? true : false,
            'bd_show_tax' => (int)(Configuration::get('PS_TAX_DISPLAY') == 1 && (int)Configuration::get('PS_TAX')),
            'bd_wrapping_cost' => Tools::displayPrice($wrappingCost, $currency),
            'bd_product_total' => Tools::displayPrice($params['cart']->getOrderTotal($useTax, Cart::BOTH_WITHOUT_SHIPPING), $currency),
            'bd_total' => Tools::displayPrice($totalToPay, $currency),
            'bd_order_process' => Configuration::get('PS_ORDER_PROCESS_TYPE') ? 'order-opc' : 'order',
            'bd_ajax_allowed' => (int)(Configuration::get('PS_BLOCK_CART_AJAX')) == 1 ? true : false,
            'bd_static_token' => Tools::getToken(false)
        ));
        if (count($errors))
            $this->context->smarty->assign('bd_carterrors', $errors);
        if (isset($this->context->cookie->ajax_blockcart_display))
            $this->context->smarty->assign('bd_cartcolapseExpandStatus', $this->context->cookie->ajax_blockcart_display);
    }

    /**
     * Method similar to modules/blocksearch/blocksearch.php calculHookCommon()
     *
     * @@return void
     */
    private function calculSearchCommon()
    {
        $this->context->smarty->assign(array(
            'bd_ENT_QUOTES' =>		ENT_QUOTES,
            'bd_search_ssl' =>		Tools::usingSecureMode(),
            'bd_ajaxsearch' =>		Configuration::get('PS_SEARCH_AJAX'),
            'bd_instantsearch' =>	Configuration::get('PS_INSTANT_SEARCH')
        ));

        return true;
    }

    /**
     * Method similar to modules/blockcms/blockcms.php _prepareHook()
     *
     * @@return void
     */
    private function prepareHook()
    {
        require_once(dirname(__FILE__).'../../../../modules/blockcms/blockcms.php');
        $block_activation = Configuration::get('FOOTER_BLOCK_ACTIVATION');

        if (!$block_activation)
            return false;

        $cms_titles = BlockCMSModel::getCMSTitlesFooter();
        $display_footer = Configuration::get('PS_STORES_DISPLAY_FOOTER');
        $display_poweredby = Configuration::get('FOOTER_POWEREDBY');
        $footer_text = Configuration::get('FOOTER_CMS_TEXT_'.(int)$this->context->language->id);

        $this->context->smarty->assign(
            array(
                'bd_cms_block' => 0,
                'bd_cms_contact_url' => 'contact',
                'bd_cms_cmslinks' => $cms_titles,
                'bd_cms_display_stores_footer' => $display_footer,
                'bd_cms_display_poweredby' => ((int)$display_poweredby === 1 || $display_poweredby === false),
                'bd_cms_footer_text' => $footer_text
            )
        );
        return true;
    }
}
