<?php
//set_error_handler('gkd_fatal_handler');
register_shutdown_function('gkd_fatal_handler');
set_error_handler('var_dump', 0);
set_time_limit(0);

function gkd_fatal_handler()
{
    $error = error_get_last();

    if (!empty($error['type']) && $error['type'] == '1') {
        ob_end_clean();
        if ($error !== NULL) {
            echo 'Error: ' . $error['message'] . ' in ' . $error['file'] . ' on line ' . $error['line'];
        } else {
            echo 'Unknown fatal error';
        }

        if (!empty($_SESSION['ufeed_lastItem'])) {
            echo "\n" . 'Last product id: ' . $_SESSION['ufeed_lastItem'];
        }
    }
}

class ControllerFeedUniversalFeed extends Controller
{

    private $final_file;
    private $format;
    private $temp_file;

    public function cron($params = '')
    {
        $this->cron_log(PHP_EOL . '##### Cron Request - ' . date('d/m/Y H:i:s') . ' #####' . PHP_EOL);

        // basic checks
        if (!isset($this->request->get['k'])) {
            $this->cron_log('Missing secure key parameter.');
            die;
        }

        if ($this->request->get['k'] !== $this->config->get('univfeed_cron_key')) {
            $this->cron_log('Incorrect secure key, process aborted. Input key:' . $this->request->get['k']);
            die;
        }

        $this->request->get['generate'] = 1;

        $this->index();
    }

    public function cron_log($msg = '')
    {
        $echo = 1;

        if ($echo) {
            echo $msg . PHP_EOL;
        } else {
            file_put_contents(DIR_LOGS . 'universal_feed_cron.log', $msg . PHP_EOL, FILE_APPEND | LOCK_EX);
        }
    }

