<?php
/**
* 2017 - Keyrnel SARL
*
* NOTICE OF LICENSE
*
* The source code of this module is under a commercial license.
* Each license is unique and can be installed and used on only one shop.
* Any reproduction or representation total or partial of the module, one or more of its components,
* by any means whatsoever, without express permission from us is prohibited.
* If you have not received this module from us, thank you for contacting us.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this module to newer
* versions in the future.
*
* @author    Keyrnel
* @copyright 2017 - Keyrnel SARL
* @license   commercial
* International Registered Trademark & Property of Keyrnel SARL
*/

if (!defined('_PS_VERSION_')) {
    exit;
}

if (!defined('_MYSQL_ENGINE_')) {
    define('_MYSQL_ENGINE_', 'MyISAM');
}

require_once(_PS_MODULE_DIR_.'flashsales/models/FlashSale.php');
if (version_compare(_PS_VERSION_, '1.6.0.7', '<')) {
    require_once(_PS_MODULE_DIR_.'flashsales/models/FlashSaleUploader.php');
} elseif (version_compare(_PS_VERSION_, '1.7', '>=')) {
    require_once(_PS_MODULE_DIR_.'flashsales/controllers/front/FlashSaleListingFrontController.php');
    require_once(_PS_MODULE_DIR_.'flashsales/controllers/front/FlashSaleProductSearchProvider.php');
}

class flashsales extends Module
{
    private $_html = '';

    private $_post_errors = array();

    private $_layouts = array('home_page', 'flashsale_page', 'product_page', 'product_list', 'column');

    private $_configs = array(
        array('name' => 'FLASHSALE_DEL_SPECIFICPRICE', 'value' => 1),
        array('name' => 'FLASHSALE_DISPLAY_TOPMENU', 'value' => 1),
        array('name' => 'FLASHSALE_PRODUCT_LIST', 'value' => 1),
        array('name' => 'FLASHSALE_PRODUCTS_NB', 'layouts' => array('home_page', 'column', 'flashsale_page'), 'value' => 4),
        array('name' => 'FLASHSALE_TITLE', 'layouts' => array('home_page', 'flashsale_page', 'column'), 'lang' => true, 'value' => array('en' => 'Flash sales', 'fr' => 'Ventes flash')),
        array('name' => 'FLASHSALE_COUNTDOWN_STRING', 'lang' => true, 'layouts' => array('home_page', 'product_page', 'product_list', 'column'), 'value' => array('en' => 'Flash sales', 'fr' => 'Ventes flash')),
        array('name' => 'FLASHSALE_DESCRIPTION', 'layouts' => array('home_page', 'flashsale_page'), 'value' => 1),
        array('name' => 'FLASHSALE_BANNER', 'layouts' => array('home_page', 'flashsale_page'), 'value' => 1),
        array('name' => 'FLASHSALE_CAROUSEL', 'layouts' => array('home_page', 'column', 'flashsale_page'), 'value' => 1)
    );

    private $_css_fields = array(
        array('property' => 'width', 'field' => 'box_width', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'border-width', 'field' => 'box_border_width', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'border-style', 'field' => 'box_border_style', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'border-color', 'field' => 'box_border_color', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'background-color', 'field' => 'box_background_color', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'padding-top', 'field' => 'box_padding_top', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'padding-bottom', 'field' => 'box_padding_bottom', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'padding-left', 'field' => 'box_padding_left', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'padding-right', 'field' => 'box_padding_right', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'margin-top', 'field' => 'box_margin_top', 'layouts' => array('product_page', 'product_list')),
        array('property' => 'margin-bottom', 'field' => 'box_margin_bottom', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content i.icon-clock-o', 'property' => 'color', 'field' => 'icon_color', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content i.icon-clock-o', 'property' => 'font-size', 'field' => 'icon_font_size', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content i.icon-clock-o', 'property' => 'display', 'field' => 'icon_display', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content span.title', 'property' => 'color', 'field' => 'title_color', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content span.title', 'property' => 'font-size', 'field' => 'title_font_size', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content span.countdown', 'property' => 'color', 'field' => 'countdown_color', 'layouts' => array('product_page', 'product_list')),
        array('class' => '.content span.countdown', 'property' => 'font-size', 'field' => 'countdown_font_size', 'layouts' => array('product_page', 'product_list')),
    );

    protected static $cache_flash_sales = array();

    private $templateFileHome;
    private $templateFileHomeTab;
    private $templateFileHomeTabContent;
    private $templateFileColumn;
    private $templateFileCountdown;

