<?php

/*
 * 2007-2014 Addonline
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 *  @author Addonline <contact@addonline.fr>
 *  @copyright  2007-2014 Addonline
 *  @license    http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 */

if (!defined('_PS_VERSION_'))
    exit;

require_once(_PS_MODULE_DIR_ . 'gls/classes/GLSTools.php');

class Gls extends Module {

    private $_postErrors;
    public static $modulePath = '';
    public static $moduleURL = '';
    static public $GLSFrontToken = '';
    static public $GLSBackToken = '';
    private $_WebServiceWSDLPath = 'http://www.gls-group.eu/276-I-PORTAL-WEBSERVICE/services/ParcelShopSearch/wsdl/2010_01_ParcelShopSearch.wsdl';

    // SQL FILTER ORDER
    const NO_FILTER = 0;
    const WITHOUT_HOME_DELIVERY = 1;

    // Contains the details of the current shop used
    public $account_shop = array(
        'GLS_WEBSERVICE_LOGIN' => '',
        'GLS_WEBSERVICE_PASSWORD' => '',
// 		'GLS_WEIGHT_COEFFICIENT' => '',
        'GLS_EXPORT_FOLDER' => '',
        'GLS_IMPORT_FOLDER' => '',
        'GLS_ZONE_CONFIGURATION' => '',
        'GLS_EXPRESS_DELIVERY_AGENCY' => '',
        'GLS_INTERNATIONAL' => '',
        'GLS_ORDER_STATE' => 3,
        'GLS_ORDER_STATE_IMPORT' => 4,
        'GLS_SHD_ONLYXL' => 0,
        'id_shop' => 1
    );
    public $gls_carriers = array('bp' => array('name' => 'GLS Chez vous', 'delay' => 'Livraison à domicile en 24/48H', 'external' => 'gls_bp'),
        'ado' => array('name' => 'GLS Chez vous+', 'delay' => 'Pour + de flexibilité, vous êtes prévenus de la livraison. En cas d\'absence, choisissez où et quand vous souhaitez être livré', 'external' => 'gls_ado'),
        'mid' => array('name' => 'GLS Avant 13h', 'delay' => 'Livraison Express en mains propres le lendemain avant 13H', 'external' => 'gls'),
        'shd' => array('name' => 'GLS Point Relais', 'delay' => 'Retrait en Point Relais de votre choix', 'external' => 'gls_shd')
    );
    public $GLS_ftp_address = 'ftp.gls-france.com';
    public $GLS_ftp_login = 'addonline';
    public $GLS_ftp_password = '-mAfXmTqC';
    public $GLS_filename_pattern = '/^tbzipdeltimes_(\d{8}).csv$/i';

    public function __construct() {

        $this->name = 'gls';
        $this->tab = 'shipping_logistics';
        $this->version = '1.1.2';
        $this->installed_version = '';
        $this->module_key = '20e6ab0adbab7496ea5c637c4731a4bf';
        $this->author = 'Jetpulp';

        parent::__construct();

        $this->displayName = $this->l('GLS');
        $this->description = $this->l('Deliver in Relay points');

        self::initModuleAccess();

        // Call everytime to prevent the change of the module by a recent one
        $this->initAccount();

        // Check if it's a gls ajax query
        $this->checkAJAX();

        //Vérifie si on a des nouveaux points de nouvelles agences
        $this->importAgenciesZipcode();
    }

    public function install() {
        if (!parent::install())
            return false;

        if (!$this->registerHookByVersion())
            return false;

        //ADMINTAB DESACTIVE
        $result = Db::getInstance()->getRow('
			SELECT id_tab
			FROM `' . _DB_PREFIX_ . 'tab`
			WHERE class_name="AdminGls"');

        if (!$result) {
            $tab = new Tab();
            $languages = Language::getLanguages(false);
            foreach ($languages as $language)
                $tab->name[$language['id_lang']] = 'GLS';
            $tab->class_name = 'AdminGls';
            $tab->module = 'gls';
            $tab->id_parent = Tab::getIdFromClassName('AdminParentOrders');

            if (!$tab->add())
                return false;

            if (is_dir(_PS_MODULE_DIR_ . 'gls/'))
                @copy(_PS_MODULE_DIR_ . 'gls/AdminGls.gif', _PS_IMG_DIR_ . '/AdminGls.gif');
        }

        // If module isn't installed, set default value
        if (!Configuration::get('GLS')) {
            Configuration::updateValue('GLS', $this->version);
            Configuration::updateValue('GLS_SECURE_KEY', md5(time() . rand(0, 10)));
        }

        $result = $this->addShippingMethod('bp');
        $result = $this->addShippingMethod('ado');
        $result = $this->addShippingMethod('mid');
        $result = $this->addShippingMethod('shd');

        //Creation des tables
        $sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'GLS_delivery_info` (
				  `id_cart` int(10) NOT NULL,
				  `id_customer` int(10) NOT NULL,
				  `relay_name` varchar(64) NOT NULL,
				  `relay_address` text NOT NULL,
				  `relay_zipcode` text(10) NOT NULL,
				  `relay_town` varchar(64) NOT NULL,
				  `relay_phone` varchar(25) NULL,
				  `relay_warnbyphone` tinyint(1) NULL,
				  `relay_id` VARCHAR(64) NOT NULL,
				  PRIMARY KEY  (`id_cart`,`id_customer`)
				) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';

        if (!Db::getInstance()->execute($sql))
            return false;

        $sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'GLS_orders_import_export` (
				  `id_order` int(10) NOT NULL,
				  `imported` tinyint(1) NULL,
				  `exported` tinyint(1) NULL,
				  PRIMARY KEY  (`id_order`)
				) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';

        if (!Db::getInstance()->execute($sql))
            return false;

