<?php
class ControllerModulePromotions extends Controller
{
    private $data   = array();
    private $module = array();

    public function __construct($registry)
    {
        parent::__construct($registry);

        $this->config->load('isenselabs/promotions');
        $this->module = $this->config->get('promotions');

        $this->load->model('setting/setting');
        $this->load->model($this->module['path']);
        $this->module['model'] = $this->{$this->module['model']};

        $this->module['promo_id'] = 0;
        if (isset($this->request->get['promo_id'])) {
            $this->module['promo_id'] = (int)$this->request->get['promo_id'];
        }

        // Module setting
        $setting = $this->model_setting_setting->getSetting($this->module['code'], $this->config->get('config_store_id'));
        $this->module['setting'] = array_replace_recursive(
            $this->module['setting'],
            !empty($setting[$this->module['code'] . '_setting']) ? $setting[$this->module['code'] . '_setting'] : array()
        );

        // Template variables
        $this->data['promo_id'] = $this->module['promo_id'];
        $this->data['store_id'] = $this->config->get('config_store_id');
        $this->data['lang_id']  = $this->config->get('config_language_id');
        $this->data['setting']  = $this->module['setting'];
        $this->data['theme']    = $this->config->get('config_theme') ? $this->config->get('config_theme') : $this->config->get('config_template');

        // Theme identifier
        $this->data['theme'] = str_replace('theme_', '', $this->data['theme']);
        if ($this->data['theme'] == 'default' && $this->config->get('theme_default_directory') != $this->data['theme']) {
            $this->data['theme'] = $this->config->get('theme_default_directory');
        }

        $this->data = array_replace_recursive(
            $this->data,
            $this->load->language($this->module['path'], $this->module['name'])
        );
    }

    public function index()
    {
        if (!$this->checkAccess('module')) {
            return;
        }

        $data = $this->data;

        $data['css_suffix'] = '';
        $data['custom_css'] = trim(htmlspecialchars_decode($this->module['setting']['module']['custom_css']));

        $i = 0;
        $base_limit = 3;
        $product_id = 0;
        $promotions = array();

        if (!empty($this->request->get['product_id'])) {
            $data['css_suffix'] .= ' islpr-product';
            $product_id = $this->request->get['product_id'];
            $results = $this->module['model']->getPromotions(array('where' => " AND pi.condition_product_ids LIKE '%\"" . (int)$product_id . "\"%'"));

            if ($results) {
                foreach ($results as $promo) {
                    if ($promo['design_status'] && $promo['design_module_banner']) {
                        $i++;
                        $promotions[$promo['promotion_id']] = $promo;

                        if ($i == $base_limit) {
                            break;
                        }
                    }
                }
            }
        }

        if (!empty($this->request->get['path']) && $i < 3) {
            $data['css_suffix'] .= ' islpr-category';
            $parts = explode('_', $this->request->get['path']);

            $queries = '';
            foreach ($parts as $part) {
                $queries .= " OR pi.condition_category_ids LIKE '%\"" . (int)$part . "\"%'";
            }

            $queries = substr($queries, 4);
            $results = $this->module['model']->getPromotions(array('where' => " AND (" . $queries . ")"));

            if ($results) {
                foreach ($results as $promo) {
                    if ($promo['design_status'] && $promo['design_module_banner']) {
                        $i++;
                        $promotions[$promo['promotion_id']] = $promo;

                        if ($i == $base_limit) {
                            break;
                        }
                    }
                }
            }
        }

        if (!empty($this->request->get['manufacturer_id']) && $i < 3) {
            $data['css_suffix'] .= ' islpr-manufacturer';
            $result_id = $this->request->get['manufacturer_id'];

            $results = $this->module['model']->getPromotions(array('where' => " AND (pi.discount_manufacturer_ids LIKE '%\"0\"%' OR pi.discount_manufacturer_ids LIKE '%\"" . (int)$result_id . "\"%')"));

            if ($results) {
                foreach ($results as $promo) {
                    if ($promo['design_status'] && $promo['design_module_banner']) {
                        $i++;
                        $promotions[$promo['promotion_id']] = $promo;

                        if ($i == $base_limit) {
                            break;
                        }
                    }
                }
            }
        }

        if ($i < 3) {
            $sort = array(
                'random' => 'RAND()',
                'priority' => 'priority_order ASC',
            );

            $param = array();
            $param['where'] = $promotions ? " AND pi.promotion_id NOT IN (" . implode(',', array_keys($promotions)). ")" : "";
            $param['order'] = " ORDER BY " . ($promotions ? "RAND()" : $sort[$data['setting']['module']['sort_order']]);
            $param['limit'] = " LIMIT 0, " . ($data['css_suffix'] ? 3 - count($promotions) : $data['setting']['module']['limit']);

            $results = $this->module['model']->getPromotions($param);

            if ($results) {
                foreach ($results as $promo) {
                    if ($promo['design_status'] && $promo['design_module_banner']) {
                        $promotions[$promo['promotion_id']] = $promo;
                    }
                }
            }
        }

        $data['promotions'] = $promotions;

        // Hide modules if no promotions banner found
        if (!$promotions) {
            return;
        }

        return $this->load->view($this->template('module'), $data);
    }