    public function __construct()
    {
        $this->name    = 'flashsales';
        $this->tab    = 'front_office_features';
        $this->version = '2.1.1';
        $this->author    = 'Keyrnel';
        $this->module_key = '36c6c0e545ecf7134526a92f293d06da';
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('Flash Sales - Extended');
        $this->description    = $this->l('Add, edit, customize your flash sales effectively and intuitively to boost your sales!');
        $this->ps_versions_compliancy = array('min' => '1.6.0', 'max' => '1.7.9');
        $this->templateFileHome = version_compare(_PS_VERSION_, '1.7', '>=') ? 'module:flashsales/views/templates/hook/home.tpl' : 'home.tpl';
        $this->templateFileHomeTab = version_compare(_PS_VERSION_, '1.7', '>=') ? 'module:flashsales/views/templates/hook/home-tab.tpl' : 'home-tab.tpl';
        $this->templateFileHomeTabContent = version_compare(_PS_VERSION_, '1.7', '>=') ? 'module:flashsales/views/templates/hook/home-tab-content.tpl' : 'home-tab-content.tpl';
        $this->templateFileColumn = version_compare(_PS_VERSION_, '1.7', '>=') ? 'module:flashsales/views/templates/hook/column.tpl' : 'column.tpl';
        $this->templateFileCountdown = version_compare(_PS_VERSION_, '1.7', '>=') ? 'module:flashsales/views/templates/hook/countdown.tpl' : 'countdown.tpl';
    }

    public function install($delete_params = true)
    {
        if (!parent::install()
            || !$this->registerHook('actionAdminControllerSetMedia')
            || !$this->registerHook('header')
            || !$this->registerHook('displayHome')
            || !$this->registerHook('displayHomeTab')
            || !$this->registerHook('displayHomeTabContent')
            || !$this->registerHook('rightColumn')
            || !$this->registerHook('leftColumn')
            || !$this->registerHook('displayProductListReviews')
            || !$this->registerHook('actionObjectDeleteAfter')
            || !$this->registerHook('displayProductAdditionalInfo')
            || !$this->registerHook('displayRightColumnProduct')) {
            return false;
        }

        // Install database
        if ($delete_params) {
            if (!$this->installDb()) {
                return false;
            }
        }

        // Instal conf
        if (!$this->installConf()) {
            return false;
        }

        $languages = Language::getLanguages();

        // Install Tab
        $tab = new Tab();
        foreach ($languages as $lang) {
            $tab->name[$lang['id_lang']] = $this->l('Flash Sales');
        }
        $tab->class_name = 'AdminFlashSales';
        $parent = version_compare(_PS_VERSION_, '1.7', '>=') ? 'AdminParentCartRules' : 'AdminPriceRule';
        $tab->id_parent = (int)Tab::getIdFromClassName($parent);
        $tab->module = $this->name;
        if (!$tab->add()) {
            return false;
        }

        // Install Meta
        $meta = new Meta();
        $meta->page = 'module-'.$this->name.'-page';
        $meta->configurable = 1;
        foreach ($languages as $language) {
            if ($language['iso_code'] == 'fr') {
                $meta->title[(int)$language['id_lang']] = 'Ventes flash';
                $meta->description[(int)$language['id_lang']] = 'Ventes flash';
                $meta->url_rewrite[(int)$language['id_lang']] = 'ventes-flash';
            } else {
                $meta->title[(int)$language['id_lang']] = 'Flash sales';
                $meta->description[(int)$language['id_lang']] = 'Flash sales';
                $meta->url_rewrite[(int)$language['id_lang']] = 'flash-sales';
            }
        }
        $meta->add();

        if (version_compare(_PS_VERSION_, '1.6', '>=') && version_compare(_PS_VERSION_, '1.7', '<')) {
            $themes = Theme::getThemes();
            $theme_meta_value = array();
            foreach ($themes as $theme) {
                $theme_meta_value[] = array(
                    'id_theme' => $theme->id,
                    'id_meta' => (int)$meta->id,
                    'left_column' => (int)$theme->default_left_column,
                    'right_column' => (int)$theme->default_right_column
                );
            }
            if (count($theme_meta_value) > 0) {
                Db::getInstance()->insert('theme_meta', (array)$theme_meta_value, false, true, DB::INSERT_IGNORE);
            }
        }

        //init css file
        $file = 'countdown.css';
        $path = _PS_MODULE_DIR_.$this->name.'/views/css/front/';
        $dest = version_compare(_PS_VERSION_, '1.7', '>=') ? _PS_THEME_DIR_.'modules/'.$this->name.'/views/css/front/' : _PS_THEME_DIR_.'css/modules/'.$this->name.'/views/css/front/';
        if (!file_exists($dest) && mkdir($dest, 0777, true)) {
            copy($path.'/'.$file, $dest.'/'.$file);
        }

        return true;
    }

    public function installDb()
    {
        $sql = array();
        include(dirname(__FILE__).'/sql/install.php');
        foreach ($sql as $s) {
            if (!Db::getInstance()->execute($s)) {
                return false;
            }
        }

        return true;
    }

