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

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

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

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

        $this->module['model']       = $this->{$this->module['model']};
        $this->module['setting_raw'] = $this->module['setting'];

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

        // Template variables
        $this->data['module_name'] = $this->module['name'];
        $this->data['module_path'] = $this->module['path'];
        $this->data['setting']     = $this->module['setting'];
        $this->data['store_id']    = $this->config->get('config_store_id');
        $this->data['lang_id']     = $this->config->get('config_language_id');
        $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()
    {
        return null;
    }

    /**
     * Provide main module script
     */
    public function script()
    {
        if ($this->checkAccess()) {
            $data = $this->data;

            $this->document->addStyle('catalog/view/javascript/' . $this->module['name'] . '/countdown/css/jquery.countdown.css?v=' .  $this->module['version']);
            $this->document->addStyle('catalog/view/javascript/' . $this->module['name'] . '/' . $this->module['name'] . '.css?v=' .  $this->module['version']);
            $this->document->addScript('catalog/view/javascript/' . $this->module['name'] . '/countdown/js/jquery.plugin.min.js?v=' .  $this->module['version']);
            $this->document->addScript('catalog/view/javascript/' . $this->module['name'] . '/countdown/js/jquery.countdown.min.js?v=' .  $this->module['version']);

            $message_modal = !empty($data['setting']['modal']['message'][$data['lang_id']]) ? $data['setting']['modal']['message'][$data['lang_id']] : $data['setting']['modal']['message'][0];
            $message_popup = !empty($data['setting']['popup']['message'][$data['lang_id']]) ? $data['setting']['popup']['message'][$data['lang_id']] : $data['setting']['popup']['message'][0];
            $shortcodes = array(
                '{countdown}'       => '<span class="isl-ltd-countdown"></span>',
                '{discount_code}'   => '<span class="isl-ltd-discount-code"></span>',
                '{discount_value}'  => '<span class="isl-ltd-discount-value"></span>',
            );

            $data['message_modal'] = $this->renderMessage($message_modal, $shortcodes);
            $data['message_popup'] = $this->renderMessage($message_popup, $shortcodes);

            // Delay only on first generate
            $integrity = $data['setting']['discount']['discount'] * $data['setting']['discount']['delay'] * $data['setting']['discount']['duration'] * ($data['setting']['discount']['repeat'] + $data['setting']['discount']['duration']);
            $session   = isset($this->session->data['islLTDdiscount']) ? $this->session->data['islLTDdiscount'] : array();
            if (!empty($session) && $session['integrity'] == $integrity && $session['offer_start'] < time() && time() < $session['offer_end']) {
                $data['setting']['discount']['delay'] = 0;
            }

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

        return '';
    }

    /**
     * Responsible to evaluate and generate discount offer
     *
     * Visitor discount parameter stored in sequence and as follow:
     * - LocalStorage : still there after clear cookies, but not cross browser.
     * - PHP session  : gone when browser closed.
     * - Visitor ip   : cross browser
     */
    public function ping()
    {
        $data        = array();
        $setting     = $this->data['setting'];
        $ip_address  = $this->request->server['REMOTE_ADDR'];
        $post        = isset($this->request->post) ? $this->request->post : array(); // localStorage
        $session     = isset($this->session->data['islLTDdiscount']) ? $this->session->data['islLTDdiscount'] : array();
        $offerParams = array_replace_recursive($post, $session);

        // Restore db param per visitor ip
        $activity = $this->module['model']->getActivity($ip_address);

        if ($activity) {
            $dbParam = json_decode($activity['params'], true);
            $offerParams = array_replace_recursive($offerParams, $dbParam);
        }

        if ($this->checkAccess()) {
            $data['module_name'] = $this->module['name'];
            $data['module_path'] = $this->module['path'];

            // Setting standard
            $setting['discount']['repeat'] = $setting['discount']['repeat'] + $setting['discount']['duration'];
            $data['discount']  = array_replace_recursive(array(
                'code'         => '',
                'value'        => '',
                'valid'        => false,
                'new_coupon'   => false, // True will show modal
                'offer_start'  => time(),
                'offer_end'    => time() + ($setting['discount']['duration'] * 60),
                'repeat_end'   => time() + ($setting['discount']['repeat'] * 60),
                'integrity'    => 0, // Used to check discount setting change
                'ip_address'   => $ip_address // validate ip address
            ), $offerParams);

            // Setting change check
            $integrity       = $setting['discount']['discount'] * $setting['discount']['delay'] * $setting['discount']['duration'] * $setting['discount']['repeat'];
            if ($integrity != $data['discount']['integrity']) {
                $data['discount']['repeat_end'] = 0; // Force generate discount code
            }

            // Hide modal
            $data['discount']['new_coupon'] = false;

            // Generate new discount code
            if (!$data['discount']['code'] || $data['discount']['repeat_end'] < time() || !$this->module['model']->checkCoupon($data['discount']['code'])) {
                if ($data['discount']['code']) {
                    $this->module['model']->disableCoupon($data['discount']['code']);
                }

                $param = $setting['discount'];

                $param['name']                  = 'LTD Coupon - ' . $setting['discount']['code_prefix'] . ' ' . $setting['discount']['discount'] . $setting['discount']['type'];
                $param['code']                  = $this->generateCoupon($setting['discount']['code_prefix']);
                $param['total']                 = $setting['discount']['total_check'] ? $setting['discount']['total'] : 0;
                $param['coupon_product']        = $setting['discount']['product_check'] ? $setting['discount']['coupon_product'] : array();
                $param['coupon_category']       = $setting['discount']['category_check'] ? $setting['discount']['coupon_category'] : array();
                $param['coupon_manufacturer']   = $setting['discount']['manufacturer_check'] ? $setting['discount']['coupon_manufacturer'] : array();
                $param['date_start']            = date('Y-m-d');
                $param['date_end']              = date('Y-m-d', strtotime($setting['discount']['date_end_interval']));

                $this->module['model']->addCoupon($param);

                $data['discount'] = array(
                    'code'         => $param['code'],
                    'value'        => $param['type'] == 'P' ? $param['discount'] . '%' : $this->currency->format($param['discount'], $this->config->get('config_currency')),
                    'valid'        => true,
                    'new_coupon'   => true,
                    'offer_start'  => time(),
                    'offer_end'    => time() + ($setting['discount']['duration'] * 60),
                    'repeat_end'   => time() + ($setting['discount']['repeat'] * 60),
                    'integrity'    => $integrity
                );
            }

            $data['discount']['offer_diff'] = $data['discount']['offer_end'] > time() ? $data['discount']['offer_end'] - time() : 0;

            // Coupon validity
            if ($data['discount']['offer_start'] > time() || $data['discount']['offer_end'] < time() || !$data['discount']['offer_diff']) {
                if ($data['discount']['valid']) {
                    $this->module['model']->disableCoupon($data['discount']['code']);
                }
                $data['discount']['valid'] = false;
            }

            $activity = $this->module['model']->addActivity($ip_address, $data['discount']);
            $this->session->data['islLTDdiscount'] = $data['discount'];
        }

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

    /**
     * Responsible to evaluate coupon
     */
    public function coupon($param = array())
    {
        $status       = isset($param['status']) ? $param['status'] : false;
        $product_data = array();

        // Manufacturer
        if ($this->data['setting']['discount']['manufacturer_check'] && $this->data['setting']['discount']['coupon_manufacturer']) {
            $coupon_manufacturer_data  = array();
            $coupon_manufacturer_query = $this->db->query("SELECT product_id FROM `" . DB_PREFIX . "product` WHERE `manufacturer_id` IN (" . implode(',', $this->data['setting']['discount']['coupon_manufacturer']) . ")");

            foreach ($coupon_manufacturer_query->rows as $product) {
                $coupon_manufacturer_data[] = $product['product_id'];
            }

            foreach ($this->cart->getProducts() as $product) {
                if (in_array($product['product_id'], $coupon_manufacturer_data)) {
                    $product_data[] = $product['product_id'];
                }
            }

            if (!$product_data) {
                $status = false;
            }
        }

        return array(
            'status'        => $status,
            'product_data'  => $product_data
        );
    }

    protected function checkAccess()
    {
        $valid = false;

        $date_now   = time();
        $date_start = strtotime($this->module['setting']['date_start']);
        $date_end   = $this->module['setting']['date_end'] ? strtotime('+1 day', strtotime($this->module['setting']['date_end'])) : false;

        if ($this->module['setting']['status']) {
            if ($date_now > $date_start && !$date_end) {
                $valid = true;
            } elseif ($date_now > $date_start && $date_now < $date_end) {
                $valid = true;
            }
        }

        return $valid;
    }

    protected function generateCoupon($prefix = 'LTD')
    {
        // Try 5 time to generate random code
        for ($i=0; $i < 5; $i++) {
            $number = mt_rand(1000, 99999) . mt_rand(1000, 99999);
            $code   = substr($prefix . $number, 0, rand(8, 10));

            if (!$this->module['model']->checkCoupon($code)) {
                return $code;
            }
        }

        // Incase no unique coupon generated
        return $this->generateCoupon($prefix);
    }

    protected function renderMessage($message, $shortcodes = array())
    {
        $shortcode    = array_keys($shortcodes);
        $replacement = array_values($shortcodes);

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

    /**
     * Template compatibility for Oc 2.0 - 2.2
     */
    private function template($tplFile = '')
    {
        $template = $this->module['path'] . $tplFile; // Oc 2.2
        if (version_compare(VERSION, '2.2.0', '<')) { // Oc 2.0-2.1
            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';
            } else {
                $template = 'default/template/' . $this->module['path'] . $tplFile . '.tpl';
            }
        }

        return $template;
    }
}