    public function page()
    {
        if (!$this->checkAccess('page')) {
            $this->response->redirect($this->url->link('common/home', '', true));
        }

        $data       = $this->data;
        $lang_id    = $this->config->get('config_language_id');
        $promo_id   = isset($this->request->get['promo_id']) ? (int)$this->request->get['promo_id'] : 0;
        $meta_title = $this->module['setting']['page']['meta_title'][$lang_id] ? $this->module['setting']['page']['meta_title'][$lang_id] : $this->module['setting']['page']['title'][$lang_id];

        $this->document->setTitle($meta_title);
        $this->document->setDescription($this->module['setting']['page']['meta_desc'][$lang_id]);
        $this->document->setKeywords($this->module['setting']['page']['meta_keyword'][$lang_id]);

        $page_url = $this->config->get('config_ssl') . 'index.php?route=' . $this->module['path'] . '/page';
        if ($this->config->get('config_seo_url') && !empty($this->module['setting']['page']['seo_url'][$lang_id])) {
            $page_url = $this->config->get('config_ssl') . $this->module['setting']['page']['seo_url'][$lang_id];
        }

        $data['breadcrumbs'] = array();
        $data['breadcrumbs'][] = array(
            'text' => $this->language->get('text_home'),
            'href' => $this->url->link('common/home', '', true)
        );
        $data['breadcrumbs'][] = array(
            'text' => $this->module['setting']['page']['title'][$lang_id],
            'href' => $page_url
        );

        //=== Show specific banner information
        $specific_promo = false;
        if ($promo_id) {
            $promo = $this->module['model']->getPromotion($promo_id);

            if ($promo && $promo['design_status']) {
                $specific_promo = true;
                $template       = 'page_promo';

                $data['breadcrumbs'][] = array(
                    'text' => $promo['title'],
                    'href' => $promo['page_url']
                );

                $this->document->setTitle($promo['title']);

                $data['heading_title'] = $promo['title'];
                $data['promo'] = $promo;

                // Shortcodes variable
                $shortcode = array(
                    '{condition_items}' => '',
                    '{discount_items}'  => '',
                );

                if (in_array($promo['rule_group'], array('product', 'manufacturer', 'category', 'order'))) {
                    // Product {condition_items}
                    if (in_array($promo['rule_type'], array('buyxgetx', 'buyxgety', 'buyxgetamountoffy', 'ordersofatleastxgety'))) {
                        $data['shortcode'] = 'condition-items';
                        $data['products'] = array();
                        if (!empty($promo['condition_product_ids'])) {
                            $data['products']  = $this->module['model']->getProducts(array(
                                'where' => " AND p.product_id IN (" . implode(',', $promo['condition_product_ids']). ")"
                            ));
                        }

                        $total_products = count($data['products']);
                        $data['slide_arrow'] = $total_products >= 6 ? true : false;
                        $data['slide_column'] = $total_products >= 19 ? 2 : 1;

                        $shortcode['{condition_items}'] = $this->load->view($this->template('product_items'), $data);

                        // Todo: it's discounts items, need to be fixed in admin promo rule
                        if (in_array($promo['rule_type'], array('ordersofatleastxgety'))) {
                            $shortcode['{condition_items}'] = '';
                            $shortcode['{discount_items}']  = $this->load->view($this->template('product_items'), $data);
                        }
                    }

                    // Product {discount_items}
                    if (in_array($promo['rule_type'], array('buyxgety', 'buyxgetamountoffy', 'amountoffy'))) {
                        $data['shortcode'] = 'discount-items';
                        $data['products'] = array();
                        if (!empty($promo['discount_product_ids'])) {
                            $data['products'] = $this->module['model']->getProducts(array(
                                'where' => " AND p.product_id IN (" . implode(',', $promo['discount_product_ids']). ")"
                            ));
                        }

                        $total_products = count($data['products']);
                        $data['slide_arrow'] = $total_products >= 6 ? true : false;
                        $data['slide_column'] = $total_products >= 19 ? 2 : 1;

                        $shortcode['{discount_items}'] = $this->load->view($this->template('product_items'), $data);
                    }

                    // Manufacturer {discount_items}
                    if (in_array($promo['rule_type'], array('xoffitemsinybrands')) && $promo['discount_manufacturer_ids']) {
                        $data['shortcode']  = 'taxonomy-discount-items';
                        $data['taxonomies'] = array();

                        $results = $this->db->query("SELECT * FROM `" . DB_PREFIX . "manufacturer` WHERE `manufacturer_id` IN (" . implode(',', $promo['discount_manufacturer_ids']). ") ORDER BY name ASC");

                        foreach ($results->rows as $result) {
                            $data['taxonomies'][$result['manufacturer_id']] = $result;
                            $data['taxonomies'][$result['manufacturer_id']]['url'] = $this->url->link('product/manufacturer/info', 'manufacturer_id=' . $result['manufacturer_id']);
                            $data['taxonomies'][$result['manufacturer_id']]['products'] = $this->module['model']->getProducts(array(
                                'where' => " AND p.manufacturer_id = " . (int)$result['manufacturer_id'],
                                'limit' => " LIMIT 0, 20"
                            ));

                            $total_products = count($data['taxonomies'][$result['manufacturer_id']]['products']);
                            $data['taxonomies'][$result['manufacturer_id']]['shortcode'] = $data['shortcode'] . '-mfc' . $result['manufacturer_id'];
                            $data['taxonomies'][$result['manufacturer_id']]['slide_arrow'] = $total_products >= 6 ? true : false;
                            $data['taxonomies'][$result['manufacturer_id']]['slide_column'] = $total_products >= 19 ? 2 : 1;
                        }

                        $shortcode['{discount_items}'] = $this->load->view($this->template('taxonomy_items'), $data);
                    }

                    // Category {discount_items} | Todo: actually it's conditions items, need to be fixed in admin promo rule
                    if (in_array($promo['rule_type'], array('percentoffitemsincat', 'buyxgetysamecategory', 'buyxfromygetoffonz', 'xoffitemsinycategoriestiered')) && $promo['condition_category_ids']) {
                        $data['shortcode']  = 'taxonomy-discount-items';
                        $data['taxonomies'] = array();

                        $results = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_description` WHERE `category_id` IN (" . implode(',', $promo['condition_category_ids']). ") AND `language_id` = " . (int)$this->config->get('config_language_id') . " ORDER BY name ASC");

                        foreach ($results->rows as $result) {
                            $data['taxonomies'][$result['category_id']] = $result;
                            $data['taxonomies'][$result['category_id']]['url'] = $this->url->link('product/category', 'path=' . $result['category_id']);
                            $data['taxonomies'][$result['category_id']]['products'] = $this->module['model']->getProducts(array(
                                'join'  => " LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id)",
                                'where' => " AND p2c.category_id = " . (int)$result['category_id'],
                                'limit' => " LIMIT 0, 20"
                            ));

                            $total_products = count($data['taxonomies'][$result['category_id']]['products']);
                            $data['taxonomies'][$result['category_id']]['shortcode'] = $data['shortcode'] . '-ctg' . $result['category_id'];
                            $data['taxonomies'][$result['category_id']]['slide_arrow'] = $total_products >= 6 ? true : false;
                            $data['taxonomies'][$result['category_id']]['slide_column'] = $total_products >= 19 ? 2 : 1;
                        }

                        if (in_array($promo['rule_type'], array('buyxfromygetoffonz'))) {
                            $shortcode['{condition_items}'] = $this->load->view($this->template('taxonomy_items'), $data);
                        } else {
                            $shortcode['{discount_items}'] = $this->load->view($this->template('taxonomy_items'), $data);
                        }
                    }

                    // Category {discount_items}
                    if (in_array($promo['rule_type'], array('buyxfromygetoffonz')) && $promo['discount_category_ids']) {
                        $data['shortcode']  = 'taxonomy-discount-items';
                        $data['taxonomies'] = array();

                        $results = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_description` WHERE `category_id` IN (" . implode(',', $promo['discount_category_ids']). ") AND `language_id` = " . (int)$this->config->get('config_language_id') . " ORDER BY name ASC");

                        foreach ($results->rows as $result) {
                            $data['taxonomies'][$result['category_id']] = $result;
                            $data['taxonomies'][$result['category_id']]['url'] = $this->url->link('product/category', 'path=' . $result['category_id']);
                            $data['taxonomies'][$result['category_id']]['products'] = $this->module['model']->getProducts(array(
                                'join'  => " LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id)",
                                'where' => " AND p2c.category_id = " . (int)$result['category_id'],
                                'limit' => " LIMIT 0, 20"
                            ));

                            $total_products = count($data['taxonomies'][$result['category_id']]['products']);
                            $data['taxonomies'][$result['category_id']]['shortcode'] = $data['shortcode'] . '-ctg' . $result['category_id'];
                            $data['taxonomies'][$result['category_id']]['slide_arrow'] = $total_products >= 6 ? true : false;
                            $data['taxonomies'][$result['category_id']]['slide_column'] = $total_products >= 19 ? 2 : 1;
                        }

                        $shortcode['{discount_items}'] = $this->load->view($this->template('taxonomy_items'), $data);
                    }
                }

                if ($shortcode['{condition_items}'] || $shortcode['{discount_items}']) {
                    $this->document->addStyle('catalog/view/theme/default/stylesheet/promotions/swiper/css/swiper.min.css');
                    $this->document->addStyle('catalog/view/theme/default/stylesheet/promotions/swiper/css/opencart.css');
                    $this->document->addScript('catalog/view/theme/default/stylesheet/promotions/swiper/js/swiper.jquery.min.js');
                }

                $data['promo']['design_page_message'] = $this->renderMessage($promo['design_page_message'], $shortcode);
            }
        }


        //=== Show all promotion banners
        if (!$specific_promo) {
            $template = 'page';

            $data['heading_title'] = $data['setting']['page']['title'][$lang_id];
            $data['page_content']  = !empty($data['setting']['page']['content'][$lang_id]) ? html_entity_decode($data['setting']['page']['content'][$lang_id], ENT_QUOTES, 'UTF-8') : '';
            $data['promotions']    = $this->module['model']->getPromotions();
        }

        $data['custom_css'] = trim(htmlspecialchars_decode($this->module['setting']['page']['custom_css']));

        // === ===

        $data['column_left']    = $this->load->controller('common/column_left');
        $data['column_right']   = $this->load->controller('common/column_right');
        $data['content_top']    = $this->load->controller('common/content_top');
        $data['content_bottom'] = $this->load->controller('common/content_bottom');
        $data['footer']         = $this->load->controller('common/footer');
        $data['header']         = $this->load->controller('common/header');

        $this->response->setOutput($this->load->view($this->template($template), $data));
    }