    public function installConf()
    {
        $languages = Language::getLanguages();

        foreach ($this->getConfigs() as $config) {
            $name = $config['name'];
            $value = $config['value'];

            if (isset($config['lang']) && $config['lang']) {
                $value = array();
                foreach ($languages as $language) {
                    $value[$language['id_lang']] = isset($config['value'][$language['iso_code']]) ? $config['value'][$language['iso_code']] : $config['value'][$language['en']];
                }
            }

            if (isset($config['layouts']) && count($config['layouts'])) {
                foreach ($config['layouts'] as $layout) {
                    $name = $config['name'].'_'.Tools::strtoupper($layout);
                    if (!Configuration::updateValue($name, $value)) {
                        return false;
                    }
                }
            } else {
                if (!Configuration::updateValue($name, $value)) {
                    return false;
                }
            }
        }

        return true;
    }

    public function uninstall($delete_params = true)
    {
        // Uninstall Module
        if (!parent::uninstall()) {
            return false;
        }

        // Delete specific prices & database
        if ($delete_params) {
            if (!$this->deleteSpecificPrice() || !$this->uninstallDb()) {
                return false;
            }
        }

        // Delete conf
        if (!$this->uninstallConf()) {
            return false;
        }

        // Delete Tabs
        $tabs = Tab::getCollectionFromModule($this->name);
        foreach ($tabs as $tab) {
            $tab->delete();
        }

        // Delete Meta
        $metas = Meta::getMetaByPage('module-'.$this->name.'-page', (int)$this->context->language->id);
        $meta = new Meta((int)$metas['id_meta']);
        if ($meta->delete() && version_compare(_PS_VERSION_, '1.6', '>=') && version_compare(_PS_VERSION_, '1.7', '<')) {
            Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'theme_meta` WHERE id_meta='.(int)$meta->id);
        }

        // Delete top-menu link
        $topmenu_class = version_compare(_PS_VERSION_, '1.7', '>=') ? 'Ps_MenuTopLinks' : 'MenuTopLinks';
        if (class_exists($topmenu_class)) {
            $shop_id = (int)Shop::getContextShopID();
            $shop_group_id = Shop::getGroupFromShop($shop_id);
            $conf = Configuration::get('MOD_BLOCKTOPMENU_ITEMS', null, $shop_group_id, $shop_id);

            $id_linksmenutop = $this->addTopMenuLink();
            $topmenu_class::remove($id_linksmenutop, $shop_id);

            Configuration::updateValue(
                'MOD_BLOCKTOPMENU_ITEMS',
                str_replace(array('LNK'.$id_linksmenutop.',', 'LNK'.$id_linksmenutop), '', $conf),
                false,
                $shop_group_id,
                $shop_id
            );
        }

        // Clear cache
        $this->_clearCache('*');