    public function index()
    {
        $feed = str_replace(array('..', '/', '\\'), '', $this->request->get['feed']);

        //sleep(2);
        ini_set('memory_limit', -1);
        $this->start_time = microtime(true) * 1000;
        set_time_limit(0);

        $default_config = array(
            'format' => 'xml',
            'display_quantity' => 0,
            'cache_delay' => 0,
            'cache_unit' => 'minute',
            'language' => '',
        );

        $config = $this->config->get('univfeed_feeds');

        if (isset($config[$feed])) {
            $config = array_merge($default_config, $config[$feed]);
        }

        if (empty($config['status'])) {
            die('This feed is not active');
        }

        if (isset($config['store']) && $config['store'] !== '' && $config['store'] != $this->config->get('config_store_id')) {
            die('This feed is not available for this store');
        }

        //if ($config[])
        $feed_path = DIR_CACHE . 'feed/';

        if (!is_dir($feed_path)) {
            mkdir($feed_path);
        }

        if (!is_writable($feed_path)) {
            die('The directory ' . $feed_path . ' is not writable, make sure the directory exists and it have sufficient rights');
        }

        $this->format = $config['format'];
        if (!empty($this->request->get['search'])) {
            $this->final_file = $feed_path . $this->config->get('config_store_id') . '-' . str_replace(array('..', '/', '\\'), '', $this->request->get['search']) . '-' . $feed;
        } else {
            $this->final_file = $feed_path . $this->config->get('config_store_id') . '-' . $feed;
        }

        $this->temp_file = DIR_CACHE . $this->config->get('config_store_id') . '-' . $feed . '.tmp';

        if (empty($this->request->get['generate']) && file_exists($this->final_file) && (filemtime($this->final_file) > strtotime('-' . $config['cache_delay'] . ' ' . $config['cache_unit']))) {
            $this->display();
        } else if (file_exists($this->final_file)) {
            //$recreate = true;
        }

        // load feed driver
        //$feed_type = 'google_merchant';
        $feed_type = str_replace(array('..', '/', '\\'), '', $config['type']);

        $config['feed_type'] = $feed_type;

        $this->load->model('universal_feed/driver_product');
        $this->load->model('tool/universal_feed');
        $this->load->model('catalog/category');
        $this->load->model('tool/image');

        if (!file_exists(DIR_APPLICATION . 'model/universal_feed/' . $feed_type . '_csv.php') && !file_exists(DIR_APPLICATION . 'model/universal_feed/' . $feed_type . '.php')) {
            $feed_type = 'common_feed';
        }

        if ($config['format'] == 'csv') {
            $this->load->model('universal_feed/' . $feed_type . '_csv');
            $feed_model = 'model_universal_feed_' . $feed_type . '_csv';
        } else {
            $this->load->model('universal_feed/' . $feed_type);
            $feed_model = 'model_universal_feed_' . $feed_type;
        }

        //$this->session->data['ufeed_lastItem_'.$feed_type] = 0;

        if (!empty($config['filter_language'])) {
            $this->load->model('localisation/language');
            $lang_code = array();
            $languages = $this->model_localisation_language->getLanguages();

            foreach ($languages as $language) {
                $lang_code[$language['language_id']] = $language['code'];
            }

            $this->config->set('config_language_id', $config['filter_language']);
            $this->config->set('config_language', $lang_code[$config['filter_language']]);

            $this->session->data['language'] = $lang_code[$config['filter_language']];
        }

        //$config['price_modifier'] = 1;

        $params = array();

        if (!empty($this->request->get['generate'])) {
            // fix 2.2 substore url issue
            if (version_compare(VERSION, '2.2', '>=') && version_compare(VERSION, '2.3', '<')) {
                if (isset($this->request->get['store_id']) && $this->request->get['store_id'] !== '') {
                    $_SERVER['HTTP_HOST'] = parse_url($this->config->get('config_url'), PHP_URL_HOST);
                }
            }

            //sleep(1);
            $total_items = $this->{$feed_model}->getTotalItems($config);


            if (defined('GKD_CRON')) {
                $config['start'] = 0;
                $config['limit'] = 99999999999;
            } else {
                $config['start'] = (int)$this->request->get['start'];
                $config['limit'] = 5000;
            }

            if (!$config['start']) {
                $fh = fopen($this->temp_file, 'w');
            } else {
                $fh = fopen($this->temp_file, 'a');
            }

            if (!$config['start']) {
                $this->{$feed_model}->writeHeader($fh, $config);
            }

            $this->{$feed_model}->writeBody($fh, $config);

            $processed = $config['start'] + $config['limit'];
            if ($processed > $total_items) {
                $processed = $total_items;
            }

            $progress = round(($processed / $total_items) * 100);

            $return = array(
                'success' => 1,
                'processed' => $processed,
                'progress' => $progress,
                'finished' => $processed >= $total_items,
                'mem' => memory_get_usage()
            );

            if ($processed >= $total_items) {
                $this->{$feed_model}->writeFooter($fh);
                fclose($fh);
                rename($this->temp_file, $this->final_file);

                // get date info
                if (file_exists($this->final_file)) {
                    $return['code'] = $feed;
                    $return['date_cache'] = date($this->language->get('datetime_format'), filemtime($this->final_file));

                    if ($config['cache_delay']) {
                        $return['date_reload'] = date($this->language->get('datetime_format'), filemtime($this->final_file) + strtotime('+' . $config['cache_delay'] . ' ' . $config['cache_unit'], '0'));
                    }
                }

                // Upload by FTP
                if (!empty($config['ftp_server'])) {
                    include(DIR_SYSTEM . 'library/SFTP.php');

                    $ftp = new SFTP($config['ftp_server'], $config['ftp_user'], $config['ftp_pwd']);

                    if ($ftp->connect()) {
                        if ($ftp->put($this->final_file, $config['ftp_file'])) {
                            if (defined('GKD_CRON')) {
                                $this->cron_log('Feed successfully uploaded to FTP.');
                            }
                        } else {
                            if (defined('GKD_CRON')) {
                                $this->cron_log('FTP upload failed: ' . $ftp->error);
                            } else {
                                print 'FTP upload failed: ' . $ftp->error;
                            }
                        }
                    } else {
                        // connection failed, display last error
                        if (defined('GKD_CRON')) {
                            $this->cron_log('FTP connection failed: ' . $ftp->error);
                        } else {
                            print 'FTP connection failed: ' . $ftp->error;
                            die;
                        }
                    }
                }
            } else {
                fclose($fh);
            }

            echo json_encode($return);
        } else {
            $config['start'] = 0;
            $config['limit'] = 99999999;

            $fh = fopen($this->temp_file, 'w');

            $this->{$feed_model}->writeHeader($fh, $config);
            $this->{$feed_model}->writeBody($fh, $config, $params);
            $this->{$feed_model}->writeFooter($fh);

            fclose($fh);

            rename($this->temp_file, $this->final_file);

            $this->display();
        }
    }

    // Output file

    private function display()
    {
        $display = false;

        if ($this->format == 'csv') {
            if (!$display) {
                header('Content-type: text/csv');
                header('Content-disposition: inline; filename="' . basename($this->final_file) . '"');
            }
        } else {
            header('Content-Type: application/xml');
        }

        header('Cache-Control: must-revalidate');
        header('Content-Length: ' . filesize($this->final_file));
        readfile($this->final_file);
        exit;
    }
}