        return true;
    }

    /*
     * * Return the token depend of the type
     */

    static public function getToken($type = 'front') {
        return ($type == 'front') ? Gls::$GLSFrontToken : (($type == 'back') ?
                        Gls::$GLSBackToken : NULL);
    }

    /*
     * * Register hook depending of the Prestashop version used
     */

    private function registerHookByVersion() {
        if (_PS_VERSION_ >= '1.3' &&
                (!$this->registerHook('extraCarrier') ||
                !$this->registerHook('updateCarrier') ||
                !$this->registerHook('newOrder') ||
                !$this->registerHook('BackOfficeHeader') ||
                !$this->registerHook('newOrder') ||
                !$this->registerHook('header')))
            return false;

        if (_PS_VERSION_ >= '1.4' &&
                (!$this->registerHook('processCarrier') ||
                !$this->registerHook('orderDetail') ||
                !$this->registerHook('orderDetailDisplayed') ||
                !$this->registerHook('newOrder') ||
                !$this->registerHook('paymentTop')))
            return false;

        if (_PS_VERSION_ >= '1.5' &&
                (!$this->registerHook('beforeCarrier') || !$this->registerHook('displayMobileHeader')))
            return false;


        return true;
    }

    public function uninstallCommonData() {
        //ADMINTAB DESACTIVE
        // Tab uninstall
        if (($id_tab = Tab::getIdFromClassName('AdminGls'))) {
            $tab = new Tab($id_tab);
            $tab->delete();
        }

        // Récupération des identifiants des transporteurs GLS
        $query = 'SELECT * from ' . _DB_PREFIX_ . 'carrier WHERE external_module_name like \'gls_%\';';
        $carriers = Db::getInstance()->executeS($query);

        // Suppression des informations persistantes
        if (is_array($carriers)) {
            foreach ($carriers as $carrier) {
                $query = 'DELETE FROM ' . _DB_PREFIX_ . 'range_price WHERE id_carrier = ' . $carrier["id_carrier"] . ';';
                Db::getInstance()->execute($query);
                $query = 'DELETE FROM ' . _DB_PREFIX_ . 'carrier_group WHERE id_carrier = ' . $carrier["id_carrier"] . ';';
                Db::getInstance()->execute($query);
                $query = 'DELETE FROM ' . _DB_PREFIX_ . 'carrier_zone WHERE id_carrier = ' . $carrier["id_carrier"] . ';';
                Db::getInstance()->execute($query);

                $oCarrier = new Carrier($carrier["id_carrier"]);
                if (Validate::isLoadedObject($oCarrier)) {
                    /* Get configuration values */
                    $shipping_method = $oCarrier->getShippingMethod();
                    $rangeTable = $oCarrier->getRangeTable();

                    $oCarrier->deleteDeliveryPrice($rangeTable);
                }
            }
        }

        if (!Db::getInstance()->execute('
					UPDATE ' . _DB_PREFIX_ . 'carrier c
					SET c.`deleted` = 1
					WHERE external_module_name like \'gls_%\''))
            return false;

        return true;
    }

    public function uninstall() {
        if (!parent::uninstall())
            return false;

        // Uninstall data that doesn't need to be keep
        if (!$this->uninstallCommonData())
            return false;

        if (Tools::getValue('keepDatabase'))
            return true;

        Configuration::deleteByName('GLS_ACCOUNT_DETAIL');

        $sql = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'GLS_delivery_info`;';

        if (!Db::getInstance()->execute($sql))
            return false;

        $sql = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'GLS_orders_import_export`;';

        if (!Db::getInstance()->execute($sql))
            return false;

        return true;
    }

    /*
     * * #TODO #TODELETE unused method
     * * OnClick for input fields under the module list fields action
     */

    public function onclickOption($type, $href = false) {
        $content = '';

        switch ($type) {
            case 'desactive':
                break;
            case 'reset':
                break;
            case 'delete':
                break;
            case 'uninstall':
                break;
            default:
        }
        return $content;
    }

    /**
     * Init the account_shop variable with the account detail for this shop
     */
    public function initAccount() {
        if (($account_shop_stored = Gls::getAccountDetail()))
            $this->account_shop = $account_shop_stored;
    }

    /*
     * * Init the access directory module for URL and file system
     * * Allow a compatibility for Presta < 1.4
     */

    public static function initModuleAccess() {
        Gls::$modulePath = _PS_MODULE_DIR_ . 'gls/';
        Gls::$GLSFrontToken = sha1('gls' . _COOKIE_KEY_ . 'Front');
        Gls::$GLSBackToken = sha1('gls' . _COOKIE_KEY_ . 'Back');
        Gls::$moduleURL = __PS_BASE_URI__ . 'modules/gls/';
    }

    public function fetchTemplate($path, $name) {
        if (_PS_VERSION_ < '1.4')
            $this->context->smarty->currentTemplate = $name;

        return $this->context->smarty->fetch(dirname(__FILE__) . $path . $name . '.tpl');
    }

    public function hookNewOrder($params) {
        $GLS_relayCarrierId = $this->getGLSRelayCarrierId();

        if ($params['order']->id_carrier != $GLS_relayCarrierId['id_carrier'])
            return;
        $order = $params['order'];
        $order->id_address_delivery = $this->isSameAddress((int) ($order->id_address_delivery), (int) ($order->id_cart), (int) ($order->id_customer));
        $order->update();
    }

    public function hookBackOfficeHeader() {
        $this->context->smarty->assign(array(
            'GLS_token' => Gls::$GLSBackToken,
            'GLS_jQuery_overload_type' => true,
            'new_gls_base_dir' => Gls::$moduleURL,
            'GLS_local_path' => Gls::$modulePath,
            'ps_version' => Gls::$modulePath,
            'GLS_account_set' => Gls::isAccountSet()
        ));

        /* Load JS & CSS files from the context ressources stacks. 
         * It does not work on BackOffice 1.5. For this specific case
         * we load these ressources from the tpl script.  */

        if (_PS_VERSION_ < '1.6') {
            $this->context->smarty->assign(array('ps_version' => '1.5'));
        } else {
            /* Insert jQuery if not already loaded */
            $this->context->controller->addJquery();
            /* Load custom CSS Files */
            $this->context->controller->addCSS($this->_path . 'views/css/style.css');
            /* Load custom JS Files */
            $this->context->controller->addJS($this->_path . 'views/js/gls.js');
        }

        return $this->display(__FILE__, 'bo-header.tpl');
    }

    /* Authorize or not the 24h delivery according to agency code and postcode */
    /* Returns either false (delivery denied) OR the delivery's cost */
    /* [Franck] */

    public function getOrderShippingCost($params, $cost) {

        /* Retrieve customer's delivery address */
        $customer = new Customer($params->id_customer);

        $addresses = $customer->getAddresses($this->context->language->id);
        $postcode = '';
        for ($i = 0; isset($addresses[$i]); $i++) {
            if ($addresses[$i]['id_address'] == $params->id_address_delivery) {
                $country = $addresses[$i]['country'];
                $postcode = $addresses[$i]['postcode'];
            }
        }

        /* Get current agency code */
        $accountDetail = $this->getAccountDetail();

        /* If not current agency code, return false */
        if (empty($accountDetail['GLS_EXPRESS_DELIVERY_AGENCY'])) {
            return false;
        }

        /* If delivery addr is not France, return false */
        if (strpos(strtolower($country), 'france') === false) {
            return false;
        }

        /* Get addresses range */
        $agenciesList = Db::getInstance()->getRow('
			SELECT zipcode_start, zipcode_end
			FROM `' . _DB_PREFIX_ . 'GLS_agency_list`'
                . 'WHERE `agencycode` = "' . $accountDetail['GLS_EXPRESS_DELIVERY_AGENCY'] . '" 
        		AND zipcode_start <= ' . $postcode . ' and zipcode_end >= ' . $postcode . '');

        /* If current agency code */
        if ($postcode > $agenciesList['zipcode_start'] && $postcode < $agenciesList['zipcode_end']) {
            return $cost;
        }

        return false;
    }

    public function hookOrderDetail($params) {
        if (!Gls::isGls($params['order']->id_carrier))
            return;

        $order = $params['order'];

        if (!empty($order->shipping_number))
            $this->context->smarty->assign('followup', $this->get_followup($order->shipping_number));
    }

    public function hookOrderDetailDisplayed($params) {}

    /*
     * * Added to be used properly with OPC
     */

    public function hookHeader($params) {

        if (!($file = basename(Tools::getValue('controller'))))
            $file = str_replace('.php', '', basename($_SERVER['SCRIPT_NAME']));

        Gls::$moduleURL = __PS_BASE_URI__ . 'modules/gls/';

        if (in_array($file, array('order-opc', 'order', 'orderopc'))) {
            $this->context->controller->addCSS($this->_path . 'views/css/style.css');
            $this->context->controller->addCSS($this->_path . 'views/css/gls.css');

            $this->context->controller->addJS($this->_path . 'views/js/jquery.popupoverlay.js');
            $this->context->controller->addJS('https://maps.google.com/maps/api/js?sensor=false&v=3');
            $this->context->controller->addJS($this->_path . 'views/js/glsFront.js');
            $this->context->controller->addJS($this->_path . 'translations/translate_' . $this->context->language->iso_code . '.js');

            $this->context->smarty->assign(
                    array(
                        'one_page_checkout' => (Configuration::get('PS_ORDER_PROCESS_TYPE') ? Configuration::get('PS_ORDER_PROCESS_TYPE') : 0),
                        'warning_message' => $this->l('You need to select a dropp-off point before going to the next step.'),
                        'new_gls_base_dir' => Gls::$moduleURL,
                        'GLS_local_path' => Gls::$modulePath,
                        'GLSToken' => Gls::$GLSFrontToken,
                        'GLS_overload_current_jquery' => false
                    )
            );
            return $this->display(__FILE__, 'header.tpl');
        }
        return '';
    }

    public function hookDisplayMobileHeader($params) {

        if (!($file = basename(Tools::getValue('controller'))))
            $file = str_replace('.php', '', basename($_SERVER['SCRIPT_NAME']));

        if (in_array($file, array('order-opc', 'order', 'orderopc'))) {
            $this->context->smarty->assign(
                    array(
                        'one_page_checkout' => (Configuration::get('PS_ORDER_PROCESS_TYPE') ? Configuration::get('PS_ORDER_PROCESS_TYPE') : 0),
                        'warning_message' => $this->l('You need to select a dropp-off point before going to the next step.'),
                        'new_gls_base_dir' => Gls::$moduleURL,
                        'GLS_local_path' => Gls::$modulePath,
                        'GLSToken' => Gls::$GLSFrontToken,
                        'GLS_overload_current_jquery' => false
                    )
            );
            return $this->display(__FILE__, 'header-mobile.tpl');
        }
        return '';
    }

    public function hookExtraCarrier($params) {

        // TODO : Makes it work with multi-shipping
        if (!Gls::isAccountSet())
            return $this->display(__FILE__, 'checkout_process_errors.tpl');

        $id_carrier = false;
        $address = new Address($this->context->cart->id_address_delivery);
        $id_zone = Address::getZoneById((int) ($address->id));


        if (_PS_VERSION_ >= '1.5')
            $id_carrier = (int) $this->context->cart->id_carrier;

        $this->context->smarty->assign(
                array(
                    'GLS_Data' => array(
                        'PS_VERSION' => _PS_VERSION_
                    )
                )
        );

        return $this->display(__FILE__, 'checkout_process.tpl');
    }

    public function hookBeforeCarrier($params) {

        if (strpos(get_class($this->context->controller), 'Opc') !== false) {
            return $this->hookExtraCarrier($params);
        } else {
            return false;
        }
    }

    /**
     * Return the detailed account
     *
     * @static
     * @return mixed
     */
    public static function getAccountDetail() {
        return unserialize(Configuration::get('GLS_ACCOUNT_DETAIL'));
    }

    /**
     * Check if the account is set
     *
     * @static
     * @return bool
     */
    public static function isAccountSet() {
        $details = Gls::getAccountDetail();
        $accountDetailsExceptions = array('GLS_SHD_ONLYXL' => '1', 'GLS_EXPORT_FOLDER' => '1', 'GLS_IMPORT_FOLDER' => '1', 'GLS_ZONE_CONFIGURATION' => '1', 'GLS_INTERNATIONAL' => '1', 'GLS_ORDER_STATE_IMPORT' => '1', 'GLS_EXPRESS_DELIVERY_AGENCY' => '1');

        if (!$details || !count($details)) {
            return false;
        }

        foreach ($details as $name => $value) {
            if (empty($value) && !isset($accountDetailsExceptions[$name])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Check any submitted form
     */
    private function _postValidation() {
        // Account settings form validation
        if (Tools::isSubmit('submit_account_detail')) {
            if (Tools::getValue('GLS_webservice_login') == '')
                $this->_postErrors[] = $this->l('Invalid Login');
            if (Tools::getValue('GLS_webservice_password') == '')
                $this->_postErrors[] = $this->l('Invalid Password');
        }

        // Order state form validation
        else if (Tools::isSubmit('submit_order_state')) {
            if (!Validate::isUnsignedInt(Tools::getValue('id_order_state')))
                $this->_postErrors[] = $this->l('Invalid order state');
        }
    }

    /**
     * Update account shop
     *
     * @return bool
     */
    public function updateAccountShop() {
        return Configuration::updateValue('GLS_ACCOUNT_DETAIL', serialize($this->account_shop));
    }

    /**
     * Post process
     *
     * @return array
     */
    private function _postProcess() {
        $post_action = array(
            'type' => Tools::getValue('GLS_tab_name'),
            'message_success' => $this->l('Action Succeed'),
            'had_errors' => false
        );

        if (Tools::isSubmit('submit_account_detail')) {
            $this->account_shop = array(
                'GLS_WEBSERVICE_LOGIN' => Tools::getValue('GLS_webservice_login'),
                'GLS_WEBSERVICE_PASSWORD' => Tools::getValue('GLS_webservice_password'),
                'GLS_SHD_ONLYXL' => Tools::getValue('GLS_SHD_ONLYXL'),
//				'GLS_WEIGHT_COEFFICIENT' => Tools::getValue('GLS_weight_coefficient'),
                'GLS_EXPORT_FOLDER' => Tools::getValue('GLS_export_folder'),
                'GLS_IMPORT_FOLDER' => Tools::getValue('GLS_import_folder'),
                'GLS_ZONE_CONFIGURATION' => Tools::getValue('GLS_zone_configuration'),
                'GLS_EXPRESS_DELIVERY_AGENCY' => Tools::getValue('GLS_express_delivery_agency'),
                'GLS_INTERNATIONAL' => Tools::getValue('GLS_international'),
                'id_shop' => $this->context->shop->id,
                'GLS_ORDER_STATE' => (int) $this->account_shop['GLS_ORDER_STATE'],
                'GLS_ORDER_STATE_IMPORT' => (int) $this->account_shop['GLS_ORDER_STATE_IMPORT'],
            );

            if ($this->updateAccountShop()) {
                //TODO : tester les identifiants (appel WS ?) et activer les transporteur si OK
                if (Tools::getValue('GLS_zone_configuration')) {
                    $this->addDefaultCarrierValue($this->getIdCarrierFromMethod('bp'), 'bp');
                    $this->addDefaultCarrierValue($this->getIdCarrierFromMethod('shd'), 'shd');
                    $this->setFranceZoneToAllCarriers();

                    $sqlZone = 'SELECT id_zone FROM ' . _DB_PREFIX_ . 'zone WHERE name like \'%France%\'';
                    $zoneFranceId = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sqlZone);

                    $this->addDeliveryPrices($this->getIdCarrierFromMethod('bp'), $zoneFranceId);
                    $this->addDeliveryPrices($this->getIdCarrierFromMethod('shd'), $zoneFranceId);
                }

                if (Tools::getValue('GLS_express_delivery_agency')) {

                    /* #Franck - Check if 24h delivery carrier exists  */
                    if (!$this->carrierExists('mid')) {
                        /* If not we add it */
                        $this->addCarrier('mid');
                    }

                    //Creation de la table des agences pour la livraison express
                    if (!$this->tableExists(_DB_PREFIX_ . 'GLS_agency_list')) {
                        $sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'GLS_agency_list` (
					  `id_agency_entry` int(10) NOT NULL AUTO_INCREMENT,
					  `agencycode` varchar(255) NULL,
					  `zipcode_start` int(5) NULL,
					  `zipcode_end` int(5) NULL,
					  `validity_date_start` varchar(20) NULL,
					  `validity_date_end` varchar(20) NULL,
					  `last_import_date` varchar(20) NULL,
					  `last_check_date` varchar(20) NULL,
					  PRIMARY KEY  (`id_agency_entry`)
					) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';
                        Db::getInstance()->execute($sql);
                    }

                    //Déclenchement de la récupération des codes postaux par agence en force update
                    $this->importAgenciesZipcode();
                }

                $post_action['message_success'] = $this->l('Account detail has been updated');
            } else {
                $this->_postErrors[] = $this->l('Cannot Update the account shop');
            }
        } else if (Tools::isSubmit('submit_order_state')) {
            Configuration::updateValue('GLS_ORDER_STATE', Tools::getValue('id_order_state'));
            $post_action['message_success'] = $this->l('Order state properly changed');
        }

        if (count($this->_postErrors))
            $post_action['had_errors'] = true;

        return $post_action;
    }

    public function getContent() {
        $post_action = NULL;
        if (!empty($_POST)) {
            $this->_postValidation();
            if (!sizeof($this->_postErrors))
                $post_action = $this->_postProcess();
        }

        $controller = (_PS_VERSION_ < '1.5') ? 'AdminContact' : 'AdminStores';

        // TODO : Fill an array with admi controller name
        $this->context->smarty->assign(array(
            'GLS_token_admin_performance' => Tools::getAdminToken('AdminPerformance' . (int) (Tab::getIdFromClassName('AdminPerformance')) . (int) ($this->context->cookie->id_employee)),
            'GLS_token_admin_carriers' => Tools::getAdminToken('AdminCarriers' . (int) (Tab::getIdFromClassName('AdminCarriers')) . (int) $this->context->employee->id),
            'GLS_token_admin_contact' => array(
                'controller_name' => $controller,
                'token' => Tools::getAdminToken($controller . (int) (Tab::getIdFromClassName($controller)) . (int) $this->context->employee->id)),
            'GLS_token_admin_gls' => Tools::getAdminToken('AdminGls' . (int) (Tab::getIdFromClassName('AdminGls')) . (int) $this->context->employee->id),
            'GLS_token_admin_module' => Tools::getAdminToken('AdminModules' . (int) (Tab::getIdFromClassName('AdminModules')) . (int) $this->context->employee->id),
            'GLS_webservice_login' => Tools::getValue('GLS_webservice_login') ? Tools::getValue('GLS_webservice_login') : $this->account_shop['GLS_WEBSERVICE_LOGIN'],
            'GLS_webservice_password' => Tools::getValue('GLS_webservice_password') ? Tools::getValue('GLS_webservice_password') : $this->account_shop['GLS_WEBSERVICE_PASSWORD'],
            'GLS_SHD_ONLYXL' => Tools::getValue('GLS_SHD_ONLYXL') ? Tools::getValue('GLS_SHD_ONLYXL') : $this->account_shop['GLS_SHD_ONLYXL'],
            //'GLS_weight_coefficient' => Tools::getValue('GLS_weight_coefficient') ? Tools::getValue('GLS_weight_coefficient') : $this->account_shop['GLS_WEIGHT_COEFFICIENT']?$this->account_shop['GLS_WEIGHT_COEFFICIENT']:'1000',
            'GLS_export_folder' => Tools::getValue('GLS_export_folder') ? Tools::getValue('GLS_export_folder') : $this->account_shop['GLS_EXPORT_FOLDER'] ? $this->account_shop['GLS_EXPORT_FOLDER'] : 'modules/gls/export',
            'GLS_import_folder' => Tools::getValue('GLS_import_folder') ? Tools::getValue('GLS_import_folder') : $this->account_shop['GLS_IMPORT_FOLDER'] ? $this->account_shop['GLS_IMPORT_FOLDER'] : 'modules/gls/import',
            'GLS_zone_configuration' => Tools::getValue('GLS_zone_configuration') ? Tools::getValue('GLS_zone_configuration') : $this->account_shop['GLS_ZONE_CONFIGURATION'] ? $this->account_shop['GLS_ZONE_CONFIGURATION'] : '0',
            'GLS_express_delivery_agency' => Tools::getValue('GLS_express_delivery_agency') ? Tools::getValue('GLS_express_delivery_agency') : $this->account_shop['GLS_EXPRESS_DELIVERY_AGENCY'],
            'GLS_international' => Tools::getValue('GLS_international') ? Tools::getValue('GLS_international') : $this->account_shop['GLS_INTERNATIONAL'] ? $this->account_shop['GLS_INTERNATIONAL'] : '0',
            'GLS_PS_WEIGHT_UNIT' => Configuration::get('PS_WEIGHT_UNIT'),
            'GLS_order_states_list' => OrderState::getOrderStates($this->context->language->id),
            'GLS_ORDER_STATE' => (int) $this->account_shop['GLS_ORDER_STATE'],
            'GLS_ORDER_STATE_IMPORT' => (int) $this->account_shop['GLS_ORDER_STATE_IMPORT'],
            'GLS_CRON_URL' => Tools::getHttpHost(true, true) . _MODULE_DIR_ . $this->name . '/cron.php?secure_key=' . Configuration::get('GLS_SECURE_KEY'),
            'GLS_name' => Tools::getValue('GLS_name') ? Tools::getValue('GLS_name') : '',
            'GLS_error_list' => $this->_postErrors,
            'GLS_form_action' => $post_action,
            'GLS_PS_ADMIN_IMG_' => _PS_ADMIN_IMG_,
            'GLS_delay' => Tools::getValue('GLS_delay') ? Tools::getValue('GLS_delay') : '',
            'GLS_local_path' => Gls::$modulePath,
            'GLS_unit_weight_used' => Configuration::get('PS_WEIGHT_UNIT'),
            'GLS_account_set' => Gls::isAccountSet(),
            'GLS_base_dir' => Gls::$moduleURL)
        );

        return $this->display(__FILE__, 'configure.tpl');
    }

    /**
     * #Franck - Check if carrier already exists
     */
    private function carrierExists($id_gls_method) {
        $carriers = Db::getInstance()->executeS('
			SELECT * FROM ' . _DB_PREFIX_ . 'carrier
			WHERE `deleted`="0" AND `external_module_name`="' . $this->gls_carriers[$id_gls_method]['external'] . '"');

        if (isset($carriers[0]['id_carrier'])) {
            return true;
        }

        return false;
    }

    /**
     * Add new carrier
     *
     * @param $name
     * @param $delay
     * @return bool|int
     */
    private function addCarrier($id_gls_method) {
        $ret = false;

        $name = $this->gls_carriers[$id_gls_method]['name'];
        $delay = $this->gls_carriers[$id_gls_method]['delay'];
        $external = $this->gls_carriers[$id_gls_method]['external'];

        if (($carrier = new Carrier())) {
            $delay_lang = array();
            foreach (Language::getLanguages(false) as $lang)
                $delay_lang[$lang['id_lang']] = $delay;

            $carrier->name = $name;
            $carrier->active = 0;
            $carrier->delay = $delay_lang;
            $carrier->grade = 5;
            $carrier->url = 'https://gls-group.eu/FR/fr/suivi-colis?match=@';
            $carrier->shipping_method = 2; //Choix de la tranche en fonction du prix
            $carrier->range_behavior = 1; //comportement hors tranche : désactiver
            /* Set Shipping_external true ONLY for 24h delivery */
            $carrier->shipping_external = !empty($external) && $external == 'gls' ? 1 : 0;
            $carrier->max_weight = 30; //Poids maximum des paquets de 30kg

            $carrier->need_range = 1;
            $carrier->external_module_name = $external;
            $carrier->is_module = (_PS_VERSION_ < '1.4') ? 0 : 1;

            $ret = $carrier->add();
        }
        return $ret ? $carrier->id : false;
    }

    public function displayInfoByCart($id_cart) {}

    /**
     * Set necessaries values to the created carrier
     *
     * @param $id_carrier
     * @param $dlv_mode
     * @return bool
     */
    private function addDefaultCarrierValue($id_carrier, $id_gls_method) {

        // Set a range price
        if (!Db::getInstance()->execute(
                        'INSERT INTO `' . _DB_PREFIX_ . 'range_price`
					 (`id_carrier`, `delimiter1`, `delimiter2`)
					 VALUES (' . (int) $id_carrier . ', 0.000000, 10000.000000)')) {
            $this->_postErrors[] = $this->l('Range price can\'t be added') . (int) $id_carrier;
            return false;
        }

        $range_price_id = Db::getInstance()->Insert_ID();

        $groups = Group::getGroups(Configuration::get('PS_LANG_DEFAULT'));
        foreach ($groups as $group)
            if (!Db::getInstance()->execute(
                            'INSERT INTO `' . _DB_PREFIX_ . 'carrier_group`
						(id_carrier, id_group)
						VALUES(' . (int) $id_carrier . ', ' . (int) ($group['id_group']) . ')')) {
                $this->_postErrors[] = $this->l('Default zone can\'t be added');
                return false;
            }

        // Set default zone FRANCE
        $sqlZone = 'SELECT id_zone FROM ' . _DB_PREFIX_ . 'zone WHERE name like \'%France%\'';
        $zoneFranceId = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sqlZone);

        if (!$zoneFranceId) {
            //If This zone doesn't exits, we create it
            if (!Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'zone` (name, active) VALUES (\'France\', 1)')) {
                $this->_postErrors[] = $this->l('Carrier zone or delivery data can\'t be added');
                return false;
            }
            $zoneFranceId = Db::getInstance()->Insert_ID();
            if (!Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'zone_shop` VALUES (' . $zoneFranceId . ',  ' . $this->context->shop->id . ')')) {
                $this->_postErrors[] = $this->l('Carrier zone or delivery data can\'t be added');
                return false;
            }
            $countryFranceId = Country::getIdByName(null, 'France');
            if (!Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'country` SET id_zone = ' . $zoneFranceId . ' WHERE id_country = ' . $countryFranceId)) {
                $this->_postErrors[] = $this->l('Carrier zone or delivery data can\'t be added');
                return false;
            }
        }

        // Set default zone
        $zones = array();
        if ($id_gls_method != 'bp') {
            $zones[] = array('id_zone' => $zoneFranceId);
        } else {
            $zones = Zone::getZones();
        }
        foreach ($zones as $zone) {
            if (!Db::getInstance()->execute(
                            'INSERT INTO `' . _DB_PREFIX_ . 'carrier_zone`
					(id_carrier, id_zone)
					VALUES(' . (int) $id_carrier . ', ' . (int) ($zone['id_zone']) . ')') ||
                    !Db::getInstance()->execute(
                            'INSERT INTO `' . _DB_PREFIX_ . 'delivery`
					(id_carrier, id_range_price, id_range_weight, id_zone, price)
					VALUES(' . (int) $id_carrier . ', ' . (int) ($range_price_id) . ', NULL,' . (int) ($zone['id_zone']) . ', 0.00)')) {
                $this->_postErrors[] = $this->l('Carrier zone or delivery data can\'t be added');
                return false;
            }
        }

        return true;
    }

    /**
     * Add new shipping method
     *
     * @return bool
     */
    private function addShippingMethod($id_gls_method) {
        if (!$id_gls_method && !isset($this->gls_carriers[$id_gls_method])) {
            return false;
        }

        if (!($id_carrier = Db::getInstance()->getValue(
                'SELECT `id_carrier`
				FROM `' . _DB_PREFIX_ . 'carrier`
				WHERE `external_module_name` = \'gls_' . $id_gls_method . '\''))) {

            // Insert new carrier for under Prestashop
            if (!($id_carrier = $this->addCarrier($id_gls_method))) {
                $this->_postErrors[] = $this->l('Carrier can\'t be created in PrestaShop');
                return false;
            }

            // ajouter le logo, copier le logo (modules\gls\images\picto_toyou.png) dans le répertoire img/s  avec comme non l'id du carrier
            ImageManager::resize(_PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'gls' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR . 'picto_' . $id_gls_method . '.png', _PS_IMG_DIR_ . 's' . DIRECTORY_SEPARATOR . $id_carrier . '.jpg', null, null, 'png');

// 				$this->addDefaultCarrierValue($id_carrier, $id_gls_method);
        } else {

            // ajouter le logo, copier le logo (modules\gls\images\picto_toyou.png) dans le répertoire img/s  avec comme non l'id du carrier
            ImageManager::resize(_PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'gls' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR . 'picto_' . $id_gls_method . '.png', _PS_IMG_DIR_ . 's' . DIRECTORY_SEPARATOR . $id_carrier . '.jpg', null, null, 'png');

            Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'carrier` SET deleted=0
				   WHERE `id_carrier` = ' . $id_carrier);
// 			$this->addDefaultCarrierValue($id_carrier, $id_gls_method);
        }

        Configuration::updateValue('GLS_ID_CARRIER_' . $id_gls_method, $id_carrier);

        return;
    }

    private function getIdCarrierFromMethod($id_gls_method) {
        $id_carrier = Db::getInstance()->getValue(
                'SELECT `id_carrier`
				FROM `' . _DB_PREFIX_ . 'carrier`
				WHERE `external_module_name` = \'gls_' . $id_gls_method . '\'');
        return $id_carrier;
    }

    private function setFranceZoneToAllCarriers() {
        // Récupération des identifiants des transporteurs non GLS
        $query = 'SELECT * from ' . _DB_PREFIX_ . 'carrier WHERE external_module_name not like \'gls_%\' AND deleted = 0;';
        $carriers = Db::getInstance()->executeS($query);

        // Set default zone FRANCE
        $sqlZone = 'SELECT id_zone FROM ' . _DB_PREFIX_ . 'zone WHERE name like \'%France%\'';
        $zoneFranceId = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sqlZone);

        if ($zoneFranceId) {
            foreach ($carriers as $carrier) {
                $id_carrier_zone = Db::getInstance()->getValue(
                        'SELECT `id_carrier`
						FROM `' . _DB_PREFIX_ . 'carrier_zone`
						WHERE `id_zone` = \'' . $zoneFranceId . '\' AND id_carrier = \'' . $carrier["id_carrier"] . '\'');

                if (!$id_carrier_zone) {
                    Db::getInstance()->execute(
                            'INSERT INTO `' . _DB_PREFIX_ . 'carrier_zone`
						(id_carrier, id_zone)
						VALUES(' . (int) $carrier["id_carrier"] . ', ' . (int) ($zoneFranceId) . ')');
                }

                $this->addDeliveryPrices($carrier["id_carrier"], (int) ($zoneFranceId));
            }
        }
    }

    /**
     * Get the followup url
     *
     * @param $exp_number
     * @return mixed
     */
    public function get_followup($exp_number) {}

    /**
     * Get the SQL query to fetch order with gls carrier
     *
     * @static
     * @param $id_order_state
     * @param $weight_coefficient
     * @return string
     */
    public static function getBaseOrdersSQLQuery($id_order_state, $weight_coefficient = 1000) {
        return 'SELECT  o.`id_address_delivery` as id_address_delivery,
						o.`id_order` as id_order,
						o.`id_customer` as id_customer,
						o.`id_cart` as id_cart,
						o.`id_lang` as id_lang,
						CONCAT(c.`firstname`, " ", c.`lastname`) AS `customer`,
						o.`total_paid_tax_incl` as total,
						o.`total_shipping` as shipping,
						o.`date_add` as date, o.`id_currency` as id_currency, o.`id_lang` as id_lang,
						oc.`weight` as weight,
						ROUND(oc.`weight` * ' . (int) $weight_coefficient . ') AS "order_weight",
						gls_info.`relay_name` as gls_Name,
						gls_info.`relay_id` as GLS_Selected_Num
				FROM `' . _DB_PREFIX_ . 'orders` o
				LEFT JOIN `' . _DB_PREFIX_ . 'GLS_delivery_info` gls_info ON (gls_info.`id_cart` = o.`id_cart` AND gls_info.`id_customer` = o.`id_customer`)
				LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON (c.`id_customer` = o.`id_customer`)
				LEFT JOIN `' . _DB_PREFIX_ . 'order_carrier` oc ON (o.`id_order` = oc.`id_order`)
				LEFT JOIN `' . _DB_PREFIX_ . 'carrier` ca ON (o.`id_carrier` = ca.`id_carrier` AND `external_module_name` like \'gls%\' )
				WHERE
				  ca.id_carrier is not null
				  AND (SELECT moh.`id_order_state` FROM `' . _DB_PREFIX_ . 'order_history` moh WHERE moh.`id_order` = o.`id_order` ORDER BY moh.`date_add` DESC LIMIT 1) = ' . (int) ($id_order_state);
    }

    /**
     * Get orders details to create Tickets
     *
     * @static
     * @param array $orderIdList
     * @param int $filterEntries
     * @param int $weight_coefficient
     * @return array
     */
    public static function getOrders($orderIdList = array(), $filterEntries = Gls::NO_FILTER, $weight_coefficient = 1000) {
        $account_shop = Gls::getAccountDetail();
        $id_order_state = $account_shop['GLS_ORDER_STATE'];
        $sql = Gls::getBaseOrdersSQLQuery($id_order_state, $weight_coefficient);

        if (count($orderIdList)) {
            $sql .= ' AND o.id_order IN (';
            foreach ($orderIdList as $id_order)
                $sql .= (int) $id_order . ', ';
            $sql = rtrim($sql, ', ') . ')';
        }
        switch ($filterEntries) {
            case Gls::WITHOUT_HOME_DELIVERY:
                $sql .= 'AND gls.gls_ModeLiv != "LD1" AND gls.gls_ModeLiv != "LDS"';
                break;
        }
        $sql .= '
			GROUP BY o.`id_order`
			ORDER BY o.`id_order` DESC;';

        return Db::getInstance()->executeS($sql);
    }

    /**
     * Get GLS error code
     *
     * @param $code
     * @return string
     */
    public function getErrorCodeDetail($code) {
        global $statCode;

        if (isset($statCode[$code]))
            return $statCode[$code];
        return $this->l('This error isn\'t referred : ') . $code;
    }

    /**
     * @param $id_carrier
     * @return mixed
     */
    public function isGls($id_carrier) {

        return Db::getInstance()->getRow('
			SELECT `id_carrier`
			FROM `' . _DB_PREFIX_ . 'carrier`
			WHERE `id_carrier` = ' . (int) $id_carrier . ' AND external_module_name like \'gls_%\'');
    }

    public function checkAJAX() {
        // Avoid loop inclusion
        static $is_included = false;

        // TODO : Find a way to use it on front
        if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && Tools::strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
            if (Tools::getValue('glstoken') && !$is_included) {
                $is_included = true;
                include(dirname(__FILE__) . '/ajax.php');
                exit(0);
            }
    }

    public function getGLSRelayCarrierId() {
        return Db::getInstance()->getRow('
			SELECT `id_carrier`
			FROM `' . _DB_PREFIX_ . 'carrier`
			WHERE `active` = 1 AND `deleted` = 0 AND `external_module_name` = \'gls_shd\'');
    }

    public function getGLSRelayPointsForZipCode($params, $country = 'FR') {


        $details = Gls::getAccountDetail();
        $login = $details['GLS_WEBSERVICE_LOGIN'];
        $mdp = $details['GLS_WEBSERVICE_PASSWORD'];

        try {
            $pointsRelaisWSService = new SoapClient($this->_WebServiceWSDLPath, array('trace' => 1));

            $aParameters = array('Credentials' => array('UserName' => $login, 'Password' => $mdp), 'Address' => array(
                    'Name1' => '',
                    'Name2' => '',
                    'Name3' => '',
                    'Street1' => $params['street'],
                    'BlockNo1' => '',
                    'Street2' => '',
                    'BlockNo2' => '',
                    'ZipCode' => $params['zipcode'],
                    'City' => $params['city'],
                    'Province' => '',
                    'Country' => $country)
            );

            $result = $pointsRelaisWSService->GetParcelShops($aParameters);

            $aDays = array('0' => $this->l('Monday'), '1' => $this->l('Tuesday'), '2' => $this->l('Wednesday'), '3' => $this->l('Thursday'), '4' => $this->l('Friday'), '5' => $this->l('Saturday'), '6' => $this->l('Sunday'));

            $productMaxWeight = 0;
            foreach ($this->context->cart->getProducts(true) as $product) {
                $weight = 0;
                if (!isset($product['weight_attribute']) || is_null($product['weight_attribute']))
                    $weight = $product['weight'];
                else
                    $weight = $product['weight_attribute'];

                $productMaxWeight = (($productMaxWeight > $weight) ? $productMaxWeight : $weight);
            }
            $onlyxlrelay = $details['GLS_SHD_ONLYXL'] || ($productMaxWeight > 20);

            $listRelais = array();


            //Erreur de login/mot de passe
            if ($result->exitCode->ErrorCode != 0) {
                $this->context->smarty->assign(array(
                    'GLS_error' => $result->exitCode->ErrorCode,
                ));
                return $this->display(__FILE__, 'listRelais.tpl');
            } else {
                $this->context->smarty->assign(array(
                    'GLS_error' => '',
                ));
            }

            foreach ($result->SearchResults as $pointRelais) {
                if ($onlyxlrelay && Tools::substr($pointRelais->Parcelshop->Address->Name1, Tools::strlen($pointRelais->Parcelshop->Address->Name1) - 2, Tools::strlen($pointRelais->Parcelshop->Address->Name1)) != 'XL') {
                    continue;
                }
                $listRelais[] = $pointRelais;
            }
            $this->context->smarty->assign(array(
                'GLS_relais' => $listRelais,
                'aCalendarDays' => $aDays,
            ));
            return $this->display(__FILE__, 'listRelais.tpl');
            return $result;
        } catch (SoapFault $e) {

            //Erreur de WS
            $this->context->smarty->assign(array(
                'GLS_error' => 9999,
            ));
            return $this->display(__FILE__, 'listRelais.tpl');
        }
    }

    public function getDefaultZipCode() {
        if ($this->context->cart->id_address_delivery) {
            $return = array();
            $address = new Address($this->context->cart->id_address_delivery);

            $return['postcode'] = $address->postcode;
            if ($address->address2) {
                $return['street'] = $address->address1 . ' ' . $address->address2;
            } else {
                $return['street'] = $address->address1;
            }
            $return['city'] = $address->city;
            $return['country'] = $address->country;
            $return['phone_mobile'] = $address->phone_mobile;
            $return['phone_number'] = $address->phone;
            return $return;
        } else {
            return;
        }
    }

    public function isSameAddress($idAddress, $idCart, $idCustomer) {

        $return = Db::getInstance()->getRow('SELECT * FROM ' . _DB_PREFIX_ . 'GLS_delivery_info WHERE id_cart =\'' . (int) ($idCart) . '\' AND id_customer =\'' . (int) ($idCustomer) . '\'');
        $psAddress = new Address((int) ($idAddress));
        $newAddress = new Address();

        if ($this->upper($psAddress->lastname) != $this->upper($return['relay_name']) || $this->upper($psAddress->address1) != $this->upper($return['relay_address']) || $this->upper($psAddress->postcode) != $this->upper($return['relay_zipcode']) || $this->upper($psAddress->city) != $this->upper($return['relay_town']) || str_replace(array(' ', '.', '-', ',', ';', '+', '/', '\\', '+', '(', ')'), '', $psAddress->phone_mobile) != $return['relay_phone']) {
            $newAddress->id_customer = (int) ($idCustomer);
            $newAddress->lastname = $psAddress->lastname;
            $newAddress->firstname = $psAddress->firstname;
            $newAddress->company = Tools::substr($return['relay_name'], 0, 32);
            $newAddress->postcode = $return['relay_zipcode'];
            $newAddress->city = $return['relay_town'];
            $newAddress->id_country = Country::getByIso('FR');
            $newAddress->phone = $psAddress->phone;
            $newAddress->phone_mobile = ($return['relay_phone']) ? $return['relay_phone'] : $psAddress->phone_mobile;
            $newAddress->alias = 'GLS Point Relay - ' . date('d-m-Y');
            $newAddress->active = 1;
            $newAddress->deleted = 1;
            $newAddress->address1 = $return['relay_address'];

            $errors = $newAddress->validateController();

            try {
                $newAddress->add();
            } catch (Exception $e) {
                Logger::addLog($e->getMessage(), 1);
                file_put_contents(dirname(__FILE__) . '/test.log', var_export($errors, true));
            }

            return (int) ($newAddress->id);
        }
        return (int) ($psAddress->id);
    }

    public function saveDeliveryDetails($params) {
        $idCart = $this->context->cart->id;
        $idCustomer = $this->context->cart->id_customer;
        $update = Db::getInstance()->getRow('SELECT count(*) FROM ' . _DB_PREFIX_ . 'GLS_delivery_info WHERE id_cart =\'' . (int) ($idCart) . '\' AND id_customer =\'' . (int) ($idCustomer) . '\'');

        if ($update) {
            Db::getInstance()->execute('DELETE FROM ' . _DB_PREFIX_ . 'GLS_delivery_info WHERE id_cart =\'' . (int) ($idCart) . '\' AND id_customer =\'' . (int) ($idCustomer) . '\'');
        }

        $sql = 'INSERT INTO ' . _DB_PREFIX_ . 'GLS_delivery_info
			( `id_cart`, `id_customer`, `relay_name`, `relay_address`,`relay_zipcode`, `relay_town`, `relay_phone`, `relay_warnbyphone`, `relay_id`)
			VALUES (' . (int) ($idCart) . ',' . (int) ($idCustomer) . ',\'' . $params['name'] . '\',\'' . $params['address'] . '\',\'' . $params['zipcode'] . '\',\'' . $params['city'] . '\',\'' . $params['phone'] . '\',' . $params['warnbyphone'] . ',\'' . $params['relayId'] . '\');';
        return Db::getInstance()->execute($sql);
    }

    public function resetDeliveryDetails() {
        $idCart = $this->context->cart->id;
        $idCustomer = $this->context->cart->id_customer;
        $delete = Db::getInstance()->getRow('SELECT count(*) FROM ' . _DB_PREFIX_ . 'GLS_delivery_info WHERE id_cart =\'' . (int) ($idCart) . '\' AND id_customer =\'' . (int) ($idCustomer) . '\'');

        if ($delete) {
            Db::getInstance()->execute('DELETE FROM ' . _DB_PREFIX_ . 'GLS_delivery_info WHERE id_cart =\'' . (int) ($idCart) . '\' AND id_customer =\'' . (int) ($idCustomer) . '\'');
        }
    }

    public function getChoosenRelay() {
        $idCart = $this->context->cart->id;
        $idCustomer = $this->context->cart->id_customer;
        return Db::getInstance()->getRow('SELECT * FROM ' . _DB_PREFIX_ . 'GLS_delivery_info WHERE id_cart =\'' . (int) ($idCart) . '\' AND id_customer =\'' . (int) ($idCustomer) . '\'');
    }

    public function upper($strIn) {
        return Tools::strtoupper(str_replace('-', ' ', Tools::link_rewrite($strIn)));
    }

    private function addDeliveryPrices($id_carrier, $id_zone, $price = 0) {

        $carrier = new Carrier($id_carrier);
        if (Validate::isLoadedObject($carrier)) {
            /* Get configuration values */
            $shipping_method = $carrier->getShippingMethod();
            $rangeTable = $carrier->getRangeTable();

            $carrier->deleteDeliveryPrice($rangeTable);
            $currentList = Carrier::getDeliveryPriceByRanges($rangeTable, $id_carrier);

            $sqlRange = 'SELECT id_' . $rangeTable . ' FROM ' . _DB_PREFIX_ . $rangeTable . ' WHERE id_carrier = \'' . $id_carrier . '\'';
            $id_range = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sqlRange);

            /* Build prices list */
            $priceList = array(); {
                $price = number_format(abs(str_replace(',', '.', $price)), 6, '.', '');
                $priceList[] = array(
                    'id_range_price' => ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) ? $id_range : null,
                    'id_range_weight' => ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) ? $id_range : null,
                    'id_carrier' => (int) $carrier->id,
                    'id_zone' => (int) $id_zone,
                    'price' => $price,
                );
            }
            /* Update delivery prices */
            $carrier->addDeliveryPrice($priceList);
        }
    }

    public function tableExists($tableName) {
        $tables = Db::getInstance()->executeS('SHOW TABLES');
        foreach ($tables as $key => $table) {
            if ($table == $tableName) {
                return true;
            }
        }
        return false;
    }

    public function importAgenciesZipcode($forceupdate = false) {

        // Get current agency code
        $accountDetail = $this->getAccountDetail();

        // If not current agency code, return false
        if (empty($accountDetail['GLS_EXPRESS_DELIVERY_AGENCY'])) {
            return false;
        }

        //On récupère la dernière date de vérification
        $lastCheckDate = Db::getInstance()->getRow('
			SELECT last_check_date
			FROM `' . _DB_PREFIX_ . 'GLS_agency_list`');

        //Si la vérification du fichier distant a déjà été faite et qu'on est pas en force update on ne fait rien
        if ($lastCheckDate['last_check_date'] >= date('Ymd') && !$forceupdate) {
            return true;
        }

        //Récupération de la date du fichier distant
        // Mise en place d'une connexion basique
        $conn_id = ftp_connect($this->GLS_ftp_address);

        // Identification avec un nom d'utilisateur et un mot de passe
        $login_result = ftp_login($conn_id, $this->GLS_ftp_login, $this->GLS_ftp_password);

        /* Use passive mode for downloads */
        ftp_pasv($conn_id, true);

        // Récupération du contenu d'un dossier
        $contents = ftp_nlist($conn_id, ".");

        // Récupération de la date du fichier distant
        $remoteFileDate = 0;
        foreach ($contents as $key => $filename) {
            if (preg_match($this->GLS_filename_pattern, $filename, $matches)) {
                $local_file = $filename;
                $remoteFileDate = ($matches[1]);
            }
        }

        //Récupération de la date déjà importé
        $lastImportDate = 19000101;
        $temp = Db::getInstance()->getRow('
      		SELECT last_import_date
      		FROM `' . _DB_PREFIX_ . 'GLS_agency_list`');
        if (isset($temp['last_import_date'])) {
            $lastImportDate = $temp['last_import_date'];
        }

        //Si on est en force update ou qu'on a un nouveau fichier disponible
        if ($forceupdate || $remoteFileDate > $lastImportDate) {

            //On récupère le dossier d'import
            $glsConfiguration = Gls::getAccountDetail();
            ($glsConfiguration['GLS_IMPORT_FOLDER']) ? $importFolder = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . $glsConfiguration['GLS_IMPORT_FOLDER'] : $importFolder = dirname(__FILE__) . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR;

            if (!file_exists($importFolder) and ! is_dir($importFolder)) {
                echo $importFolder . ' ' . $this->l('does not exist');
                die();
            }

            //On télécharge le fichier dans une variable temporaire
            ob_start();
            $result = ftp_get($conn_id, "php://output", $local_file, FTP_BINARY);
            $data = ob_get_contents();
            $aAgencies = explode("\r\n", $data);
            ob_end_clean();


            //Si le fichier n'est pas vide
            if (count($aAgencies) > 1) {

                //On vide la table
                $query = 'TRUNCATE ' . _DB_PREFIX_ . 'GLS_agency_list;';
                Db::getInstance()->execute($query);


                //On remplit la table avec le nouveau fichier
                foreach ($aAgencies as $key => $agency) {

                    $aData = explode(';', $agency);
                    $insertQuery = 'INSERT INTO ' . _DB_PREFIX_ . 'GLS_agency_list
									(`agencycode`,
									`zipcode_start`,
									`zipcode_end`,
									`validity_date_start`,
									`validity_date_end`,
									`last_import_date`,
									`last_check_date`)
									VALUES
									(\'' . $aData[0] . '\',
									\'' . $aData[1] . '\',
									\'' . $aData[2] . '\',
									\'' . $aData[3] . '\',
									\'' . $aData[4] . '\',
									\'' . $remoteFileDate . '\',
									\'' . date('Ymd') . '\');';
                    Db::getInstance()->execute($insertQuery);
                }
            }//Fin du si le fichier n'est pas vide
        } else { //Si on est pas en force update et qu'on a pas de nouveau fichier disponible
            //On met à jour la check date
            $query = 'UPDATE ' . _DB_PREFIX_ . 'GLS_agency_list SET last_check_date=\'' . date('Ymd') . '\';';
            Db::getInstance()->execute($query);
        }//Fin du si on est en force update ou qu'on a un nouveau fichier disponible
    }

}