        return true;
    }

    public function deleteSpecificPrice()
    {
        $ids_flash_sale = FlashSale::getFlashSalesLite();
        foreach ($ids_flash_sale as $id_flash_sale) {
            $flash_sale = new FlashSale((int)$id_flash_sale);
            $flash_sale->deleteSpecificPrice();
        }

        return true;
    }

    public function uninstallDb()
    {
        $sql = array();
        include(dirname(__FILE__).'/sql/uninstall.php');
        foreach ($sql as $s) {
            if (!Db::getInstance()->execute($s)) {
                return false;
            }
        }

        return true;
    }

    public function uninstallConf()
    {
        foreach ($this->getConfigs() as $config) {
            $name = $config['name'];

            if (isset($config['layouts']) && count($config['layouts'])) {
                foreach ($config['layouts'] as $layout) {
                    $name = $config['name'].'_'.Tools::strtoupper($layout);
                    Configuration::deleteByName($name);
                }
            } else {
                Configuration::deleteByName($name);
            }
        }

        return true;
    }

    public function reset()
    {
        if (!$this->uninstall(false)) {
            return false;
        }
        if (!$this->install(false)) {
            return false;
        }

        return true;
    }

    public function getContent()
    {
        if (Tools::isSubmit('submitFlashSales')) {
            $this->updateConfigFieldsValues();

            $topmenu_module = version_compare(_PS_VERSION_, '1.7', '>=') ? 'Ps_MainMenu' : 'blocktopmenu';
            $topmenu = Module::getInstanceByName($topmenu_module);
            if ($topmenu && $topmenu->active) {
                $this->updateTopMenuDisplay();

                if (version_compare(_PS_VERSION_, '1.7', '>=')) {
                    $dir = _PS_CACHE_DIR_.DIRECTORY_SEPARATOR.'ps_mainmenu';
                    if (is_dir($dir)) {
                        foreach (scandir($dir) as $entry) {
                            if (preg_match('/\.json$/', $entry)) {
                                unlink($dir.DIRECTORY_SEPARATOR.$entry);
                            }
                        }
                    }
                } else {
                    $topmenu->_clearCache('blocktopmenu.tpl');
                }
            }

            $this->updateCssFile();

            if (!count($this->_post_errors)) {
                $this->_clearCache('*');
                Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&conf=4&token='.Tools::getAdminTokenLite('AdminModules'));
            } else {
                foreach ($this->_post_errors as $err) {
                    $this->_html .= $this->displayError($err);
                }
            }
        }

        if (version_compare(_PS_VERSION_, '1.6', '<')) {
            $this->_html .= '<div id="flashsale-content" class="bootstrap">';
            $this->_html .= $this->renderFlashSalesForm();
            $this->_html .= '</div>';
        } else {
            $this->_html .= $this->renderFlashSalesForm();
        }

        return $this->_html;
    }

    public function renderFlashSalesForm()
    {
        $languages = Language::getLanguages();
        $topmenu_module = version_compare(_PS_VERSION_, '1.7', '>=') ? 'Ps_MainMenu' : 'blocktopmenu';
        $topmenu = Module::getInstanceByName($topmenu_module);

        $css_path = _PS_MODULE_DIR_.$this->name.'/views/css/front/countdown.css';
        $css_override_path = version_compare(_PS_VERSION_, '1.7', '>=') ? _PS_THEME_DIR_.'modules/'.$this->name.'/views/css/front/countdown.css' : _PS_THEME_DIR_.'css/modules/'.$this->name.'/views/css/front/countdown.css';
        if (file_exists($css_override_path)) {
            $css_path = $css_override_path;
        }

        $css_file = Tools::file_get_contents($css_path);
        $css_fields = $this->loadCssFields($css_file);

        $this->context->smarty->assign(array(
            'languages' => Language::getLanguages(true, Context::getContext()->shop->id),
            'default_language' => (int)Configuration::get('PS_LANG_DEFAULT'),
            'currentIndex' => $this->context->link->getAdminLink('AdminModules', true).'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name,
            'currentToken' => Tools::getAdminTokenLite('AdminModules'),
            'css_file' => $css_file,
            'css_fields' => $css_fields,
            'topmenu' => (bool)($topmenu && $topmenu->active),
            'tpl_general' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/general.tpl',
            'tpl_display' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/display.tpl',
            'tpl_tab_home_page' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/tabs/home_page.tpl',
            'tpl_tab_product_page' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/tabs/product_page.tpl',
            'tpl_tab_flashsale_page' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/tabs/flashsale_page.tpl',
            'tpl_tab_product_list' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/tabs/product_list.tpl',
            'tpl_tab_column' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/tabs/column.tpl',
            'tpl_fields' => _PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/_partials/fields.tpl',
        ));

        if (version_compare(_PS_VERSION_, '1.6', '<')) {
            $this->context->controller->addCss($this->_path.'views/css/admin/admin-theme.css', 'all');
            $this->context->controller->addJS(array(
                _MODULE_DIR_.'flashsales/views/js/tools/bootstrap.js',
                _MODULE_DIR_.'flashsales/views/js/tools/jquery.autosize.js',
                _MODULE_DIR_.'flashsales/views/js/tools/functions.js'
            ));
        }

        $this->context->controller->addJS(array(
            _MODULE_DIR_.$this->name.'/views/js/tools/colorpicker.js',
            _MODULE_DIR_.$this->name.'/views/js/admin/settings.js'
        ));

        return $this->context->smarty->createTemplate(_PS_MODULE_DIR_.$this->name.'/views/templates/admin/settings/form.tpl', $this->context->smarty)->fetch();
    }

    protected function updateConfigFieldsValues()
    {
        $config = $this->getConfigFieldsValues();

        foreach ($config as $key => $val) {
            if (is_array($val) && count($val)) {
                foreach ($val as $v) {
                    if (!Validate::isCleanHTML($v)) {
                        $this->_post_errors[] = sprintf($this->l('Unvalid lang field : "%s"'), $key);
                        return false;
                    }
                }
            }

            Configuration::updateValue($key, $val);
        }

        return true;
    }

    protected function loadCssFields($content)
    {
        if (empty($content)) {
            return array();
        }

        $fields = array();

        foreach ($this->getLayouts() as $layout) {
            $properties = array();

            foreach ($this->getCssFields() as $css_field) {
                if (isset($css_field['layouts']) && !in_array($layout, ($css_field['layouts']))) {
                    continue;
                }
                $pos = stripos($content, '.flashsale-countdown-box.'.$layout);
                if (isset($css_field['class'])) {
                    $pos = stripos($content, $css_field['class'], $pos);
                }

                if (preg_match('#'.$css_field['property'].'[^-]#', $content, $matches, PREG_OFFSET_CAPTURE, $pos)) {
                    $pos = stripos($content, ':', $matches[0][1]);
                    $start = $pos + 1;
                    $end = stripos($content, ';', $start);
                    $output = Tools::substr($content, $start, $end - $start);

                    // replace pattern
                    $pattern = array('/px/', '/%/', '/inline-block/', '/solid/', '/none/');
                    $replace = array('', '', 1, 1, 0);
                    $output = preg_replace($pattern, $replace, $output);
                    // delete spaces
                    $output = trim($output);

                    $properties[$css_field['field']] = $output;
                }
            }

            $fields[$layout] = $properties;
        }

        return $fields;
    }

    protected function updateCssFile()
    {
        $content = strip_tags(Tools::getValue('css_file'));

        // replace correct end of line
        $content = str_replace("\r\n", PHP_EOL, $content);
        // Magic Quotes shall... not.. PASS!
        if (_PS_MAGIC_QUOTES_GPC_) {
            $content = Tools::stripslashes($content);
        }

        if (Validate::isCleanHTML($content)) {
            $path = version_compare(_PS_VERSION_, '1.7', '>=') ? _PS_THEME_DIR_.'modules/'.$this->name.'/views/css/front/countdown.css' : _PS_THEME_DIR_.'css/modules/'.$this->name.'/views/css/front/countdown.css';
            if (!file_put_contents($path, $content)) {
                $this->_post_errors[] = sprintf($this->l('File "%s" cannot be created'), dirname($path));
            }
        } else {
            $this->_post_errors[] = $this->l('Your css cannot contain JavaScript code.');
        }
    }

    protected function updateTopMenuDisplay()
    {
        $shop_id = (int)Shop::getContextShopID();
        $shop_group_id = Shop::getGroupFromShop($shop_id);
        $conf = Configuration::get('MOD_BLOCKTOPMENU_ITEMS', null, $shop_group_id, $shop_id);

        $display = Tools::getValue('flashsale_display_topmenu');
        Configuration::updateValue('FLASHSALE_DISPLAY_TOPMENU', (int)$display);

        $id_linksmenutop = $this->addTopMenuLink();

        if (!$display) {
            $topmenu_class = version_compare(_PS_VERSION_, '1.7', '>=') ? 'Ps_MenuTopLinks' : 'MenuTopLinks';
            $topmenu_class::remove((int)$id_linksmenutop, $shop_id);

            Configuration::updateValue('MOD_BLOCKTOPMENU_ITEMS', str_replace(array('LNK'.(int)$id_linksmenutop.',', 'LNK'.(int)$id_linksmenutop), '', $conf), false, (int)$shop_group_id, (int)$shop_id);
        } else {
            $menu_items = Tools::strlen($conf) ? explode(',', $conf) : array();
            if (!in_array('LNK'.(int)$id_linksmenutop, $menu_items)) {
                $menu_items[] = 'LNK'.(int)$id_linksmenutop;
            }

            Configuration::updateValue('MOD_BLOCKTOPMENU_ITEMS', implode(',', $menu_items), false, (int)$shop_group_id, (int)$shop_id);
        }

        return true;
    }

    protected function addTopMenuLink()
    {
        $id_linksmenutop = 0;
        $topmenu_class = version_compare(_PS_VERSION_, '1.7', '>=') ? 'Ps_MenuTopLinks' : 'MenuTopLinks';
        $labels = array();
        $page_link = array();
        $languages = Language::getLanguages();

        foreach ($languages as $language) {
            $label = ($language['iso_code'] == 'fr') ? 'Ventes flash' : 'Flash sales';
            $labels[(int)$language['id_lang']] = $label;
            $page_link[(int)$language['id_lang']] = $this->context->link->getModuleLink($this->name, 'page', array(), null, (int)$language['id_lang']);
            $links = $topmenu_class::gets((int)$language['id_lang'], null, (int)Shop::getContextShopID());
            foreach ($links as $link) {
                if ($link['link'] == $page_link[(int)$language['id_lang']]) {
                    $id_linksmenutop = (int)$link['id_linksmenutop'];
                    break 2;
                }
            }
        }
        if ($id_linksmenutop == 0) {
            $topmenu_class::add($page_link, $labels, 0, (int)Shop::getContextShopID());
            $id_linksmenutop = $this->addTopMenuLink();
        }

        return $id_linksmenutop;
    }

    public function getConfigFieldsValues()
    {
        $fields = array();
        $languages = Language::getLanguages();

        foreach ($this->getConfigs() as $config) {
            $name = $config['name'];

            if (isset($config['layouts']) && count($config['layouts'])) {
                foreach ($config['layouts'] as $layout) {
                    $name = $config['name'].'_'.Tools::strtoupper($layout);
                    if (isset($config['lang']) && $config['lang']) {
                        foreach ($languages as $language) {
                            $fields[$name][$language['id_lang']] = Tools::getValue(Tools::strtolower($name).'_'.$language['id_lang'], Configuration::get($name, $language['id_lang']));
                        }
                    } else {
                        $fields[$name] = Tools::getValue(Tools::strtolower($name), Configuration::get($name));
                    }
                }
            } else {
                if (isset($config['lang']) && $config['lang']) {
                    foreach ($languages as $language) {
                        $fields[$name][$language['id_lang']] = Tools::getValue(Tools::strtolower($name).'_'.$language['id_lang'], Configuration::get($name, $language['id_lang']));
                    }
                } else {
                    $fields[$name] = Tools::getValue(Tools::strtolower($name), Configuration::get($name));
                }
            }
        }

        return $fields;
    }

    public function hookActionAdminControllerSetMedia()
    {
        if (!($this->context->controller->controller_name == 'AdminModules' && Tools::getValue('configure') == $this->name)
            && $this->context->controller->controller_name != 'AdminFlashSales') {
            return false;
        }

        $this->context->controller->addCSS($this->_path.'views/css/admin/admin-design.css', 'all');
    }

    public function hookHeader($params)
    {
        $flash_sale_ids = FlashSale::getFlashSalesLite();
        foreach ($flash_sale_ids as $flash_sale_id) {
            $clear = false;
            $now = date('Y-m-d H:i:s');
            $flash_sale = new FlashSale((int)$flash_sale_id);
            if ($flash_sale->active && $flash_sale->to < $now) {
                $flash_sale->active = 0;
                $flash_sale->update();
                $clear = true;
            } elseif ($flash_sale->active && $flash_sale->from <= $now) {
                $clear = true;
            }

            if ($clear) {
                $ids_product = $flash_sale->getProducts();
                foreach ($ids_product as $id_product) {
                    $product = new Product((int)$id_product);
                    if (Validate::isLoadedObject($product)) {
                        $product->update();
                        break;
                    }
                }

                $this->_clearCache('*');
            }
        }

        $this->context->controller->addJS($this->_path.'views/js/front/countdown.js');
        $this->context->controller->addCSS($this->_path.'views/css/front/countdown.css', 'all');
        $this->context->controller->addCSS($this->_path.'views/css/front/global.css', 'all');

        foreach ($this->getConfigs() as $config) {
            if ($config['name'] != 'FLASHSALE_CAROUSEL') {
                continue;
            }

            foreach ($config['layouts'] as $layout) {
                $name = $config['name'].'_'.Tools::strtoupper($layout);
                if (Configuration::get($name)) {
                    $this->context->controller->addJS($this->_path.'views/js/tools/owl.carousel.min.js');
                    $this->context->controller->addCSS($this->_path.'views/css/tools/owl.carousel.min.css', 'all');
                    $this->context->controller->addCSS($this->_path.'views/css/tools/owl.theme.default.min.css', 'all');
                    if (Configuration::get('FLASHSALE_PRODUCT_LIST')) {
                        if (version_compare(_PS_VERSION_, '1.7', '<')) {
                            $this->context->controller->addCSS($this->_path.'views/css/front/miniature16.css', 'all');
                        } else {
                            $this->context->controller->addCSS($this->_path.'views/css/front/miniature17.css', 'all');
                        }
                    }

                    break 2;
                }
            }
        }


        $version = Tools::substr(_PS_VERSION_, 0, 3);
        $this->smarty->assign(array(
            'ps_version' => str_replace('.', '', $version)
        ));
    }

    public function hookActionObjectDeleteAfter($params)
    {
        $object = $params['object'];

        if (get_class($object) === 'Product') {
            Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'flash_sale_products` WHERE `id_product` = '.(int)$object->id);
        } elseif (get_class($object) === 'Category') {
            Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'flash_sale_products` WHERE `id_category` = '.(int)$object->id);
        } elseif (get_class($object) === 'Manufacturer') {
            Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'flash_sale_products` WHERE `id_manufacturer` = '.(int)$object->id);
        } elseif (get_class($object) === 'SpecificPrice') {
            Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'flash_sale_specific_prices` WHERE `id_specific_price` = '.(int)$object->id);
        }

        $this->_clearCache('*');

        return true;
    }

    public function hookDisplayHome($params)
    {
        if (!$this->isCached($this->templateFileHome, $this->getCacheId('home'))) {
            if (!isset(flashsales::$cache_flash_sales['home'])) {
                $flash_sales = FlashSale::getFlashSales((int)$this->context->language->id, 'home');
                if (is_array($flash_sales) && count($flash_sales)) {
                    foreach ($flash_sales as $key => $flash_sale) {
                        $flash_sales[$key]['products'] = $this->getProducts('home', (int)$flash_sale['id_flash_sale']);
                        if (!$flash_sales[$key]['products']) {
                            unset($flash_sales[$key]);
                            continue;
                        }
                        $banner = _PS_MODULE_DIR_.$this->name.'/views/img/banner/'.(int)$flash_sale['id_flash_sale'].'.jpg';
                        $flash_sales[$key]['banner'] = file_exists($banner) ? _MODULE_DIR_.$this->name.'/views/img/banner/'.(int)$flash_sale['id_flash_sale'].'.jpg' : false;
                    }

                    if (!count($flash_sales)) {
                        $flash_sales = false;
                    }
                }
                flashsales::$cache_flash_sales['home'] = $flash_sales;
            }

            if (flashsales::$cache_flash_sales['home'] === false) {
                return false;
            }

            $this->smarty->assign(array(
                'layout' => 'home_page',
                'flash_sales' => flashsales::$cache_flash_sales['home'],
                'txt' => Configuration::get('FLASHSALE_COUNTDOWN_STRING_HOME_PAGE', (int)$this->context->language->id),
                'tpl_product_list' => $this->getTemplateProductListPath()
            ));
        }

        return $this->renderContent($this->templateFileHome, 'home');
    }

    public function hookDisplayHomeTab($params)
    {
        if (version_compare(_PS_VERSION_, '1.6', '<')) {
            return false;
        }

        if (!$this->isCached($this->templateFileHomeTab, $this->getCacheId('home-tab'))) {
            if (!isset(flashsales::$cache_flash_sales['home_tab'])) {
                flashsales::$cache_flash_sales['home_tab'] = $this->getProducts('home_tab');
            }

            if (flashsales::$cache_flash_sales['home_tab'] === false) {
                return false;
            }
        }

        return $this->renderContent($this->templateFileHomeTab, 'home-tab');
    }

    public function hookDisplayHomeTabContent($params)
    {
        if (version_compare(_PS_VERSION_, '1.6', '<')) {
            return false;
        }

        if (!$this->isCached($this->templateFileHomeTabContent, $this->getCacheId('home-tab-content'))) {
            if (!isset(flashsales::$cache_flash_sales['home_tab'])) {
                flashsales::$cache_flash_sales['home_tab'] = $this->getProducts('home_tab');
            }

            if (flashsales::$cache_flash_sales['home_tab'] === false) {
                return false;
            }

            $this->smarty->assign(array(
                'flash_sales' => flashsales::$cache_flash_sales['home_tab'],
                'homeSize' => Image::getSize(ImageType::getFormatedName('home'))
            ));
        }

        return $this->renderContent($this->templateFileHomeTabContent, 'home-tab-content');
    }

    public function hookRightColumn($params)
    {
        if (!$this->isCached($this->templateFileColumn, $this->getCacheId('column'))) {
            if (!isset(flashsales::$cache_flash_sales['column'])) {
                flashsales::$cache_flash_sales['column'] = $this->getProducts('column');
            }

            if (flashsales::$cache_flash_sales['column'] === false) {
                return false;
            }

            foreach (flashsales::$cache_flash_sales['column'] as &$product) {
                $product['price'] = Tools::displayPrice($product['price']);
                $product['price_tax_exc'] = Tools::displayPrice($product['price_tax_exc']);
                $product['price_without_reduction'] = Tools::displayPrice($product['price_without_reduction']);
            }

            $this->smarty->assign(array(
                'layout' => 'column',
                'flash_sales' => flashsales::$cache_flash_sales['column'],
                'priceDisplay' => Product::getTaxCalculationMethod((int)$this->context->customer->id),
                'tpl_product_list' => $this->getTemplateProductListPath()
            ));
        }
        return $this->renderContent($this->templateFileColumn, 'column');
    }

    public function hookLeftColumn($params)
    {
        return $this->hookRightColumn($params);
    }

    public function hookDisplayRightColumnProduct($params)
    {
        $id_product = (int)Tools::getValue('id_product');
        $ids = array();
        $ids_combination = Product::getProductAttributesIds($id_product);

        foreach ($ids_combination as $id_combination) {
            $ids[] = (int)$id_combination['id_product_attribute'];
        }
        array_unshift($ids, 0);

        $flash_sale_data = array();
        foreach ($ids as $id_product_attribute) {
            if (!($specific_price = FlashSale::getProductSpecificPrice($id_product, $id_product_attribute)) || $specific_price['reduction'] == 0) {
                continue;
            }

            $flash_sale_data['combinations'][] = $id_product_attribute;
            if (!isset($flash_sale_data['to'])) {
                $flash_sale_data['to'] = (int)strtotime($specific_price['to']);
            }
        }

        if (!isset($flash_sale_data['to'])) {
            return;
        }

        $this->smarty->assign(array(
            'to' => $flash_sale_data['to'],
            'layout' => 'product_page',
            'combinations' => implode(',', $flash_sale_data['combinations']),
            'txt' => Configuration::get('FLASHSALE_COUNTDOWN_STRING_PRODUCT_PAGE', (int)$this->context->language->id),
            'id_product' => $id_product
        ));

        return $this->renderContent($this->templateFileCountdown);
    }

    public function hookDisplayProductListReviews($params)
    {
        $id_product = (int)$params['product']['id_product'];
        if (!($specific_price = FlashSale::getProductSpecificPrice($id_product))) {
            return;
        }

        $this->smarty->assign(array(
            'layout' => $layout = isset($params['layout']) && !empty($params['layout']) ? $params['layout'] : 'product_list',
            'to' => (int)strtotime($specific_price['to']),
            'txt' => Configuration::get('FLASHSALE_COUNTDOWN_STRING_PRODUCT_LIST', (int)$this->context->language->id),
            'id_product' => $id_product
        ));

        return $this->renderContent($this->templateFileCountdown);
    }

    public function hookDisplayProductAdditionalInfo($params)
    {
        return $this->hookDisplayRightColumnProduct($params);
    }

    public function renderContent($template, $cacheId = null)
    {
        if (version_compare(_PS_VERSION_, '1.7', '<')) {
            return $this->display(__FILE__, $template, $this->getCacheId($cacheId));
        } else {
            return $this->fetch($template, $this->getCacheId($cacheId));
        }
    }

    public function getProducts($filter = null, $id_flash_sale = null)
    {
        if (Configuration::get('PS_CATALOG_MODE')) {
            return false;
        }

        $nbProducts = false;
        if ($filter) {
            $conf = $filter;
            if ($filter == 'home') {
                $conf = 'home_page';
            } elseif ($filter == 'page') {
                $conf = 'flashsale_page';
            }

            $nbProducts = (int)Configuration::get('FLASHSALE_PRODUCTS_NB_'.Tools::strtoupper($conf));
        }

        if (version_compare(_PS_VERSION_, '1.7', '<')) {
            return FlashSale::getAllProducts((int)$this->context->language->id, $id_flash_sale, $filter, false, 0, ($nbProducts ? $nbProducts : 8));
        } else {
            $flashsale = new FlashSale((int)$id_flash_sale);

            $searchProvider = new FlashSaleProductSearchProvider(
                $this->context->getTranslator(),
                $flashsale
            );

            $context = new PrestaShop\PrestaShop\Core\Product\Search\ProductSearchContext($this->context);

            $query = new PrestaShop\PrestaShop\Core\Product\Search\ProductSearchQuery();
            $query
                ->setQueryType('flash-sales')
                ->setResultsPerPage($nbProducts)
                ->setPage(1)
                ->setSortOrder(new PrestaShop\PrestaShop\Core\Product\Search\SortOrder('product', 'position', 'asc'))
            ;

            $result = $searchProvider->runQuery(
                $context,
                $query
            );

            $assembler = new ProductAssembler($this->context);

            $presenterFactory = new ProductPresenterFactory($this->context);
            $presentationSettings = $presenterFactory->getPresentationSettings();
            $presenter = new PrestaShop\PrestaShop\Core\Product\ProductListingPresenter(
                new PrestaShop\PrestaShop\Adapter\Image\ImageRetriever(
                    $this->context->link
                ),
                $this->context->link,
                new PrestaShop\PrestaShop\Adapter\Product\PriceFormatter(),
                new PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever(),
                $this->context->getTranslator()
            );

            $products_for_template = array();

            foreach ($result->getProducts() as $rawProduct) {
                $products_for_template[] = $presenter->present(
                    $presentationSettings,
                    $assembler->assembleProduct($rawProduct),
                    $this->context->language
                );
            }

            return $products_for_template;
        }
    }

    public function _clearCache($template, $cache_id = null, $compile_id = null)
    {
        parent::_clearCache($this->templateFileColumn, 'column');
        parent::_clearCache($this->templateFileHomeTabContent, 'home-tab-content');
        parent::_clearCache($this->templateFileHomeTab, 'home-tab');
        parent::_clearCache($this->templateFileHome, 'home');
        parent::_clearCache($this->templateFileCountdown);
        return true;
    }

    public function getTemplateProductListPath()
    {
        $path = null;

        if (version_compare(_PS_VERSION_, '1.7', '>=')) {
            if (Configuration::get('FLASHSALE_PRODUCT_LIST')) {
                $path = 'module:flashsales/views/templates/front/1.7/product-list.tpl';
            } else {
                $path = 'catalog/_partials/miniatures/product.tpl';
            }
        } else {
            if (Configuration::get('FLASHSALE_PRODUCT_LIST')) {
                $path = _PS_MODULE_DIR_.$this->name.'/views/templates/front/1.6/product-list.tpl';
            } else {
                $path = _PS_THEME_DIR_.'product-list.tpl';
            }
        }

        return $path;
    }

    public function getLayouts()
    {
        return $this->_layouts;
    }

    public function getConfigs()
    {
        return $this->_configs;
    }

    public function getCssFields()
    {
        return $this->_css_fields;
    }
}