    public function ping()
    {
        $data  = array();
        $param = array_merge(
            array('ntf_success' => false),
            $this->request->post
        );

        // Theme identifier
        $theme = str_replace('theme_', '', $this->data['theme']);
        if ($theme == 'default' && $this->config->get('theme_default_directory') != $this->data['theme']) {
            $theme = $this->config->get('theme_default_directory');
        }

        if ($this->checkAccess() && isset($this->session->data['isl_promotions']) && $this->cart->getProducts()) {
            foreach ($this->session->data['isl_promotions']['notifications'] as $notification) {
                // Prevent success notification always show when page load
                if ($notification['alert'] == 'success' && !$param['ntf_success']) {
                    continue;
                }
                $notification['theme'] = $theme;

                $data[] = $notification;
            }
            unset($this->session->data['isl_promotions']);
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($data));
    }

    protected function checkAccess($source = '')
    {
        $access = true;

        if (!$this->module['setting']['status']) {
            $access = false;
        }

        if ($access && $this->module['setting']['test_mode']) {
            if (version_compare(VERSION, '2.2.0.0', '<')) {
                $this->load->library('user');
                $this->user = new User($this->registry);
            } else {
                $this->user = new Cart\User($this->registry);
            }

            if (!$this->user->isLogged()) {
                $access = false;
            }
        }

        if ($access && $source == 'module' && !$this->module['setting']['module']['status']) {
            $access = false;
        }

        if ($access && $source == 'page') {
            $promo_id   = isset($this->request->get['promo_id']) ? (int)$this->request->get['promo_id'] : 0;

            // Status of all page promotions, individual promo page always enabled
            if (!$promo_id && !$this->module['setting']['page']['status']) {
                $access = false;
            }
        }

        return $access;
    }

    protected function renderMessage($message, $param = array())
    {
        $template       = array_keys($param);
        $replacement    = array_values($param);

        return html_entity_decode(str_replace($template, $replacement, $message), ENT_QUOTES, 'UTF-8');
    }

    private function template($tplFile = 'module')
    {
        $template = 'default/template/' . $this->module['path'] . '/' . $tplFile . '.tpl';
        if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/' . $this->module['path'] . '/' . $tplFile . '.tpl')) {
            $template = $this->config->get('config_template') . '/template/' . $this->module['path'] . '/' . $tplFile . '.tpl';
        }

        return $template;
    }
}
