HEX
Server: nginx/1.24.0
System: Linux rtfmfm 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64
User: neo (1001)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/kpopbg.com/speedy/speedy.php
<?php

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

if((empty(Context::getContext()->controller->controller_name) || !preg_match('/^Admin/', Context::getContext()->controller->controller_name)) && session_id() == '') {
    session_start();
}

class Speedy extends Module {
    CONST MODULE_NAME = 'speedy';

    public $error;
    private $error_arr = array();
    private $speedy;
    public $text_error_connect = '';
    public $text_error_currency = '';
    public $bg_currency = '';
    private $parcel_sizes = array(
        1 => 'XS',
        2 => 'S',
        3 => 'M',
        4 => 'L',
        5 => 'XL',
    );

    private $countries_allowed = array(642);

    public function __construct() {
        $this->name = self::MODULE_NAME;
        $this->tab = 'shipping_logistics';
        $this->version = '2.5.6';
        $this->author = 'Speedy JSC';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = array('min' => 1.5, 'max' => _PS_VERSION_);

        parent::__construct();

        $this->displayName = $this->l('Спиди');
        $this->description = $this->l('Модул за доставки със Спиди.');

        $this->confirmUninstall = $this->l('Сигурни ли сте, че искате да деинсталирате този модул?');

        if (!Configuration::get('SPEEDY_MODULE'))
            $this->warning = $this->l('No name provided');

        if ($this->validateCurrency()) {
            $this->bg_currency = new Currency(Currency::getIdByIsoCode('BGN'));
        }

        $this->text_error_connect = $this->l('Възникна грешка при връзката с Спиди! Моля, опитайте отново!');
        $this->text_error_currency = $this->l('За да работи модула Спиди, трябва да има добавена валута Български Лев (BGN)');

        if (!$this->active && Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            if ($carrier && $carrier->active) {
                $carrier->active = 0;
                $carrier->update();
            }
        }

        require_once(dirname(__FILE__) . '/speedy-eps-lib.php');
        $this->speedy = new SpeedyEpsLib();

        spl_autoload_register(array($this, 'autoLoad'));
        $this->autoLoad('SpeedyCache');

        if (!is_dir(SpeedyCache::PATH)) {
            mkdir(SpeedyCache::PATH);
        }
    }

    public function install() {
        $carrierConfig = array('name' => 'Спиди',
            'id_tax_rules_group' => 0,
            'url' => 'https://www.speedy.bg/bg/track-shipment/?shipmentNumber=@',
            'active' => false,
            'deleted' => 0,
            'shipping_handling' => false,
            'range_behavior' => 0,
            'delay' => array(
                'bg' => 'Бърза доставка със Спиди!',
                'en' => 'Fast delivery with Speedy!',
                Language::getIsoById(Configuration::get('PS_LANG_DEFAULT')) => 'Fast delivery with Speedy!'
            ),
            'id_zone' => 1, // Area where the carrier operates
            'is_module' => true, // We specify that it is a module
            'shipping_external' => true,
            'external_module_name' => 'speedy', // We specify the name of the module
            'need_range' => true
        );

        if (version_compare(@constant('_PS_VERSION_'), '1.7', '>=')) {
            $carrierConfig['name'] = ' ';
        }

        $id_carrier = $this->installExternalCarrier($carrierConfig);

        Configuration::updateValue('SPEEDY_CARRIER_ID', (int) $id_carrier);

        if (Shop::isFeatureActive())
            Shop::setContext(Shop::CONTEXT_ALL);

        if (!parent::install() OR !$this->registerHook('backBeforePayment') OR !$this->registerHook('backOfficeHeader') OR !$this->registerHook('extraCarrier') OR !$this->registerHook('updateCarrier') OR !$this->registerHook('AdminOrder') OR !$this->registerHook('header') OR !$this->registerHook('beforeCarrier') OR !$this->registerHook('displayMobileHeader') OR !$this->registerHook('displayPaymentTop') OR !$this->registerHook('displayAdminProductsExtra') OR !$this->registerHook('actionProductSave') OR !$this->registerHook('displayOrderDetail') OR !$this->registerHook('displayPDFInvoice') OR !$this->registerHook('displayCarrierExtraContent'))
            return false;

        Configuration::updateValue('SPEEDY_MODULE', 'Спиди');

        include_once(dirname(__FILE__) . '/sql/sql-install.php');

        foreach ($sql as $s)
            if (!Db::getInstance()->Execute($s))
                return false;

        @mail('support@extensadev.com', 'Speedy Shipping Module installed (PRESTA)', Tools::getHttpHost(true) . __PS_BASE_URI__ . ' - ' . Configuration::get('PS_SHOP_NAME') . "\r\n" . 'version - ' . _PS_VERSION_ . "\r\n" . 'IP - ' . $_SERVER['REMOTE_ADDR'], 'MIME-Version: 1.0' . "\r\n" . 'Content-type: text/plain; charset=UTF-8' . "\r\n" . 'From: ' . Configuration::get('PS_SHOP_NAME') . ' <' . Configuration::get('PS_SHOP_EMAIL') . '>' . "\r\n");

        return true;
    }

    public function uninstall() {
        if (!parent::uninstall() ||
                !Configuration::deleteByName('SPEEDY_MODULE') || !$this->unregisterHook('backBeforePayment') || !$this->unregisterHook('backOfficeHeader') || !$this->unregisterHook('extraCarrier') || !$this->unregisterHook('updateCarrier') || !$this->unregisterHook('AdminOrder') || !$this->unregisterHook('header') || !$this->unregisterHook('beforeCarrier') || !$this->unregisterHook('displayMobileHeader') || !$this->unregisterHook('displayPaymentTop') || !$this->unregisterHook('displayAdminProductsExtra') || !$this->unregisterHook('actionProductSave') || !$this->unregisterHook('displayOrderDetail') || !$this->unregisterHook('displayPDFInvoice') || !$this->unregisterHook('displayCarrierExtraContent'))
            return false;

        //Uninstall Carriers
        //Db::getInstance()->update(_DB_PREFIX_.'carrier', array('deleted' => 1), '`external_module_name` = \'speedy\' OR `id_carrier` IN (SELECT DISTINCT(`id_carrier`) FROM `'._DB_PREFIX_.'fedex_rate_service_code`)');

        include_once(dirname(__FILE__) . '/sql/sql-uninstall.php');
        foreach ($sql as $s)
            if (!Db::getInstance()->Execute($s))
                return false;

        Configuration::deleteByName('SPEEDY_SERVER_ADDRESS');
        Configuration::deleteByName('SPEEDY_USERNAME');
        Configuration::deleteByName('SPEEDY_PASSWORD');
        Configuration::deleteByName('SPEEDY_NAME');
        Configuration::deleteByName('SPEEDY_TELEPHONE');
        Configuration::deleteByName('SPEEDY_WORKINGTIME_END_HOUR');
        Configuration::deleteByName('SPEEDY_WORKINGTIME_END_MIN');
        Configuration::deleteByName('SPEEDY_ALLOWED_METHODS');
        Configuration::deleteByName('SPEEDY_CLIENT_ID');
        Configuration::deleteByName('SPEEDY_PRICING');
        Configuration::deleteByName('SPEEDY_OPTION_BEFORE_PAYMENT');
        Configuration::deleteByName('SPEEDY_RETURN_PAYER_TYPE');
        Configuration::deleteByName('SPEEDY_RETURN_PACKAGE_CITY_SERVICE_ID');
        Configuration::deleteByName('SPEEDY_RETURN_PACKAGE_INTERCITY_SERVICE_ID');
        Configuration::deleteByName('SPEEDY_RETURN_VOUCHER');
        Configuration::deleteByName('SPEEDY_RETURN_VOUCHER_CITY_SERVICE_ID');
        Configuration::deleteByName('SPEEDY_RETURN_VOUCHER_INTERCITY_SERVICE_ID');
        Configuration::deleteByName('SPEEDY_RETURN_VOUCHER_PAYER_TYPE');
        Configuration::deleteByName('SPEEDY_FIXED_PRICE');
        Configuration::deleteByName('SPEEDY_FREE_SHIPPING_TOTAL');
        Configuration::deleteByName('SPEEDY_FREE_METHOD_CITY');
        Configuration::deleteByName('SPEEDY_FREE_METHOD_INTERCITY');
        Configuration::deleteByName('SPEEDY_FREE_METHOD_INTERNATIONAL');
        Configuration::deleteByName('SPEEDY_BACK_DOCUMENTS');
        Configuration::deleteByName('SPEEDY_BACK_RECEIPT');
        Configuration::deleteByName('SPEEDY_DEFAULT_WEIGHT');
        Configuration::deleteByName('SPEEDY_PACKING');
        Configuration::deleteByName('SPEEDY_LABEL_PRINTER');
        Configuration::deleteByName('SPEEDY_ADDITIONAL_COPY_FOR_SENDER');
        Configuration::deleteByName('SPEEDY_INSURANCE');
        Configuration::deleteByName('SPEEDY_FRAGILE');
        Configuration::deleteByName('SPEEDY_FROM_OFFICE');
        Configuration::deleteByName('SPEEDY_OFFICE_ID');
        Configuration::deleteByName('SPEEDY_DOCUMENTS');
        Configuration::deleteByName('SPEEDY_FIXED_TIME');
        Configuration::deleteByName('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT');
        Configuration::deleteByName('SPEEDY_TAKING_DATE');
        Configuration::deleteByName('SPEEDY_ORDER_STATUS_ID');
        Configuration::deleteByName('SPEEDY_GEO_ZONE_ID');
        Configuration::deleteByName('SPEEDY_MIN_PACKAGE_DIMENTION');
        Configuration::deleteByName('SPEEDY_CONVERTION_TO_WIN1251');
        Configuration::deleteByName('SPEEDY_CURRENCY');
        Configuration::deleteByName('SPEEDY_MONEY_TRANSFER');

        $carrier = new Carrier((int) (Configuration::get('SPEEDY_CARRIER_ID')));
        $carrier->deleted = 1;
        if (!$carrier->update())
            return false;

        Configuration::deleteByName('SPEEDY_CARRIER_ID');

        return true;
    }

    private function installExternalCarrier($config) {
        $carrier = new Carrier();
        $carrier->name = $config['name'];
        $carrier->url = $config['url'];
        $carrier->id_tax_rules_group = $config['id_tax_rules_group'];
        $carrier->id_zone = $config['id_zone'];
        $carrier->active = $config['active'];
        $carrier->deleted = $config['deleted'];
        $carrier->delay = $config['delay'];
        $carrier->shipping_handling = $config['shipping_handling'];
        $carrier->range_behavior = $config['range_behavior'];
        $carrier->is_module = $config['is_module'];
        $carrier->shipping_external = $config['shipping_external'];
        $carrier->external_module_name = $config['external_module_name'];
        $carrier->need_range = $config['need_range'];

        $languages = Language::getLanguages(true);
        foreach ($languages as $language) {
            if ($language['iso_code'] == 'fr')
                $carrier->delay[(int) $language['id_lang']] = $config['delay'][$language['iso_code']];
            if ($language['iso_code'] == 'en')
                $carrier->delay[(int) $language['id_lang']] = $config['delay'][$language['iso_code']];
            if ($language['iso_code'] == Language::getIsoById(Configuration::get('PS_LANG_DEFAULT')))
                $carrier->delay[(int) $language['id_lang']] = $config['delay'][$language['iso_code']];
        }

        if ($carrier->add()) {
            $groups = Group::getGroups(true);
            foreach ($groups as $group)
                Db::getInstance()->insert('carrier_group', array('id_carrier' => (int)($carrier->id), 'id_group' => (int)($group['id_group'])));

            $rangePrice = new RangePrice();
            $rangePrice->id_carrier = $carrier->id;
            $rangePrice->delimiter1 = '0';
            $rangePrice->delimiter2 = '10000';
            $rangePrice->add();

            $rangeWeight = new RangeWeight();
            $rangeWeight->id_carrier = $carrier->id;
            $rangeWeight->delimiter1 = '0';
            $rangeWeight->delimiter2 = '10000';
            $rangeWeight->add();

            $zones = Zone::getZones(true);
            foreach ($zones as $zone) {
                Db::getInstance()->insert('carrier_zone', array('id_carrier' => (int)($carrier->id), 'id_zone' => (int)($zone['id_zone'])));
                Db::getInstance()->insert('delivery', array('id_carrier' => (int)($carrier->id), 'id_range_price' => (int)($rangePrice->id), 'id_range_weight' => NULL, 'id_zone' => (int)($zone['id_zone']), 'price' => '0'));

                Db::getInstance()->insert('delivery', array('id_carrier' => (int)($carrier->id), 'id_range_price' => NULL, 'id_range_weight' => (int)($rangeWeight->id), 'id_zone' => (int)($zone['id_zone']), 'price' => '0'));
            }

            if (!copy(dirname(__FILE__) . '/speedy.jpg', _PS_SHIP_IMG_DIR_ . '/' . (int) $carrier->id . '.jpg'))
                return false;

            return (int) ($carrier->id);
        }

        return false;
    }

    public function hookUpdateCarrier($params) {
        if ((int) ($params['id_carrier']) == (int) (Configuration::get('SPEEDY_CARRIER_ID')))
            Configuration::updateValue('SPEEDY_CARRIER_ID', (int) ($params['carrier']->id));
    }

    public function getContent() {
        if (Tools::getValue('ajax_function') == 'speedy_calculate') {
            $this->speedyCalculate();
        } elseif (Tools::getValue('ajax_function') == 'speedy_validate_bill_of_lading') {
            $this->validateBillOfLading();
        } elseif (Tools::getValue('ajax_function') == 'speedy_get_allowed_methods') {
            $this->getAllowedMethods();
        } elseif (Tools::getValue('ajax_function') == 'speedy_get_offices') {
            $this->getOffices();
        } elseif (Tools::getValue('ajax_function') == 'speedy_check_credentials') {
            $this->checkCredentials();
        }

        if (version_compare(@constant('_PS_VERSION_'), '1.7', '>=')) {
            $this->context->smarty->assign('ps_version', '1.7');
        } elseif (version_compare(@constant('_PS_VERSION_'), '1.6', '>=') && version_compare(@constant('_PS_VERSION_'), '1.7', '<')) {
            $this->context->smarty->assign('ps_version', '1.6');
        } else {
            $this->context->smarty->assign('ps_version', '1.5');
        }

        $this->context->smarty->assign('success', '');

        if (!$this->validateCurrency()) {
            $this->context->smarty->assign('error_currency', $this->text_error_currency);
        } else {
            $this->context->smarty->assign('error_currency', '');
        }

        $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));

        if (Tools::isSubmit('form_submitted') && $this->validateSettings()) {
            Configuration::updateValue('SPEEDY_SERVER_ADDRESS', Tools::getValue('speedy_server_address'));
            Configuration::updateValue('SPEEDY_USERNAME', Tools::getValue('speedy_username'));

            if (str_replace(array('*', ' '), '', Tools::getValue('speedy_password'))) {
                Configuration::updateValue('SPEEDY_PASSWORD', Tools::getValue('speedy_password'));
            }

            Configuration::updateValue('SPEEDY_NAME', Tools::getValue('speedy_name'));
            Configuration::updateValue('SPEEDY_TELEPHONE', Tools::getValue('speedy_telephone'));
            Configuration::updateValue('SPEEDY_WORKINGTIME_END_HOUR', Tools::getValue('speedy_workingtime_end_hour'));
            Configuration::updateValue('SPEEDY_WORKINGTIME_END_MIN', Tools::getValue('speedy_workingtime_end_min'));

            if (Tools::getValue('speedy_allowed_methods')) {
                Configuration::updateValue('SPEEDY_ALLOWED_METHODS', serialize(Tools::getValue('speedy_allowed_methods')));
            } else {
                Configuration::updateValue('SPEEDY_ALLOWED_METHODS', array());
            }

            Configuration::updateValue('SPEEDY_CLIENT_ID', Tools::getValue('speedy_client_id'));
            Configuration::updateValue('SPEEDY_PRICING', Tools::getValue('speedy_pricing'));
            Configuration::updateValue('SPEEDY_OPTION_BEFORE_PAYMENT', Tools::getValue('speedy_option_before_payment'));
            Configuration::updateValue('SPEEDY_RETURN_PAYER_TYPE', Tools::getValue('speedy_return_payer_type'));
            Configuration::updateValue('SPEEDY_RETURN_PACKAGE_CITY_SERVICE_ID', Tools::getValue('speedy_return_package_city_service_id'));
            Configuration::updateValue('SPEEDY_RETURN_PACKAGE_INTERCITY_SERVICE_ID', Tools::getValue('speedy_return_package_intercity_service_id'));
            Configuration::updateValue('SPEEDY_RETURN_VOUCHER', Tools::getValue('speedy_return_voucher'));
            Configuration::updateValue('SPEEDY_RETURN_VOUCHER_CITY_SERVICE_ID', Tools::getValue('speedy_return_voucher_city_service_id'));
            Configuration::updateValue('SPEEDY_RETURN_VOUCHER_INTERCITY_SERVICE_ID', Tools::getValue('speedy_return_voucher_intercity_service_id'));
            Configuration::updateValue('SPEEDY_RETURN_VOUCHER_PAYER_TYPE', Tools::getValue('speedy_return_voucher_payer_type'));
            Configuration::updateValue('SPEEDY_FIXED_PRICE', str_replace(',', '.', Tools::getValue('speedy_fixed_price')));
            Configuration::updateValue('SPEEDY_FREE_SHIPPING_TOTAL', Tools::getValue('speedy_free_shipping_total'));
            Configuration::updateValue('SPEEDY_FREE_METHOD_CITY', Tools::getValue('speedy_free_method_city'));
            Configuration::updateValue('SPEEDY_FREE_METHOD_INTERCITY', Tools::getValue('speedy_free_method_intercity'));

            if (Tools::getValue('speedy_free_method_international')) {
                Configuration::updateValue('SPEEDY_FREE_METHOD_INTERNATIONAL', serialize(Tools::getValue('speedy_free_method_international')));
            } else {
                Configuration::updateValue('SPEEDY_FREE_METHOD_INTERNATIONAL', array());
            }

            Configuration::updateValue('SPEEDY_BACK_DOCUMENTS', Tools::getValue('speedy_back_documents'));
            Configuration::updateValue('SPEEDY_BACK_RECEIPT', Tools::getValue('speedy_back_receipt'));
            Configuration::updateValue('SPEEDY_DEFAULT_WEIGHT', str_replace(',', '.', Tools::getValue('speedy_default_weight')));
            Configuration::updateValue('SPEEDY_PACKING', Tools::getValue('speedy_packing'));
            Configuration::updateValue('SPEEDY_LABEL_PRINTER', Tools::getValue('speedy_label_printer'));
            Configuration::updateValue('SPEEDY_ADDITIONAL_COPY_FOR_SENDER', Tools::getValue('speedy_additional_copy_for_sender'));
            Configuration::updateValue('SPEEDY_INSURANCE', Tools::getValue('speedy_insurance'));
            Configuration::updateValue('SPEEDY_FRAGILE', Tools::getValue('speedy_fragile'));
            Configuration::updateValue('SPEEDY_FROM_OFFICE', Tools::getValue('speedy_from_office'));
            Configuration::updateValue('SPEEDY_OFFICE_ID', Tools::getValue('speedy_office_id'));
            Configuration::updateValue('SPEEDY_DOCUMENTS', Tools::getValue('speedy_documents'));
            Configuration::updateValue('SPEEDY_FIXED_TIME', Tools::getValue('speedy_fixed_time'));
            Configuration::updateValue('SPEEDY_CHECK_OFFICE_WORK_DAY', Tools::getValue('speedy_check_office_work_day'));
            Configuration::updateValue('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT', Tools::getValue('speedy_invoice_courier_sevice_as_text'));
            Configuration::updateValue('SPEEDY_TAKING_DATE', Tools::getValue('speedy_taking_date'));
            Configuration::updateValue('SPEEDY_ORDER_STATUS_ID', Tools::getValue('speedy_order_status_id'));
            Configuration::updateValue('SPEEDY_GEO_ZONE_ID', Tools::getValue('speedy_geo_zone_id'));
            Configuration::updateValue('SPEEDY_MIN_PACKAGE_DIMENTION', Tools::getValue('speedy_min_package_dimention'));
            Configuration::updateValue('SPEEDY_CONVERTION_TO_WIN1251', Tools::getValue('speedy_convertion_to_win1251'));
            Configuration::updateValue('SPEEDY_CURRENCY', 'BGN');

            $this->_addWeightDimentions(Tools::getValue('weight_dimensions'));

            if (Tools::getIsset('speedy_money_transfer') && $this->speedy->isAvailableMoneyTransfer()) {
                Configuration::updateValue('SPEEDY_MONEY_TRANSFER', Tools::getValue('speedy_money_transfer'));
            } else {
                Configuration::updateValue('SPEEDY_MONEY_TRANSFER', false);
            }

            $carrier->active = Tools::getValue('speedy_status') ? true : false;
            $carrier->update();

            // import file
            if ( Tools::fileAttachment('speedy_table_rate_file', false)) {
                $table_rate_file = Tools::fileAttachment('speedy_table_rate_file', true);
                if (($handle_import = fopen($table_rate_file['tmp_name'], 'r')) !== false) {
                    $handle_import_data = fgetcsv($handle_import, 100000); // remove title line
                }

                $file_columns_indexes = array();
                foreach($handle_import_data as $index => $columnName) {
                    $file_columns_indexes[$columnName] = array_search($columnName, $handle_import_data);
                }

                while (($handle_import_data = fgetcsv($handle_import, 100000)) !== false) {
                    $data[] = array(
                        'service_id' => $handle_import_data[$file_columns_indexes['ServiceID']],
                        'take_from_office' => $handle_import_data[$file_columns_indexes['TakeFromOffice']],
                        'weight' => str_replace(',', '.', $handle_import_data[$file_columns_indexes['Weight']]),
                        'order_total' => str_replace(',', '.', $handle_import_data[$file_columns_indexes['OrderTotal']]),
                        'price_without_vat' => str_replace(',', '.', $handle_import_data[$file_columns_indexes['PriceWithoutVAT']]),
                        'fixed_time_delivery' => str_replace(',', '.', $handle_import_data[$file_columns_indexes['FixedTimeDelivery']]),
                    );
                }

                $this->_importFilePrice($data);
            }

            $this->context->smarty->assign('success', $this->l('Успешно променихте параметрите на Спиди!'));
        }

        if (isset($this->error_arr['error_warning'])) {
            $this->context->smarty->assign('error_warning', $this->error_arr['error_warning']);
        } else {
            $this->context->smarty->assign('error_warning', '');
        }

        if (isset($this->error_arr['error_username'])) {
            $this->context->smarty->assign('error_username', $this->error_arr['error_username']);
        } else {
            $this->context->smarty->assign('error_username', '');
        }

        if (isset($this->error_arr['error_password'])) {
            $this->context->smarty->assign('error_password', $this->error_arr['error_password']);
        } else {
            $this->context->smarty->assign('error_password', '');
        }

        if (isset($this->error_arr['error_name'])) {
            $this->context->smarty->assign('error_name', $this->error_arr['error_name']);
        } else {
            $this->context->smarty->assign('error_name', '');
        }

        if (isset($this->error_arr['error_telephone'])) {
            $this->context->smarty->assign('error_telephone', $this->error_arr['error_telephone']);
        } else {
            $this->context->smarty->assign('error_telephone', '');
        }

        if (isset($this->error_arr['error_default_weight'])) {
            $this->context->smarty->assign('error_default_weight', $this->error_arr['error_default_weight']);
        } else {
            $this->context->smarty->assign('error_default_weight', '');
        }

        if (isset($this->error_arr['error_allowed_methods'])) {
            $this->context->smarty->assign('error_allowed_methods', $this->error_arr['error_allowed_methods']);
        } else {
            $this->context->smarty->assign('error_allowed_methods', '');
        }

        if (isset($this->error_arr['error_speedy_client_id'])) {
            $this->context->smarty->assign('error_speedy_client_id', $this->error_arr['error_speedy_client_id']);
        } else {
            $this->context->smarty->assign('error_speedy_client_id', '');
        }

        if (isset($this->error_arr['error_taking_date'])) {
            $this->context->smarty->assign('error_taking_date', $this->error_arr['error_taking_date']);
        } else {
            $this->context->smarty->assign('error_taking_date', '');
        }

        if (isset($this->error_arr['error_free_method_international'])) {
            $this->context->smarty->assign('error_free_method_international', $this->error_arr['error_free_method_international']);
        } else {
            $this->context->smarty->assign('error_free_method_international', '');
        }

        if (isset($this->error_arr['error_speedy_packing'])) {
            $this->context->smarty->assign('error_speedy_packing', $this->error_arr['error_speedy_packing']);
        } else {
            $this->context->smarty->assign('error_speedy_packing', '');
        }

        $this->context->smarty->assign('speedy_version', $this->version);

        if (Tools::getIsset('speedy_server_address') && Tools::getValue('speedy_server_address')) {
            $this->context->smarty->assign('speedy_server_address', Tools::getValue('speedy_server_address'));
        } elseif (Configuration::get('SPEEDY_SERVER_ADDRESS')) {
            $this->context->smarty->assign('speedy_server_address', Configuration::get('SPEEDY_SERVER_ADDRESS'));
        } else {
            $this->context->smarty->assign('speedy_server_address', 'https://www.speedy.bg/eps/main01.wsdl');
        }

        if (Tools::getValue('speedy_username')) {
            $this->context->smarty->assign('speedy_username', Tools::getValue('speedy_username'));
        } else {
            $this->context->smarty->assign('speedy_username', Configuration::get('SPEEDY_USERNAME'));
        }

        if (Configuration::get('SPEEDY_PASSWORD')) {
            $this->context->smarty->assign('speedy_password', '********');
        } else {
            $this->context->smarty->assign('speedy_password', Tools::getValue('speedy_password'));
        }

        if (Tools::getValue('speedy_name')) {
            $this->context->smarty->assign('speedy_name', Tools::getValue('speedy_name'));
        } else {
            $this->context->smarty->assign('speedy_name', Configuration::get('SPEEDY_NAME'));
        }

        if (Tools::getValue('speedy_telephone')) {
            $this->context->smarty->assign('speedy_telephone', Tools::getValue('speedy_telephone'));
        } else {
            $this->context->smarty->assign('speedy_telephone', Configuration::get('SPEEDY_TELEPHONE'));
        }

        if (Tools::getValue('speedy_workingtime_end_hour')) {
            $this->context->smarty->assign('speedy_workingtime_end_hour', Tools::getValue('speedy_workingtime_end_hour'));
        } else {
            $this->context->smarty->assign('speedy_workingtime_end_hour', Configuration::get('SPEEDY_WORKINGTIME_END_HOUR'));
        }

        if (Tools::getValue('speedy_workingtime_end_min')) {
            $this->context->smarty->assign('speedy_workingtime_end_min', Tools::getValue('speedy_workingtime_end_min'));
        } else {
            $this->context->smarty->assign('speedy_workingtime_end_min', Configuration::get('SPEEDY_WORKINGTIME_END_MIN'));
        }

        if (Tools::getIsset('speedy_allowed_methods')) {
            $this->context->smarty->assign('speedy_allowed_methods', Tools::getValue('speedy_allowed_methods'));
        } elseif (Configuration::get('SPEEDY_ALLOWED_METHODS') && $_SERVER['REQUEST_METHOD'] != 'POST') {
            $this->context->smarty->assign('speedy_allowed_methods', unserialize(Configuration::get('SPEEDY_ALLOWED_METHODS')));
        } else {
            $this->context->smarty->assign('speedy_allowed_methods', array());
        }

        if (Tools::getValue('speedy_client_id')) {
            $this->context->smarty->assign('speedy_client_id', Tools::getValue('speedy_client_id'));
        } else {
            $this->context->smarty->assign('speedy_client_id', Configuration::get('SPEEDY_CLIENT_ID'));
        }

        if (Tools::getValue('speedy_pricing')) {
            $this->context->smarty->assign('speedy_pricing', Tools::getValue('speedy_pricing'));
        } else {
            $this->context->smarty->assign('speedy_pricing', Configuration::get('SPEEDY_PRICING'));
        }

        if (Tools::getValue('speedy_option_before_payment')) {
            $this->context->smarty->assign('speedy_option_before_payment', Tools::getValue('speedy_option_before_payment'));
        } else {
            $this->context->smarty->assign('speedy_option_before_payment', Configuration::get('SPEEDY_OPTION_BEFORE_PAYMENT'));
        }

        if (Tools::getValue('speedy_return_payer_type')) {
            $this->context->smarty->assign('speedy_return_payer_type', Tools::getValue('speedy_return_payer_type'));
        } else {
            $this->context->smarty->assign('speedy_return_payer_type', Configuration::get('SPEEDY_RETURN_PAYER_TYPE'));
        }

        if (Tools::getValue('speedy_return_package_city_service_id')) {
            $this->context->smarty->assign('speedy_return_package_city_service_id', Tools::getValue('speedy_return_package_city_service_id'));
        } else {
            $this->context->smarty->assign('speedy_return_package_city_service_id', Configuration::get('SPEEDY_RETURN_PACKAGE_CITY_SERVICE_ID'));
        }

        if (Tools::getValue('speedy_return_package_intercity_service_id')) {
            $this->context->smarty->assign('speedy_return_package_intercity_service_id', Tools::getValue('speedy_return_package_intercity_service_id'));
        } else {
            $this->context->smarty->assign('speedy_return_package_intercity_service_id', Configuration::get('SPEEDY_RETURN_PACKAGE_INTERCITY_SERVICE_ID'));
        }

        if (Tools::getValue('speedy_return_voucher')) {
            $this->context->smarty->assign('speedy_return_voucher', Tools::getValue('speedy_return_voucher'));
        } else {
            $this->context->smarty->assign('speedy_return_voucher', Configuration::get('SPEEDY_RETURN_VOUCHER'));
        }

        if (Tools::getValue('speedy_return_voucher_city_service_id')) {
            $this->context->smarty->assign('speedy_return_voucher_city_service_id', Tools::getValue('speedy_return_voucher_city_service_id'));
        } else {
            $this->context->smarty->assign('speedy_return_voucher_city_service_id', Configuration::get('SPEEDY_RETURN_VOUCHER_CITY_SERVICE_ID'));
        }

        if (Tools::getValue('speedy_return_voucher_intercity_service_id')) {
            $this->context->smarty->assign('speedy_return_voucher_intercity_service_id', Tools::getValue('speedy_return_voucher_intercity_service_id'));
        } else {
            $this->context->smarty->assign('speedy_return_voucher_intercity_service_id', Configuration::get('SPEEDY_RETURN_VOUCHER_INTERCITY_SERVICE_ID'));
        }

        if (Tools::getValue('speedy_return_voucher_payer_type')) {
            $this->context->smarty->assign('speedy_return_voucher_payer_type', Tools::getValue('speedy_return_voucher_payer_type'));
        } else {
            $this->context->smarty->assign('speedy_return_voucher_payer_type', Configuration::get('SPEEDY_RETURN_VOUCHER_PAYER_TYPE'));
        }

        if (Tools::getValue('speedy_fixed_price')) {
            $this->context->smarty->assign('speedy_fixed_price', str_replace(',', '.', Tools::getValue('speedy_fixed_price')));
        } else {
            $this->context->smarty->assign('speedy_fixed_price', Configuration::get('SPEEDY_FIXED_PRICE'));
        }

        if (Tools::getValue('speedy_free_shipping_total')) {
            $this->context->smarty->assign('speedy_free_shipping_total', Tools::getValue('speedy_free_shipping_total'));
        } else {
            $this->context->smarty->assign('speedy_free_shipping_total', Configuration::get('SPEEDY_FREE_SHIPPING_TOTAL'));
        }

        if (Tools::getValue('speedy_free_method_city')) {
            $this->context->smarty->assign('speedy_free_method_city', Tools::getValue('speedy_free_method_city'));
        } else {
            $this->context->smarty->assign('speedy_free_method_city', Configuration::get('SPEEDY_FREE_METHOD_CITY'));
        }

        if (Tools::getValue('speedy_free_method_intercity')) {
            $this->context->smarty->assign('speedy_free_method_intercity', Tools::getValue('speedy_free_method_intercity'));
        } else {
            $this->context->smarty->assign('speedy_free_method_intercity', Configuration::get('SPEEDY_FREE_METHOD_INTERCITY'));
        }

        if (Tools::getIsset('speedy_free_method_international')) {
            $this->context->smarty->assign('speedy_free_method_international', Tools::getValue('speedy_free_method_international'));
        } elseif (Configuration::get('SPEEDY_FREE_METHOD_INTERNATIONAL') && $_SERVER['REQUEST_METHOD'] != 'POST') {
            $this->context->smarty->assign('speedy_free_method_international', unserialize(Configuration::get('SPEEDY_FREE_METHOD_INTERNATIONAL')));
        } else {
            $this->context->smarty->assign('speedy_free_method_international', array());
        }

        if (Tools::getValue('speedy_back_documents')) {
            $this->context->smarty->assign('speedy_back_documents', Tools::getValue('speedy_back_documents'));
        } else {
            $this->context->smarty->assign('speedy_back_documents', Configuration::get('SPEEDY_BACK_DOCUMENTS'));
        }

        if (Tools::getValue('speedy_back_receipt')) {
            $this->context->smarty->assign('speedy_back_receipt', Tools::getValue('speedy_back_receipt'));
        } else {
            $this->context->smarty->assign('speedy_back_receipt', Configuration::get('SPEEDY_BACK_RECEIPT'));
        }

        if (Tools::getValue('speedy_default_weight')) {
            $this->context->smarty->assign('speedy_default_weight', Tools::getValue('speedy_default_weight'));
        } else {
            $this->context->smarty->assign('speedy_default_weight', Configuration::get('SPEEDY_DEFAULT_WEIGHT'));
        }

        if (Tools::getValue('speedy_packing')) {
            $this->context->smarty->assign('speedy_packing', Tools::getValue('speedy_packing'));
        } else {
            $this->context->smarty->assign('speedy_packing', Configuration::get('SPEEDY_PACKING'));
        }

        if (Tools::getValue('speedy_label_printer')) {
            $this->context->smarty->assign('speedy_label_printer', Tools::getValue('speedy_label_printer'));
        } else {
            $this->context->smarty->assign('speedy_label_printer', Configuration::get('SPEEDY_LABEL_PRINTER'));
        }

        if (Tools::getValue('speedy_additional_copy_for_sender')) {
            $this->context->smarty->assign('speedy_additional_copy_for_sender', Tools::getValue('speedy_additional_copy_for_sender'));
        } else {
            $this->context->smarty->assign('speedy_additional_copy_for_sender', Configuration::get('SPEEDY_ADDITIONAL_COPY_FOR_SENDER'));
        }

        if (Tools::getValue('speedy_insurance')) {
            $this->context->smarty->assign('speedy_insurance', Tools::getValue('speedy_insurance'));
        } else {
            $this->context->smarty->assign('speedy_insurance', Configuration::get('SPEEDY_INSURANCE'));
        }

        if (Tools::getValue('speedy_fragile')) {
            $this->context->smarty->assign('speedy_fragile', Tools::getValue('speedy_fragile'));
        } else {
            $this->context->smarty->assign('speedy_fragile', Configuration::get('SPEEDY_FRAGILE'));
        }

        if (Tools::getValue('speedy_from_office')) {
            $this->context->smarty->assign('speedy_from_office', Tools::getValue('speedy_from_office'));
        } else {
            $this->context->smarty->assign('speedy_from_office', Configuration::get('SPEEDY_FROM_OFFICE'));
        }

        if (Tools::getValue('speedy_office_id')) {
            $this->context->smarty->assign('speedy_office_id', Tools::getValue('speedy_office_id'));
        } else {
            $this->context->smarty->assign('speedy_office_id', Configuration::get('SPEEDY_OFFICE_ID'));
        }

        if (Tools::getValue('speedy_documents')) {
            $this->context->smarty->assign('speedy_documents', Tools::getValue('speedy_documents'));
        } else {
            $this->context->smarty->assign('speedy_documents', Configuration::get('SPEEDY_DOCUMENTS'));
        }

        if (Tools::getValue('speedy_fixed_time')) {
            $this->context->smarty->assign('speedy_fixed_time', Tools::getValue('speedy_fixed_time'));
        } else {
            $this->context->smarty->assign('speedy_fixed_time', Configuration::get('SPEEDY_FIXED_TIME'));
        }

        if (Tools::getValue('speedy_check_office_work_day')) {
            $this->context->smarty->assign('speedy_check_office_work_day', Tools::getValue('speedy_check_office_work_day'));
        } else {
            $this->context->smarty->assign('speedy_check_office_work_day', Configuration::get('SPEEDY_CHECK_OFFICE_WORK_DAY'));
        }

        if (Tools::getValue('speedy_invoice_courier_sevice_as_text')) {
            $this->context->smarty->assign('speedy_invoice_courier_sevice_as_text', Tools::getValue('speedy_invoice_courier_sevice_as_text'));
        } else {
            $this->context->smarty->assign('speedy_invoice_courier_sevice_as_text', Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT'));
        }

        if (Tools::getValue('speedy_taking_date')) {
            $this->context->smarty->assign('speedy_taking_date', Tools::getValue('speedy_taking_date'));
        } else {
            $this->context->smarty->assign('speedy_taking_date', Configuration::get('SPEEDY_TAKING_DATE'));
        }

        if (Tools::getValue('speedy_currency')) {
            $this->context->smarty->assign('speedy_currency', Tools::getValue('speedy_currency'));
        } else {
            $this->context->smarty->assign('speedy_currency', Configuration::get('SPEEDY_CURRENCY'));
        }

        if (Tools::getValue('speedy_weight_class_id')) {
            $this->context->smarty->assign('speedy_weight_class_id', Tools::getValue('speedy_weight_class_id'));
        } else {
            $this->context->smarty->assign('speedy_weight_class_id', Configuration::get('SPEEDY_WEIGHT_CLASS_ID'));
        }

        if (Tools::getValue('speedy_order_status_id')) {
            $this->context->smarty->assign('speedy_order_status_id', Tools::getValue('speedy_order_status_id'));
        } else {
            $this->context->smarty->assign('speedy_order_status_id', Configuration::get('SPEEDY_ORDER_STATUS_ID'));
        }

        if (Tools::getValue('speedy_geo_zone_id')) {
            $this->context->smarty->assign('speedy_geo_zone_id', Tools::getValue('speedy_geo_zone_id'));
        } else {
            $this->context->smarty->assign('speedy_geo_zone_id', Configuration::get('SPEEDY_GEO_ZONE_ID'));
        }

        if (Tools::getValue('speedy_min_package_dimention')) {
            $this->context->smarty->assign('speedy_min_package_dimention', Tools::getValue('speedy_min_package_dimention'));
        } else {
            $this->context->smarty->assign('speedy_min_package_dimention', Configuration::get('SPEEDY_MIN_PACKAGE_DIMENTION'));
        }

        if (Tools::getValue('speedy_status')) {
            $this->context->smarty->assign('speedy_status', Tools::getValue('speedy_status'));
        } else {
            $this->context->smarty->assign('speedy_status', $carrier->active ? 1 : 0);
        }

        if (Tools::getValue('speedy_convertion_to_win1251')) {
            $this->context->smarty->assign('speedy_convertion_to_win1251', Tools::getValue('speedy_convertion_to_win1251'));
        } else {
            $this->context->smarty->assign('speedy_convertion_to_win1251', Configuration::get('SPEEDY_CONVERTION_TO_WIN1251'));
        }

        $this->context->smarty->assign('geo_zones', Zone::getZones());

        $this->context->smarty->assign('weight_dimensions', $this->_getWeightDimentions());

        $this->context->smarty->assign('order_statuses', OrderState::getOrderStates($this->context->employee->id_lang));

        $this->context->smarty->assign('services', $this->speedy->getServices($this->context->language->iso_code));

        $this->context->smarty->assign('clients', $this->speedy->getListContractClients());

        $this->context->smarty->assign('offices', $this->speedy->getOffices(null, null, $this->context->language->iso_code));

        if ($this->speedy->isAvailableMoneyTransfer()) {
            $this->context->smarty->assign('available_money_transfer', true);

            if (Tools::getValue('speedy_money_transfer')) {
                $this->context->smarty->assign('speedy_money_transfer', Tools::getValue('speedy_money_transfer'));
            } else {
                $this->context->smarty->assign('speedy_money_transfer', Configuration::get('SPEEDY_MONEY_TRANSFER'));
            }
        } else {
            $this->context->smarty->assign('available_money_transfer', false);
            $this->context->smarty->assign('speedy_money_transfer', false);
        }

        $this->context->smarty->assign('pricings', array(
            'calculator' => $this->l('Спиди калкулатор'),
            'calculator_fixed' => $this->l('Спиди калкулатор + Надбавка за обработка'),
            'fixed' => $this->l('Фиксирана цена за доставка'),
            'free' => $this->l('Безплатна доставка'),
            'table_rate' => $this->l('Цена от файл'),
        ));

        $this->context->smarty->assign('options_before_payment', array(
            'no_option' => $this->l('Без опция'),
            'test'      => $this->l('Теставай преди да платиш (ТПП)'),
            'open'      => $this->l('Отвори преди да платиш (ОПП)'),
        ));

        $this->context->smarty->assign('return_payers', array(
            0      => $this->l('Подател'),
            1      => $this->l('Получател'),
        ));

        $this->context->smarty->assign('package_dimentions', array(
            ''     => $this->l('Без опция'),
            'XS'   => 'XS',
            'S'    => 'S',
            'M'    => 'M',
            'L'    => 'L',
            'XL'   => 'XL',
        ));

        $this->context->smarty->assign('payer_types', array(
            ParamCalculation::PAYER_TYPE_SENDER     => $this->l('Подател'),
            ParamCalculation::PAYER_TYPE_RECEIVER   => $this->l('Получател'),
        ));

        $this->context->smarty->assign('action', Tools::safeOutput($_SERVER['REQUEST_URI']));

        $this->context->smarty->assign('token', Tools::getValue('token'));

        $this->context->smarty->assign(array(
            'SPEEDY_CARRIER_ID' => Configuration::get('SPEEDY_CARRIER_ID'),
            'this_path' => $this->_path,
            'this_path_ssl' => Tools::getShopDomainSsl(true, true) . __PS_BASE_URI__ . 'modules/' . $this->name . '/'
        ));

        // Check requirments
        $php_version = preg_replace('/^([0-9\.]+).*/', '$1', phpversion());

        $mysql_version = Db::getInstance()->getRow("SELECT VERSION() as mysql_version");
        $mysql_version = preg_replace('/^([0-9\.]+).*/', '$1', $mysql_version['mysql_version']);

        $requirements = array(
            array(
                'name' => $this->l('Минимална версия на PHP'),
                'required' => '5.6',
                'current' => $php_version,
                'is_success' => (version_compare($php_version, '5.6', '>='))
            ),
            array(
                'name' => $this->l('Минимална версия на MySQL'),
                'required' => '5.0.x',
                'current' => $mysql_version,
                'is_success' => (version_compare($mysql_version, '5', '>='))
            ),
            array(
                'name' => $this->l('Пуснато SOAP разширение'),
                'is_success' => class_exists('SOAPClient')
            ),
        );
        $this->context->smarty->assign('requirements', $requirements);

        return $this->display(__FILE__, 'speedy_form.tpl');
    }

    private function validateSettings() {
        $error = false;

        if (!Tools::getValue('speedy_username')) {
            $this->error_arr['error_username'] = $this->l('Моля, въведете потребителско име!');
            $error = true;
        }

        if (!Tools::getValue('speedy_password')) {
            $this->error_arr['error_password'] = $this->l('Моля, въведете парола!');
            $error = true;
        }

        if (!Tools::getValue('speedy_name')) {
            $this->error_arr['error_name'] = $this->l('Моля, въведете фирма!');
            $error = true;
        }

        if (!Tools::getValue('speedy_telephone')) {
            $this->error_arr['error_telephone'] = $this->l('Моля, въведете телефон!');
            $error = true;
        }

        if (!Tools::getValue('speedy_default_weight')) {
            $this->error_arr['error_default_weight'] = $this->l('Моля, въведете тегло по подразбиране за един брой!');
            $error = true;
        } elseif (Tools::getValue('speedy_default_weight') && !is_numeric(Tools::getValue('speedy_default_weight'))) {
            $this->error_arr['error_default_weight'] = $this->l('Невалидна стойност, моля въведете число!');
            $error = true;
        }

        if (!Tools::getIsset('speedy_allowed_methods')) {
            $this->error_arr['error_allowed_methods'] = $this->l('Моля, изберете поне един метод!');
            $error = true;
        }

        if (!Tools::getValue('speedy_client_id')) {
            $this->error_arr['error_speedy_client_id'] = $this->l('Моля, изберете обект!');
            $error = true;
        }

        if (Tools::getValue('speedy_pricing') == 'free' && !Tools::getIsset('speedy_free_method_international')) {
            $this->error_arr['error_free_method_international'] = $this->l('Моля, изберете поне един метод!');
            $error = true;
        }

        if (!Tools::getValue('speedy_packing')) {
            $this->error_arr['error_speedy_packing'] = $this->l('Моля, въведете опаковка!');
            $error = true;
        }

        if (Tools::getValue('speedy_taking_date') && !is_numeric(Tools::getValue('speedy_taking_date'))) {
            $this->error_arr['error_taking_date'] = $this->l('Невалидна стойност, моля въведете число!');
            $error = true;
        }

        if (Tools::fileAttachment('speedy_table_rate_file')) {
            $table_rate_file = Tools::fileAttachment('speedy_table_rate_file', true);
            if (($handle_import = fopen($table_rate_file['tmp_name'], 'r')) !== false) {
                $handle_import_data = fgetcsv($handle_import, 100000); // remove title line
            }

            $file_columns = array(
                'ServiceID',
                'TakeFromOffice',
                'Weight',
                'OrderTotal',
                'PriceWithoutVAT',
                'FixedTimeDelivery',
            );

            sort($handle_import_data);
            sort($file_columns);

            if ($handle_import_data != $file_columns) {
                $this->error_arr['error_warning'] = $this->l('Невалидни колони във файла!');
                $error = true;
            }

            $csv_mimetypes = array(
                'text/csv',
                'text/plain',
                'application/csv',
                'text/comma-separated-values',
                'application/excel',
                'application/vnd.ms-excel',
                'application/vnd.msexcel',
                'text/anytext',
                'application/octet-stream',
                'application/txt',
            );

            if (!in_array($table_rate_file['mime'], $csv_mimetypes)) {
                $this->error_arr['error_warning'] = $this->l('Невалиден формат на файала');
                $error = true;
            }
        }

        if ($this->speedy->getError()) {
            $this->error_arr['error_warning'] = $this->speedy->getError();
            $error = true;
        }

        if (!$error) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    public function hookAdminOrder($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        if (!$this->active || !$carrier_active || !$this->validateCurrency())
            return;

        if (version_compare(@constant('_PS_VERSION_'), '1.7', '>=')) {
            $this->context->smarty->assign('ps_version', '1.7');
        } elseif (version_compare(@constant('_PS_VERSION_'), '1.6', '>=') && version_compare(@constant('_PS_VERSION_'), '1.7', '<')) {
            $this->context->smarty->assign('ps_version', '1.6');
        } else {
            $this->context->smarty->assign('ps_version', '1.5');
        }

        if (method_exists($this->context->controller, "addJqueryPlugin")) {
            $this->context->controller->addJqueryPlugin('fancybox');
        }

        $this->context->smarty->assign('action', Tools::safeOutput($_SERVER['REQUEST_URI']));

        if (($_SERVER['REQUEST_METHOD'] == 'POST') && Tools::getIsset('query_courier')) {
            if (!Tools::getIsset('selected')) {
                $_SESSION['courier_warning'] = $this->l('Няма избрани товарителници!');
            } else {
                $this->speedyCourier(Tools::getValue('selected'));
            }
        }

        if (isset($_SESSION['courier_warning'])) {
            $this->context->smarty->assign('courier_warning', $_SESSION['courier_warning']);
            unset($_SESSION['courier_warning']);
        } else {
            $this->context->smarty->assign('courier_warning', array());
        }

        if (isset($_SESSION['courier_success'])) {
            $this->context->smarty->assign('courier_success', $_SESSION['courier_success']);
            unset($_SESSION['courier_success']);
        } else {
            $this->context->smarty->assign('courier_success', '');
        }

        $this->context->smarty->assign('from_office', Configuration::get('SPEEDY_FROM_OFFICE'));

        $speedy_order_info = $this->_getOrder($params['id_order']);

        $order_list = array();

        $order_results = $this->_getOrders(array('taking_date' => date("Y-m-d", time())));
        if ($order_results) {
            foreach ($order_results as $order_result) {
                $order_data = unserialize($order_result['data']);

                $order_currency = Currency::getCurrencyInstance($order_result['id_currency']);

                $customer = new Customer($order_result['id_customer']);

                $total_price = Tools::convertPriceFull($order_data['shipping_method_cost'], $order_currency, $this->bg_currency);

                $order_list[$order_result['order_id']] = array(
                    'order_id' => $order_result['order_id'],
                    'order_href' => $_SERVER['PHP_SELF'] . '?controller=AdminOrders&id_order=' . $order_result['order_id'] . '&vieworder&token=' . Tools::getAdminTokenLite('AdminOrders'),
                    'bol_id' => $order_result['bol_id'],
                    'customer' => $customer->firstname . ' ' . $customer->lastname,
                    'customer_href' => $_SERVER['PHP_SELF'] . '?controller=AdminCustomers&id_customer=' . $order_result['id_customer'] . '&viewcustomer&token=' . Tools::getAdminTokenLite('AdminCustomers'),
                    'cost' => Tools::displayPrice($total_price, $this->bg_currency->id)
                );
            }
        }

        if (($_SERVER['REQUEST_METHOD'] == 'POST') && Tools::getIsset('bol_id') && Tools::getValue('bol_id') && Tools::getIsset('do_action') && (Tools::getValue('do_action') == 'print_pdf' || Tools::getValue('do_action') == 'print_return_voucher')) {
            $loading_info = $this->_getOrderByBolId(Tools::getValue('bol_id'));
            if ($loading_info) {
                $print = false;
                if (Tools::getValue('do_action') == 'print_pdf') {
                    $print = $this->printPDF($loading_info);
                } elseif (Tools::getValue('do_action') == 'print_return_voucher') {
                    $print = $this->printReturnVoucher($loading_info);
                }

                if ($print) {
                    Tools::redirectAdmin(urldecode($_SERVER['REQUEST_URI']));
                }
            }
        }

        if ($speedy_order_info) {
            $allowed_pricings = array(
                'calculator',
                'free',
                'calculator_fixed'
            );

            $show_invoice_courier_sevice_as_text = false;
            if (Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT') && in_array(Configuration::get('SPEEDY_PRICING'), $allowed_pricings) && (!isset($speedy_order_data['cod']) || !$speedy_order_data['cod'])) {
                if (isset($speedy_order_data['shipping_method_text']) && !empty($speedy_order_data['shipping_method_cost'])) {
                    $show_invoice_courier_sevice_as_text = true;

                    $this->context->smarty->assign('speedy_label', sprintf($this->l('Спиди (%s дължими при доставка)'), $speedy_order_data['shipping_method_text']));
                    $this->context->smarty->assign('speedy_price', Tools::displayPrice(0.00, $this->bg_currency->id));
                }
            }
            $this->context->smarty->assign('show_invoice_courier_sevice_as_text', $show_invoice_courier_sevice_as_text);

            if ($speedy_order_info['bol_id']) {
                $this->getSpeedyLoadingInfo($speedy_order_info);
                $this->getDeliveryInfo($speedy_order_info['bol_id']);
                $this->context->smarty->assign('order_list', $order_list);
                $this->context->smarty->assign('return_voucher_requested', $this->speedy->checkReturnVoucherRequested($speedy_order_info['bol_id']));
                return $this->display(__FILE__, 'speedy_loading.tpl');
            } else {
                $this->getSpeedyGenerateForm($params, $speedy_order_info);

                if (isset($order_list[$params['id_order']])) {
                    unset($order_list[$params['id_order']]);
                }

                $this->context->smarty->assign('order_list', $order_list);
                return $this->display(__FILE__, 'speedy_generate.tpl');
            }
        } else {
            return '';
        }
    }

    private function getSpeedyGenerateForm($params, $speedy_order_info) {
        $speedy_order_data = unserialize($speedy_order_info['data']);

        if (($_SERVER['REQUEST_METHOD'] == 'POST') && !Tools::getIsset('query_courier') && $this->validateSpeedyForm(true, false)) {
            $_POST['taking_date'] = strtotime(Tools::getValue('taking_date'));

            $order = new Order($params['id_order']);
            $order_currency = Currency::getCurrencyInstance($order->id_currency);

            if (Tools::getIsset('shipping_method_id') && isset($_SESSION['shipping_method_cost'][Tools::getValue('shipping_method_id')]) && isset($_SESSION['shipping_method_title'][Tools::getValue('shipping_method_id')])) {
                $_POST['shipping_method_id'] = Tools::getValue('shipping_method_id');
                $_POST['shipping_method_cost'] = $_SESSION['shipping_method_cost'][Tools::getValue('shipping_method_id')];
                $_POST['shipping_method_title'] = $_SESSION['shipping_method_title'][Tools::getValue('shipping_method_id')];

                if (isset($_POST['fixed_time_cb'][Tools::getValue('shipping_method_id')]) && isset($_SESSION['loading_methods_fixed_time_serialize'][Tools::getValue('shipping_method_id')])) {
                    $method = unserialize($_SESSION['loading_methods_fixed_time_serialize'][Tools::getValue('shipping_method_id')]);
                    if ($method->getServiceTypeId() == Tools::getValue('shipping_method_id')) {
                        $_POST['shipping_method_cost'] = $method->getResultInfo()->getAmounts()->getTotal();
                    }
                }

                $_POST['shipping_method_cost'] = Tools::convertPriceFull($_POST['shipping_method_cost'], $this->bg_currency, $order_currency);

                if ($_POST['shipping_method_id'] != 500) {
                    unset($_POST['parcel_size']);
                } else {
                    foreach($_POST['parcels_size'] as $key => $parcel_size) {
                        $_POST['parcels_size'][$key]['depth'] = '';
                        $_POST['parcels_size'][$key]['height'] = '';
                        $_POST['parcels_size'][$key]['width'] = '';
                    }
                }

                if (isset($_POST['fixed_time_cb']) && isset($_SESSION['loading_methods_fixed_time'][Tools::getValue('shipping_method_id')])) {
                    $_POST['fixed_time'] = $_POST['fixed_time_hour'] . $_POST['fixed_time_min'];
                } else {
                    $_POST['fixed_time'] = null;
                }
            }

            if (!Tools::getIsset('shipping_method_id') && isset($speedy_order_data['shipping_method_id']) && is_null($speedy_order_data['fixed_time']) && isset($speedy_order_data['fixed_time_cb'])) {
                $speedy_order_data['fixed_time'] = $speedy_order_data['fixed_time_hour'] . $speedy_order_data['fixed_time_min'];
            }

            $customer = (array) new Customer($order->id_customer);
            $delivery_address = (array) new Address($order->id_address_delivery);

            if (!empty($delivery_address['phone_mobile'])) {
                $telephone = $delivery_address['phone_mobile'];
            } else {
                $telephone = $delivery_address['phone'];
            }

            $order_info = array(
                'firstname' => $delivery_address['firstname'],
                'lastname' => $delivery_address['lastname'],
                'company' => $delivery_address['company'],
                'telephone' => $telephone,
                'email' => $customer['email'],
                'order_id' => $params['id_order']
            );

            if (Tools::getIsset('shipping_method_id') && !isset($_POST['fixed_time_cb']) && isset($_POST['fixed_time_min']) && isset($_POST['fixed_time_hour'])) {
                unset($speedy_order_data['fixed_time_cb']);
            }

            if (!Tools::getIsset('shipping_method_id') && isset($speedy_order_data['shipping_method_id']) && !isset($speedy_order_data['fixed_time_cb']) && isset($speedy_order_data['fixed_time_min']) && isset($speedy_order_data['fixed_time_hour'])) {
                $speedy_order_data['fixed_time'] = null;
            }

            $data = array_merge($speedy_order_data, $_POST);

            $data['shipping_method_cost'] = Tools::convertPriceFull($data['shipping_method_cost'], $order_currency, $this->bg_currency);

            $bol = $this->speedy->createBillOfLading($data, $order_info);

            if (!$this->speedy->getError() && $bol) {
                $this->_editOrder($params['id_order'], array('bol_id' => $bol['bol_id'], 'speedy_additional_copy_for_sender' => $data['speedy_additional_copy_for_sender'], 'taking_date' => date("Y-m-d H:i:s", $data['taking_date'])));

                if ((Configuration::get('SPEEDY_PRICING') == 'free') && ($bol['total'] >= (float) Configuration::get('SPEEDY_FREE_SHIPPING_TOTAL')) &&
                        ($data['shipping_method_id'] == Configuration::get('SPEEDY_FREE_METHOD_CITY') || $data['shipping_method_id'] == Configuration::get('SPEEDY_FREE_METHOD_INTERCITY') || in_array($data['shipping_method_id'], unserialize(Configuration::get('SPEEDY_FREE_METHOD_INTERNATIONAL'))))) {
                    $data['shipping_method_cost'] = 0;
                } elseif (Configuration::get('SPEEDY_PRICING') == 'fixed') {
                    $data['shipping_method_cost'] = Configuration::get('SPEEDY_FIXED_PRICE');
                } elseif (Configuration::get('SPEEDY_PRICING') == 'table_rate') {
                    $filter_data = array(
                        'service_id' => $data['shipping_method_id'],
                        'take_from_office' => $data['to_office'],
                        'weight' => $data['weight'],
                        'order_total' => $data['total'],
                        'fixed_time_delivery' => isset($data['fixed_time_cb']) ? $data['fixed_time_cb'] : 0,
                    );

                    $speedy_table_rate = $this->_getSpeedyTableRate($filter_data);

                    if (!empty($speedy_table_rate)) {
                        $speedy_data['shipping_method_cost'] = $speedy_table_rate['price_without_vat'];
                    }
                } else {
                    $data['shipping_method_cost'] = $bol['total'];

                    if (Configuration::get('SPEEDY_PRICING') == 'calculator_fixed') {
                        $data['shipping_method_cost'] += Configuration::get('SPEEDY_FIXED_PRICE');
                    }
                }

                $data['shipping_method_cost'] = Tools::convertPriceFull((float)$data['shipping_method_cost'], $this->bg_currency, $order_currency);

                $data['shipping_method_text'] = Tools::displayPrice($data['shipping_method_cost'], (int)$order->id_currency);

                $this->_updateOrderInfo($params['id_order'], $data, $data['shipping_method_cost'], $bol['bol_id']);

                $order_state = new OrderState(Configuration::get('SPEEDY_ORDER_STATUS_ID'));

                if (!Validate::isLoadedObject($order_state))
                    $this->context->smarty->assign('error_warning', Tools::displayError($this->l('Невалиден статус на поръчка!')));
                else {
                    $current_order_state = $order->getCurrentOrderState();

                    if ($current_order_state->id != $order_state->id) {
                        $order->current_state = $order_state->id;
                        $order->valid = $order_state->logable;
                        $order->update();

                        $sql = "INSERT INTO `" . _DB_PREFIX_ . "order_history` SET `id_employee` = '" . (int) $this->context->employee->id . "', `id_order` = '" . (int) $order->id . "', `id_order_state` = '" . (int) $order_state->id . "', date_add = NOW() ";

                        $history_insert = Db::getInstance()->Execute($sql);

                        if ($history_insert) {
                            $order_history_id = Db::getInstance()->Insert_ID();
                            $result = Db::getInstance()->getRow('
                                SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name`
                                FROM `' . _DB_PREFIX_ . 'order_history` oh
                                    LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON oh.`id_order` = o.`id_order`
                                    LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON o.`id_customer` = c.`id_customer`
                                    LEFT JOIN `' . _DB_PREFIX_ . 'order_state` os ON oh.`id_order_state` = os.`id_order_state`
                                    LEFT JOIN `' . _DB_PREFIX_ . 'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = o.`id_lang`)
                                WHERE oh.`id_order_history` = ' . (int) $order_history_id . ' AND os.`send_email` = 1');
                            if (isset($result['template']) && Validate::isEmail($result['email'])) {
                                $topic = $result['osname'];
                                $data = array(
                                    '{lastname}' => $result['lastname'],
                                    '{firstname}' => $result['firstname'],
                                    '{id_order}' => (int) $order->id,
                                    '{order_name}' => $order->getUniqReference()
                                );

                                if ($result['module_name']) {
                                    $module = Module::getInstanceByName($result['module_name']);
                                    if (Validate::isLoadedObject($module) && isset($module->extra_mail_vars) && is_array($module->extra_mail_vars))
                                        $data = array_merge($data, $module->extra_mail_vars);
                                }

                                $data['{total_paid}'] = Tools::displayPrice((float) $order->total_paid, new Currency((int) $order->id_currency), false);
                                $data['{order_name}'] = $order->getUniqReference();

                                // An additional email is sent the first time a virtual item is validated
                                $virtual_products = $order->getVirtualProducts();

                                if ($virtual_products && (!$current_order_state || !$current_order_state->logable) && $order_state && $order_state->logable) {
                                    $assign = array();
                                    foreach ($virtual_products as $key => $virtual_product) {
                                        $id_product_download = ProductDownload::getIdFromIdProduct($virtual_product['product_id']);
                                        $product_download = new ProductDownload($id_product_download);
                                        // If this virtual item has an associated file, we'll provide the link to download the file in the email
                                        if ($product_download->display_filename != '') {
                                            $assign[$key]['name'] = $product_download->display_filename;
                                            $dl_link = $product_download->getTextLink(false, $virtual_product['download_hash'])
                                                    . '&id_order=' . $order->id
                                                    . '&secure_key=' . $order->secure_key;
                                            $assign[$key]['link'] = $dl_link;
                                            if ($virtual_product['download_deadline'] != '0000-00-00 00:00:00')
                                                $assign[$key]['deadline'] = Tools::displayDate($virtual_product['download_deadline'], $order->id_lang);
                                            if ($product_download->nb_downloadable != 0)
                                                $assign[$key]['downloadable'] = $product_download->nb_downloadable;
                                        }
                                    }
                                    $this->context->smarty->assign('virtualProducts', $assign);
                                    $this->context->smarty->assign('id_order', $order->id);
                                    $iso = Language::getIsoById((int) ($order->id_lang));
                                    $links = $this->context->smarty->fetch(_PS_MAIL_DIR_ . $iso . '/download-product.tpl');
                                    $tmp_array = array('{nbProducts}' => count($virtual_products), '{virtualProducts}' => $links);
                                    $data = array_merge($data, $tmp_array);
                                    // If there's at least one downloadable file
                                    if (!empty($assign))
                                        Mail::Send((int) $order->id_lang, 'download_product', Mail::l('Virtual product to download', $order->id_lang), $data, $result['email'], $result['firstname'] . ' ' . $result['lastname'], null, null, null, null, _PS_MAIL_DIR_, false, (int) $order->id_shop);
                                }

                                if (Validate::isLoadedObject($order))
                                    Mail::Send((int) $order->id_lang, $result['template'], $topic, $data, $result['email'], $result['firstname'] . ' ' . $result['lastname'], null, null, null, null, _PS_MAIL_DIR_, false, (int) $order->id_shop);
                            }
                        }
                    } else
                        $this->context->smarty->assign('error_warning', Tools::displayError('This order is already assigned this status'));
                }

                Tools::redirectAdmin(urldecode($_SERVER['REQUEST_URI']));
            } else {
                if (stripos($this->speedy->getError(), 'Not valid serviceTypeId') !== false) {
                    $this->error_arr['error_warning'] = $this->l('Моля, изчислете цената за доставка отново и при нужда изберете друг метод за доставка!');
                } else {
                    $this->error_arr['error_warning'] = $this->speedy->getError();
                }
            }
        }

        if (isset($this->error_arr['error_warning'])) {
            $this->context->smarty->assign('error_warning', $this->error_arr['error_warning']);
        } else {
            $this->context->smarty->assign('error_warning', '');
        }

        if (isset($this->error_arr['error_contents'])) {
            $this->context->smarty->assign('error_contents', $this->error_arr['error_contents']);
        } else {
            $this->context->smarty->assign('error_contents', '');
        }

        if (isset($this->error_arr['error_weight'])) {
            $this->context->smarty->assign('error_weight', $this->error_arr['error_weight']);
        } else {
            $this->context->smarty->assign('error_weight', '');
        }

        if (isset($this->error_arr['error_count'])) {
            $this->context->smarty->assign('error_count', $this->error_arr['error_count']);
        } else {
            $this->context->smarty->assign('error_count', '');
        }

        if (isset($this->error_arr['error_address'])) {
            $this->context->smarty->assign('error_address', $this->error_arr['error_address']);
        } else {
            $this->context->smarty->assign('error_address', '');
        }

        if (isset($this->error_arr['error_office'])) {
            $this->context->smarty->assign('error_office', $this->error_arr['error_office']);
        } else {
            $this->context->smarty->assign('error_office', '');
        }

        if (isset($this->error_arr['error_fixed_time'])) {
            $this->context->smarty->assign('error_fixed_time', $this->error_arr['error_fixed_time']);
        } else {
            $this->context->smarty->assign('error_fixed_time', '');
        }

        if (isset($this->error_arr['error_packing'])) {
            $this->context->smarty->assign('error_packing', $this->error_arr['error_packing']);
        } else {
            $this->context->smarty->assign('error_packing', '');
        }

        if (Tools::getIsset('client_id')) {
            $this->context->smarty->assign('speedy_client_id', Tools::getValue('client_id'));
        } elseif (isset($speedy_order_data['client_id'])) {
            $this->context->smarty->assign('speedy_client_id', $speedy_order_data['client_id']);
        } else {
            $this->context->smarty->assign('speedy_client_id', Configuration::get('SPEEDY_CLIENT_ID'));
        }

        if (Tools::getIsset('contents')) {
            $this->context->smarty->assign('contents', Tools::getValue('contents'));
        } elseif (isset($speedy_order_data['contents'])) {
            $this->context->smarty->assign('contents', $speedy_order_data['contents']);
        } else {
            $this->context->smarty->assign('contents', $this->l('Поръчка:') . ' ' . $params['id_order']);
        }

        if (Tools::getIsset('weight')) {
            $this->context->smarty->assign('weight', Tools::getValue('weight'));
        } elseif (isset($speedy_order_data['weight'])) {
            $this->context->smarty->assign('weight', $speedy_order_data['weight']);
        } else {
            $this->context->smarty->assign('weight', '');
        }

        if (Tools::getIsset('packing')) {
            $this->context->smarty->assign('packing', Tools::getValue('packing'));
        } elseif (isset($speedy_order_data['packing'])) {
            $this->context->smarty->assign('packing', $speedy_order_data['packing']);
        } else {
            $this->context->smarty->assign('packing', Configuration::get('SPEEDY_PACKING'));
        }

        $this->context->smarty->assign('clients', $this->speedy->getListContractClients());

        if (Tools::getIsset('payer_type')) {
            $this->context->smarty->assign('payer_type', Tools::getValue('payer_type'));
        } else {
            $payer_type_params = array(
                'cod' => $speedy_order_data['cod'],
                'abroad' => $speedy_order_data['abroad'],
            );
            $this->context->smarty->assign('payer_type', $this->speedy->getPayerType($payer_type_params));
        }

        if (Tools::getIsset('option_before_payment')) {
            $this->context->smarty->assign('option_before_payment', Tools::getValue('option_before_payment'));
        } elseif (isset($speedy_order_data['option_before_payment'])) {
            $this->context->smarty->assign('option_before_payment', $speedy_order_data['option_before_payment']);
        } else {
            $this->context->smarty->assign('option_before_payment', Configuration::get('SPEEDY_OPTION_BEFORE_PAYMENT'));
        }

        $this->context->smarty->assign('options_before_payment', array(
            'no_option' => $this->l('Без опция'),
            'test'      => $this->l('Теставай преди да платиш (ТПП)'),
            'open'      => $this->l('Отвори преди да платиш (ОПП)'),
        ));

        if (Tools::getIsset('count')) {
            $this->context->smarty->assign('count', Tools::getValue('count'));
        } elseif (isset($speedy_order_data['count'])) {
            $this->context->smarty->assign('count', $speedy_order_data['count']);
        } else {
            $this->context->smarty->assign('count', 1);
        }

        if (Tools::getIsset('parcels_size')) {
            $this->context->smarty->assign('parcels_sizes', Tools::getValue('parcels_size'));
        } elseif (isset($speedy_order_data['parcels_size'])) {
            $this->context->smarty->assign('parcels_sizes', $speedy_order_data['parcels_size']);
        } else {
            $parcels_sizes = array();
            
            if (isset($speedy_order_data['width'])) {
                $parcels_sizes[1]['width'] = $speedy_order_data['width'];
            } else {
                $parcels_sizes[1]['width'] = '';
            }
            if (isset($speedy_order_data['height'])) {
                $parcels_sizes[1]['height'] = $speedy_order_data['height'];
            } else {
                $parcels_sizes[1]['height'] = '';
            }
            if (isset($speedy_order_data['depth'])) {
                $parcels_sizes[1]['depth'] = $speedy_order_data['depth'];
            } else {
                $parcels_sizes[1]['depth'] = '';
            }
            if (!isset($parcels_sizes[1]['weight'])) {
                $parcels_sizes[1]['weight'] = '';
            }

            $this->context->smarty->assign('parcels_sizes', $parcels_sizes);
        }

        if (Tools::getIsset('parcel_size')) {
            $this->context->smarty->assign('parcel_size', Tools::getValue('parcel_size'));
        } elseif (isset($speedy_order_data['parcel_size'])) {
            $this->context->smarty->assign('parcel_size', $speedy_order_data['parcel_size']);
        } else {
            $this->context->smarty->assign('parcel_size', $this->parcel_sizes[1]);
        }

        $this->context->smarty->assign('parcel_sizes', $this->parcel_sizes);

        if (Tools::getIsset('shipping_method_id')) {
            $this->context->smarty->assign('shipping_method_id', Tools::getValue('shipping_method_id'));
        } elseif (isset($speedy_order_data['shipping_method_id'])) {
            $this->context->smarty->assign('shipping_method_id', $speedy_order_data['shipping_method_id']);
        } else {
            $this->context->smarty->assign('shipping_method_id', '');
        }

        if (Tools::getIsset('deffered_days')) {
            $this->context->smarty->assign('deffered_days', Tools::getValue('deffered_days'));
        } elseif (isset($speedy_order_data['deffered_days'])) {
            $this->context->smarty->assign('deffered_days', $speedy_order_data['deffered_days']);
        } else {
            $this->context->smarty->assign('deffered_days', 0);
        }

        if (Tools::getIsset('client_note')) {
            $this->context->smarty->assign('client_note', Tools::getValue('client_note'));
        } elseif (isset($speedy_order_data['client_note'])) {
            $this->context->smarty->assign('client_note', $speedy_order_data['client_note']);
        } else {
            $this->context->smarty->assign('client_note', '');
        }

        $module_speedypayment = Module::getInstanceByName('speedypayment');
        if (Validate::isLoadedObject($module_speedypayment) && $module_speedypayment->active) {
            $speedypayment = true;
        } else {
            $speedypayment = false;
        }

        if (!$speedypayment) {
            $this->context->smarty->assign('cod', false);
        } elseif (Tools::getIsset('cod')) {
            $this->context->smarty->assign('cod', Tools::getValue('cod'));
        } elseif (isset($speedy_order_data['cod'])) {
            $this->context->smarty->assign('cod', $speedy_order_data['cod']);
        } else {
            $this->context->smarty->assign('cod', true);
        }

        if (Tools::getIsset('total')) {
            $this->context->smarty->assign('total', Tools::getValue('total'));
        } elseif (isset($speedy_order_data['total'])) {
            $this->context->smarty->assign('total', $speedy_order_data['total']);
        } else {
            $this->context->smarty->assign('total', '');
        }

        if (Tools::getIsset('convertion_to_win1251')) {
            $this->context->smarty->assign('convertion_to_win1251', Tools::getValue('convertion_to_win1251'));
        } elseif (isset($speedy_order_data['convertion_to_win1251'])) {
            $this->context->smarty->assign('convertion_to_win1251', $speedy_order_data['convertion_to_win1251']);
        } else {
            $this->context->smarty->assign('convertion_to_win1251', '');
        }

        if (Tools::getIsset('speedy_additional_copy_for_sender')) {
            $this->context->smarty->assign('speedy_additional_copy_for_sender', Tools::getValue('speedy_additional_copy_for_sender'));
        } elseif (isset($speedy_order_data['speedy_additional_copy_for_sender'])) {
            $this->context->smarty->assign('speedy_additional_copy_for_sender', $speedy_order_data['speedy_additional_copy_for_sender']);
        } else {
            $this->context->smarty->assign('speedy_additional_copy_for_sender', Configuration::get('SPEEDY_ADDITIONAL_COPY_FOR_SENDER'));
        }

        if (Tools::getIsset('insurance')) {
            $this->context->smarty->assign('insurance', Tools::getValue('insurance'));
        } elseif (isset($speedy_order_data['insurance'])) {
            $this->context->smarty->assign('insurance', $speedy_order_data['insurance']);
        } else {
            $this->context->smarty->assign('insurance', Configuration::get('SPEEDY_INSURANCE'));
        }

        if (Tools::getIsset('fragile')) {
            $this->context->smarty->assign('fragile', Tools::getValue('fragile'));
        } elseif (isset($speedy_order_data['fragile'])) {
            $this->context->smarty->assign('fragile', $speedy_order_data['fragile']);
        } else {
            $this->context->smarty->assign('fragile', Configuration::get('SPEEDY_FRAGILE'));
        }

        if (Tools::getIsset('totalNoShipping')) {
            $this->context->smarty->assign('totalNoShipping', Tools::getValue('totalNoShipping'));
        } elseif (isset($speedy_order_data['totalNoShipping'])) {
            $this->context->smarty->assign('totalNoShipping', $speedy_order_data['totalNoShipping']);
        } else {
            $this->context->smarty->assign('totalNoShipping', '');
        }

        if (Tools::getIsset('abroad')) {
            $abroad = Tools::getValue('abroad');
        } elseif (isset($speedy_order_data['abroad'])) {
            $abroad = $speedy_order_data['abroad'];
        } else {
            $abroad = 0;
        }

        $this->context->smarty->assign('abroad', $abroad);

        if (Tools::getIsset('to_office')) {
            $this->context->smarty->assign('to_office', Tools::getValue('to_office'));
        } elseif (isset($speedy_order_data['to_office'])) {
            $this->context->smarty->assign('to_office', $speedy_order_data['to_office']);
        } else {
            $this->context->smarty->assign('to_office', 0);
        }

        if (Tools::getIsset('is_apt')) {
            $this->context->smarty->assign('is_apt', Tools::getValue('is_apt'));
        } elseif (isset($speedy_order_data['is_apt'])) {
            $this->context->smarty->assign('is_apt', $speedy_order_data['is_apt']);
        } else {
            $this->context->smarty->assign('is_apt', '');
        }

        if (Tools::getIsset('postcode')) {
            $this->context->smarty->assign('postcode', Tools::getValue('postcode'));
        } elseif (isset($speedy_order_data['postcode'])) {
            $this->context->smarty->assign('postcode', $speedy_order_data['postcode']);
        } else {
            $this->context->smarty->assign('postcode', '');
        }

        if (Tools::getIsset('city')) {
            $this->context->smarty->assign('city', Tools::getValue('city'));
        } elseif (isset($speedy_order_data['city'])) {
            $this->context->smarty->assign('city', $speedy_order_data['city']);
        } else {
            $this->context->smarty->assign('city', '');
        }

        if (Tools::getIsset('country_id')) {
            $country_id = Tools::getValue('country_id');
        } elseif (isset($speedy_order_data['country_id'])) {
            $country_id = $speedy_order_data['country_id'];
        } else {
            $country_id = 0;
        }

        $this->context->smarty->assign('country_id', $country_id);

        if (Tools::getIsset('city_id')) {
            $city_id = Tools::getValue('city_id');
        } elseif (isset($speedy_order_data['city_id'])) {
            $city_id = $speedy_order_data['city_id'];
        } else {
            $city_id = 0;
        }

        $this->context->smarty->assign('city_id', $city_id);

        if (Tools::getIsset('city_nomenclature')) {
            $this->context->smarty->assign('city_nomenclature', Tools::getValue('city_nomenclature'));
        } elseif (isset($speedy_order_data['city_nomenclature'])) {
            $this->context->smarty->assign('city_nomenclature', $speedy_order_data['city_nomenclature']);
        } else {
            $this->context->smarty->assign('city_nomenclature', '');
        }

        if (Tools::getIsset('quarter')) {
            $this->context->smarty->assign('quarter', Tools::getValue('quarter'));
        } elseif (isset($speedy_order_data['quarter'])) {
            $this->context->smarty->assign('quarter', $speedy_order_data['quarter']);
        } else {
            $this->context->smarty->assign('quarter', '');
        }

        if (Tools::getIsset('quarter_id')) {
            $this->context->smarty->assign('quarter_id', Tools::getValue('quarter_id'));
        } elseif (isset($speedy_order_data['quarter_id'])) {
            $this->context->smarty->assign('quarter_id', $speedy_order_data['quarter_id']);
        } else {
            $this->context->smarty->assign('quarter_id', 0);
        }

        if (Tools::getIsset('street')) {
            $this->context->smarty->assign('street', Tools::getValue('street'));
        } elseif (isset($speedy_order_data['street'])) {
            $this->context->smarty->assign('street', $speedy_order_data['street']);
        } else {
            $this->context->smarty->assign('street', '');
        }

        if (Tools::getIsset('street_id')) {
            $this->context->smarty->assign('street_id', Tools::getValue('street_id'));
        } elseif (isset($speedy_order_data['street_id'])) {
            $this->context->smarty->assign('street_id', $speedy_order_data['street_id']);
        } else {
            $this->context->smarty->assign('street_id', 0);
        }

        if (Tools::getIsset('street_no')) {
            $this->context->smarty->assign('street_no', Tools::getValue('street_no'));
        } elseif (isset($speedy_order_data['street_no'])) {
            $this->context->smarty->assign('street_no', $speedy_order_data['street_no']);
        } else {
            $this->context->smarty->assign('street_no', '');
        }

        if (Tools::getIsset('object')) {
            $this->context->smarty->assign('object', Tools::getValue('object'));
        } elseif (isset($speedy_order_data['object'])) {
            $this->context->smarty->assign('object', $speedy_order_data['object']);
        } else {
            $this->context->smarty->assign('object', '');
        }

        if (Tools::getIsset('object_id')) {
            $this->context->smarty->assign('object_id', Tools::getValue('object_id'));
        } elseif (isset($speedy_order_data['object_id'])) {
            $this->context->smarty->assign('object_id', $speedy_order_data['object_id']);
        } else {
            $this->context->smarty->assign('object_id', 0);
        }

        if (Tools::getIsset('block_no')) {
            $this->context->smarty->assign('block_no', Tools::getValue('block_no'));
        } elseif (isset($speedy_order_data['block_no'])) {
            $this->context->smarty->assign('block_no', $speedy_order_data['block_no']);
        } else {
            $this->context->smarty->assign('block_no', '');
        }

        if (Tools::getIsset('entrance_no')) {
            $this->context->smarty->assign('entrance_no', Tools::getValue('entrance_no'));
        } elseif (isset($speedy_order_data['entrance_no'])) {
            $this->context->smarty->assign('entrance_no', $speedy_order_data['entrance_no']);
        } else {
            $this->context->smarty->assign('entrance_no', '');
        }

        if (Tools::getIsset('floor_no')) {
            $this->context->smarty->assign('floor_no', Tools::getValue('floor_no'));
        } elseif (isset($speedy_order_data['floor_no'])) {
            $this->context->smarty->assign('floor_no', $speedy_order_data['floor_no']);
        } else {
            $this->context->smarty->assign('floor_no', '');
        }

        if (Tools::getIsset('apartment_no')) {
            $this->context->smarty->assign('apartment_no', Tools::getValue('apartment_no'));
        } elseif (isset($speedy_order_data['apartment_no'])) {
            $this->context->smarty->assign('apartment_no', $speedy_order_data['apartment_no']);
        } else {
            $this->context->smarty->assign('apartment_no', '');
        }

        if (Tools::getIsset('office_id')) {
            $this->context->smarty->assign('office_id', Tools::getValue('office_id'));
        } elseif (isset($speedy_order_data['office_id'])) {
            $this->context->smarty->assign('office_id', $speedy_order_data['office_id']);
        } else {
            $this->context->smarty->assign('office_id', 0);
        }

        if (Tools::getIsset('note')) {
            $this->context->smarty->assign('note', Tools::getValue('note'));
        } elseif (isset($speedy_order_data['note'])) {
            $this->context->smarty->assign('note', $speedy_order_data['note']);
        } else {
            $this->context->smarty->assign('note', '');
        }

        if (Tools::getIsset('country')) {
            $this->context->smarty->assign('country', Tools::getValue('country'));
        } elseif (isset($speedy_order_data['country'])) {
            $this->context->smarty->assign('country', $speedy_order_data['country']);
        } else {
            $this->context->smarty->assign('country', '');
        }

        if (Tools::getIsset('country_id')) {
            $country_id = Tools::getValue('country_id');
        } elseif (isset($speedy_order_data['country_id'])) {
            $country_id = $speedy_order_data['country_id'];
        } else {
            $country_id = '';
        }

        $this->context->smarty->assign('country_id', $country_id);

        if (in_array($country_id, $this->countries_allowed)) {
            $this->context->smarty->assign('allowed_country', 1);
        } else {
            $this->context->smarty->assign('allowed_country', 0);
        }

        if (Tools::getIsset('country_nomenclature')) {
            $this->context->smarty->assign('country_nomenclature', Tools::getValue('country_nomenclature'));
        } elseif (isset($speedy_order_data['country_nomenclature'])) {
            $this->context->smarty->assign('country_nomenclature', $speedy_order_data['country_nomenclature']);
        } else {
            $this->context->smarty->assign('country_nomenclature', '');
        }

        if (Tools::getIsset('country_address_nomenclature')) {
            $this->context->smarty->assign('country_address_nomenclature', Tools::getValue('country_address_nomenclature'));
        } elseif (isset($speedy_order_data['country_address_nomenclature'])) {
            $this->context->smarty->assign('country_address_nomenclature', $speedy_order_data['country_address_nomenclature']);
        } else {
            $this->context->smarty->assign('country_address_nomenclature', '');
        }

        if (Tools::getIsset('required_state')) {
            $this->context->smarty->assign('required_state', Tools::getValue('required_state'));
        } elseif (isset($speedy_order_data['required_state'])) {
            $this->context->smarty->assign('required_state', $speedy_order_data['required_state']);
        } else {
            $this->context->smarty->assign('required_state', '');
        }

        if (Tools::getIsset('required_postcode')) {
            $this->context->smarty->assign('required_postcode', Tools::getValue('required_postcode'));
        } elseif (isset($speedy_order_data['required_postcode'])) {
            $this->context->smarty->assign('required_postcode', $speedy_order_data['required_postcode']);
        } else {
            $this->context->smarty->assign('required_postcode', '');
        }

        if (Tools::getIsset('active_currency_code')) {
            $this->context->smarty->assign('active_currency_code', Tools::getValue('active_currency_code'));
        } elseif (isset($speedy_order_data['active_currency_code'])) {
            $this->context->smarty->assign('active_currency_code', $speedy_order_data['active_currency_code']);
        } else {
            $this->context->smarty->assign('active_currency_code', '');
        }

        if (Tools::getIsset('state')) {
            $this->context->smarty->assign('state', Tools::getValue('state'));
        } elseif (isset($speedy_order_data['state'])) {
            $this->context->smarty->assign('state', $speedy_order_data['state']);
        } else {
            $this->context->smarty->assign('state', '');
        }

        if (Tools::getIsset('state_id')) {
            $this->context->smarty->assign('state_id', Tools::getValue('state_id'));
        } elseif (isset($speedy_order_data['state_id'])) {
            $this->context->smarty->assign('state_id', $speedy_order_data['state_id']);
        } else {
            $this->context->smarty->assign('state_id', '');
        }

        if (Tools::getIsset('address_1')) {
            $this->context->smarty->assign('address_1', Tools::getValue('address_1'));
        } elseif (isset($speedy_order_data['address_1'])) {
            $this->context->smarty->assign('address_1', $speedy_order_data['address_1']);
        } else {
            $this->context->smarty->assign('address_1', '');
        }

        if (Tools::getIsset('address_2')) {
            $this->context->smarty->assign('address_2', Tools::getValue('address_2'));
        } elseif (isset($speedy_order_data['address_2'])) {
            $this->context->smarty->assign('address_2', $speedy_order_data['address_2']);
        } else {
            $this->context->smarty->assign('address_2', '');
        }

        if (Tools::getIsset('fixed_time_cb')) {
            $this->context->smarty->assign('fixed_time_cb', Tools::getValue('fixed_time_cb'));
        } elseif (isset($speedy_order_data['fixed_time_cb']) && ($_SERVER['REQUEST_METHOD'] != 'POST')) {
            $this->context->smarty->assign('fixed_time_cb', $speedy_order_data['fixed_time_cb']);
        } else {
            $this->context->smarty->assign('fixed_time_cb', false);
        }

        if (Tools::getIsset('fixed_time_hour')) {
            $this->context->smarty->assign('fixed_time_hour', Tools::getValue('fixed_time_hour'));
        } elseif (isset($speedy_order_data['fixed_time_hour'])) {
            $this->context->smarty->assign('fixed_time_hour', $speedy_order_data['fixed_time_hour']);
        } else {
            $this->context->smarty->assign('fixed_time_hour', '');
        }

        if (Tools::getIsset('fixed_time_min')) {
            $this->context->smarty->assign('fixed_time_min', Tools::getValue('fixed_time_min'));
        } elseif (isset($speedy_order_data['fixed_time_min'])) {
            $this->context->smarty->assign('fixed_time_min', $speedy_order_data['fixed_time_min']);
        } else {
            $this->context->smarty->assign('fixed_time_min', '');
        }

        $this->context->smarty->assign('order_id', $params['id_order']);

        $this->context->smarty->assign('fixed_time', Configuration::get('SPEEDY_FIXED_TIME'));

        $this->context->smarty->assign('offices', array());

        $lang = $abroad ? 'en' : $this->context->language->iso_code;

        if (!$city_id) {
            $cities = $this->speedy->getCities($speedy_order_data['city'], $speedy_order_data['postcode'], null, $lang);

            if (!$this->speedy->getError()) {
                if (count($cities) == 1) {
                    $this->context->smarty->assign('postcode', $cities[0]['postcode']);
                    $this->context->smarty->assign('city', $cities[0]['value']);
                    $this->context->smarty->assign('city_id', $cities[0]['id']);
                    $city_id = $cities[0]['id'];
                    $this->context->smarty->assign('city_nomenclature', $cities[0]['nomenclature']);
                }
            } else {
                $this->context->smarty->assign('error_address', $this->speedy->getError());
            }
        }

        if ($city_id && $country_id) {
            $this->context->smarty->assign('offices', $this->speedy->getOffices(null, $city_id, $lang, $country_id));

            if ($this->speedy->getError()) {
                $this->context->smarty->assign('error_office', $this->speedy->getError());
            }
        }

        $cod_status = $speedypayment;

        if ($abroad) {
            if (isset($speedy_order_data['cod_status'])) {
                $cod_status = $speedy_order_data['cod_status'];
            }
        }

        $this->context->smarty->assign('cod_status', $cod_status);

        $this->context->smarty->assign('days', array(0, 1, 2));
        $this->context->smarty->assign('taking_date', date('d-m-Y', (Configuration::get('SPEEDY_TAKING_DATE') ? strtotime('+' . (int) Configuration::get('SPEEDY_TAKING_DATE') . ' day', mktime(9, 0, 0)) : time())));

        $this->context->smarty->assign(array(
            'SPEEDY_CARRIER_ID' => Configuration::get('SPEEDY_CARRIER_ID'),
            'this_path' => $this->_path,
            'speedy_token' => Tools::getAdminTokenLite('AdminModules'),
            'this_path_ssl' => Tools::getShopDomainSsl(true, true) . __PS_BASE_URI__ . 'modules/' . $this->name . '/'
        ));
    }

    private function getSpeedyLoadingInfo($loading_info) {
        if (($_SERVER['REQUEST_METHOD'] == 'POST') && Tools::getIsset('bol_id') && Tools::getValue('bol_id') && Tools::getIsset('do_action')) {
            if (Tools::getValue('do_action') == 'cancel_loading') {
                if ($this->cancelLoading($loading_info)) {
                    Tools::redirectAdmin(urldecode($_SERVER['REQUEST_URI']));
                }
            }
        }

        if (isset($_SESSION['success'])) {
            $this->context->smarty->assign('success', $_SESSION['success']);
            unset($_SESSION['success']);
        } else {
            $this->context->smarty->assign('success', '');
        }

        if (isset($_SESSION['warning'])) {
            $this->context->smarty->assign('warning', $_SESSION['warning']);
            unset($_SESSION['warning']);
        } else {
            $this->context->smarty->assign('warning', '');
        }

        $loading = array(
            'loading_num' => $loading_info['bol_id'],
            'track_loading' => 'http://www.speedy.bg/begin.php?shipmentNumber=' . $loading_info['bol_id'] . '&lang=' . (strtolower(Context::getContext()->language->iso_code) == 'bg' ? 'bg' : 'en'),
        );

        $this->context->smarty->assign('loading', $loading);

        $this->context->smarty->assign(array(
            'SPEEDY_CARRIER_ID' => Configuration::get('SPEEDY_CARRIER_ID'),
            'this_path' => $this->_path,
            'this_path_ssl' => Tools::getShopDomainSsl(true, true) . __PS_BASE_URI__ . 'modules/' . $this->name . '/'
        ));
    }

    private function getDeliveryInfo($bol_id)
    {
        $deliveryInfo = $this->speedy->getDeliveryInfo($bol_id);
        $deliveryDate = '';
        $deliveryConsignee = '';
        $deliveryNote = '';
        if (isset($deliveryInfo)) {
            if (!empty($deliveryInfo->getDeliveryDate())) {
                $deliveryDate = date($this->context->language->date_format_full, strtotime($deliveryInfo->getDeliveryDate()));
            }

            if (!empty($deliveryInfo->getConsignee())) {
                $deliveryConsignee = $deliveryInfo->getConsignee();
            }

            if (!empty($deliveryInfo->getDeliveryNote())) {
                $deliveryNote = $deliveryInfo->getDeliveryNote();
            }

            $this->context->smarty->assign('showDeliveryInfoText', 1);
        }
        $this->context->smarty->assign('deliveryDate', $deliveryDate);
        $this->context->smarty->assign('deliveryConsignee', $deliveryConsignee);
        $this->context->smarty->assign('deliveryNote', $deliveryNote);
    }

    private function speedyCalculate() {
        if (($_SERVER['REQUEST_METHOD'] == 'POST') && $this->validateSpeedyForm(true)) {
            $results_speedy = $this->_getQuoteAdmin();
            $results['methods'] = $results_speedy['quote'];

            if (isset($results_speedy['shipping_method_id'])) {
                $results['shipping_method_id'] = $results_speedy['shipping_method_id'];
            } else {
                $results['shipping_method_id'] = 0;
            }
        } else {
            $results['methods'] = array();
            $results['shipping_method_id'] = 0;
        }

        echo json_encode($results);
        exit;
    }

    private function getAllowedMethods() {
        $json = array();

        require_once(dirname(__FILE__) . '/speedy-eps-lib.php');
        $this->speedy = new SpeedyEpsLib();

        $services = $this->speedy->getServices($this->context->language->iso_code);

        if ($services) {
            foreach ($services as $service_id => $service) {
                $json['services'][] = array(
                    'service_id' => $service_id,
                    'name' => $service
                );
            }
        } else {
            $json['error'] = $this->l('Грешка при взимането на позволените методи!');
        }

        echo json_encode($json);
        exit;
    }

    private function getOffices() {
        $json = array();

        require_once(dirname(__FILE__) . '/speedy-eps-lib.php');
        $this->speedy = new SpeedyEpsLib();

        $offices = $this->speedy->getOffices(null, null, $this->context->language->iso_code);

        if ($offices) {
            $json['offices'] = $offices;
        } else {
            $json['error'] = $this->l('Грешка при взимането на офисите!');
        }

        echo json_encode($json);
        exit;
    }

    public function hookHeader($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        if (!$this->active || !$carrier_active || !$this->validateCurrency())
            return;

        if (method_exists($this->context->controller, "addCSS")) {
            $this->context->controller->addCSS(($this->_path).'speedy.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.theme.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.autocomplete.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.core.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.menu.css', 'all');
        }

        if (method_exists($this->context->controller, "addJS")) {
            $this->context->controller->addJquery();
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.core.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.widget.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.position.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.autocomplete.min.js');
            $this->context->controller->addJS(($this->_path).'js/proceedWithPayment.js');

            if (version_compare(@constant('_PS_VERSION_'), '1.6', '>=') && version_compare(@constant('_PS_VERSION_'), '1.7', '<')) {
                $this->context->controller->addJS(($this->_path).'js/jquery.ui.menu.min.js');
            }
        }

        if (Tools::getIsset('id_order') && Tools::getIsset('id_cart') && isset($_SESSION['speedy']) && !empty($_SESSION['speedy']['shipping_method_id']) && isset($_SESSION['speedy']['shipping_method_cost'])) {
            $orders = $this->getOrdersByCartId(Tools::getValue('id_cart'));
            if (isset($orders[Configuration::get('SPEEDY_CARRIER_ID')])) {
                $this->_addOrder(Tools::getValue('id_order'), $_SESSION['speedy']);
                unset($_SESSION['speedy']);
            }
        }
    }

    public function validateSpeedyForm($admin_validation = false, $ajax = true) {
        if (!Tools::getValue('validate')) {
            return true;
        }

        if ($admin_validation) {
            if ((mb_strlen(Tools::getValue('contents'), "UTF-8") < 1) || (mb_strlen(Tools::getValue('contents'), "UTF-8") > 100)) {
                $this->error_arr['error_contents'] = true;
            }

            if (Tools::getValue('weight') <= 0) {
                $this->error_arr['error_weight'] = true;
            }

            if (Tools::getValue('count') <= 0) {
                $this->error_arr['error_count'] = true;
            }

            if (!Tools::getValue('packing')) {
                $this->error_arr['error_packing'] = true;
            }
        }

        if (!Tools::getIsset('abroad') || !Tools::getValue('abroad') || in_array(Tools::getValue('country_id'), $this->countries_allowed)) {
            if (Tools::getValue('city') && Tools::getValue('city_id') &&
                    (!Tools::getValue('to_office') && ((Tools::getValue('quarter') && (Tools::getValue('quarter_id') && Tools::getValue('city_nomenclature') == 'FULL' || Tools::getValue('city_nomenclature') != 'FULL') && (Tools::getValue('block_no') || Tools::getValue('street_no'))) ||
                    (Tools::getValue('street') && (Tools::getValue('street_id') && Tools::getValue('city_nomenclature') == 'FULL' || Tools::getValue('city_nomenclature') != 'FULL') && (Tools::getValue('block_no') || Tools::getValue('street_no'))) || Tools::getValue('note') || Tools::getValue('object_id')) || (Tools::getValue('to_office') && Tools::getValue('office_id')))) {
            } else {
                if (Tools::getValue('to_office')) {
                    $this->error_arr['error_office'] = $this->l('Моля, въведете населено място и изберете офис!');
                } else {
                    $this->error_arr['error_address'] = true;
                }
            }
        } else {
            $validAddress = $this->speedy->validateAddress($_POST);
            if ($validAddress !== true) {
                $this->error_arr['error']['warning'] = $validAddress;
            }
        }

        if (Tools::getIsset('cod') && Tools::getValue('cod') && Tools::getIsset('active_currency_code')) {
            if (!Currency::getIdByIsoCode(Tools::getValue('active_currency_code'))) {
                $active_currency_code_error = sprintf($this->l('Не може да използвате Наложен платеж, валутата %s лиспва. Моля обърнете се към администраторите на магазина!'), Tools::getValue('active_currency_code'));
                if (!$admin_validation) {
                    $this->error_arr['error']['warning'] = $active_currency_code_error;
                } else {
                    $this->error_arr['error_warning'] = $active_currency_code_error;
                }
            }
        }

        if (!$admin_validation) {
            if (!Tools::getIsset('cod')) {
                $this->error_arr['error_cod'] = true;
            }
        }

        if (!$this->error_arr) {
            return TRUE;
        } else {
            if ($ajax) {
                echo json_encode($this->error_arr);
                exit;
            } else {
                if (!$this->error_arr) {
                    return TRUE;
                } else {
                    return FALSE;
                }
            }
        }
    }

    public function hookBackBeforePayment($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        if (!$this->active || !$carrier_active)
            return;

        if (Tools::getIsset('delivery_option')) {
            foreach (Tools::getValue('delivery_option') as $delivery_option) {
                if ((int) $delivery_option == Configuration::get('SPEEDY_CARRIER_ID') && !isset($_SESSION['speedy']['shipping_method_cost'])) {
                    $_SESSION['error_speedy_calculate'] = Tools::displayError($this->l('Моля изберете услуга!'));
                    Tools::redirect('index.php?controller=order&step=2');
                }
            }
        }
    }

    public function hookdisplayCarrierExtraContent($params) {
        return $this->hookExtraCarrier($params);
    }

    public function hookExtraCarrier($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        if (!$this->active || !$carrier_active)
            return;

        if (version_compare(@constant('_PS_VERSION_'), '1.7', '>=')) {
            $this->context->smarty->assign('ps_version', '1.7');
        } elseif (version_compare(@constant('_PS_VERSION_'), '1.6', '>=') && version_compare(@constant('_PS_VERSION_'), '1.7', '<')) {
            $this->context->smarty->assign('ps_version', '1.6');
        } else {
            $this->context->smarty->assign('ps_version', '1.5');
        }

        if ($this->validateCurrency()) {
            $speedy_error = 0;

            if (Context::getContext()->customer->logged && !Context::getContext()->customer->is_guest && !empty(Context::getContext()->cart->id_address_delivery)) {
                $shipping_address = $this->_getAddress(Context::getContext()->cart->id_address_delivery);
                $this->context->smarty->assign('speedy_precalculate', false);
            } elseif (isset($_SESSION['speedy'])) {
                $shipping_address = $_SESSION['speedy'];
                $this->context->smarty->assign('speedy_precalculate', false);
            } else {
                $shipping_address = array();
                $this->context->smarty->assign('speedy_precalculate', true);
            }

            $store_shipping_address = (array) new Address(Context::getContext()->cart->id_address_delivery);

            // Check delivery country
            $delivery_address = new Address(Context::getContext()->cart->id_address_delivery);
            $delivery_country = new Country($delivery_address->id_country);
            if ($delivery_country->iso_code == 'BG') {
                $abroad = 0;
            } else {
                $abroad = 1;
            }

            $this->context->smarty->assign('abroad', $abroad);

            $results_speedy = $this->_getQuotePublic();

            if (!empty($results_speedy)) {
                $this->context->smarty->assign('speedy_methods', $results_speedy['quote']);
            } else {
                $this->context->smarty->assign('speedy_methods', array());
            }

            if (!empty($_SESSION['speedy']['shipping_method_id'])) {
                $this->context->smarty->assign('shipping_method_id', $_SESSION['speedy']['shipping_method_id']);
            } else {
                $this->context->smarty->assign('shipping_method_id', '');
            }

            if (isset($this->error_arr['error_address'])) {
                $this->context->smarty->assign('error_address', $this->error_arr['error_address']);
            } else {
                $this->context->smarty->assign('error_address', '');
            }

            if (isset($this->error_arr['office'])) {
                $this->context->smarty->assign('error_office', $this->error_arr['office']);
            } else {
                $this->context->smarty->assign('error_office', '');
            }

            if (isset($this->error_arr['fixed_time'])) {
                $this->context->smarty->assign('error_fixed_time', $this->error_arr['fixed_time']);
            } else {
                $this->context->smarty->assign('error_fixed_time', '');
            }

            if (isset($this->error_arr['cod'])) {
                $this->context->smarty->assign('error_cod', $this->error_arr['cod']);
            } else {
                $this->context->smarty->assign('error_cod', '');
            }

            $module_speedypayment = Module::getInstanceByName('speedypayment');
            if (Validate::isLoadedObject($module_speedypayment) && $module_speedypayment->active) {
                $speedypayment = true;
            } else {
                $speedypayment = false;
            }

            if (!$speedypayment) {
                $this->context->smarty->assign('cod', false);
            } elseif (Tools::getIsset('cod')) {
                $this->context->smarty->assign('cod', Tools::getValue('cod'));
            } elseif (isset($_SESSION['speedy']['cod'])) {
                $this->context->smarty->assign('cod', $_SESSION['speedy']['cod']);
            } else {
                $this->context->smarty->assign('cod', null);
            }

            if (Tools::getIsset('to_office')) {
                $this->context->smarty->assign('to_office', Tools::getValue('to_office'));
            } elseif (isset($shipping_address['to_office'])) {
                $this->context->smarty->assign('to_office', $shipping_address['to_office']);
            }

            if (Tools::getIsset('postcode')) {
                $this->context->smarty->assign('postcode', Tools::getValue('postcode'));
            } elseif (isset($shipping_address['postcode'])) {
                $this->context->smarty->assign('postcode', $shipping_address['postcode']);
            } else {
                $this->context->smarty->assign('postcode', '');
            }

            if (Tools::getIsset('city')) {
                $this->context->smarty->assign('city', Tools::getValue('city'));
            } elseif (isset($shipping_address['city'])) {
                $this->context->smarty->assign('city', $shipping_address['city']);
            } else {
                $this->context->smarty->assign('city', '');
            }

            if (Tools::getIsset('city_id')) {
                $city_id = Tools::getValue('city_id');
            } elseif (isset($shipping_address['city_id'])) {
                $city_id = $shipping_address['city_id'];
            } else {
                $city_id = 0;
            }

            $this->context->smarty->assign('city_id', $city_id);

            if (Tools::getIsset('city_nomenclature')) {
                $this->context->smarty->assign('city_nomenclature', Tools::getValue('city_nomenclature'));
            } elseif (isset($shipping_address['city_nomenclature'])) {
                $this->context->smarty->assign('city_nomenclature', $shipping_address['city_nomenclature']);
            } else {
                $this->context->smarty->assign('city_nomenclature', '');
            }

            if (Tools::getIsset('quarter')) {
                $this->context->smarty->assign('quarter', Tools::getValue('quarter'));
            } elseif (isset($shipping_address['quarter'])) {
                $this->context->smarty->assign('quarter', $shipping_address['quarter']);
            } else {
                $this->context->smarty->assign('quarter', '');
            }

            if (Tools::getIsset('quarter_id')) {
                $this->context->smarty->assign('quarter_id', Tools::getValue('quarter_id'));
            } elseif (isset($shipping_address['quarter_id'])) {
                $this->context->smarty->assign('quarter_id', $shipping_address['quarter_id']);
            } else {
                $this->context->smarty->assign('quarter_id', 0);
            }

            if (Tools::getIsset('object')) {
                $this->context->smarty->assign('object', Tools::getValue('object'));
            } elseif (isset($shipping_address['object'])) {
                $this->context->smarty->assign('object', $shipping_address['object']);
            } else {
                $this->context->smarty->assign('object', '');
            }

            if (Tools::getIsset('object_id')) {
                $this->context->smarty->assign('object_id', Tools::getValue('object_id'));
            } elseif (isset($shipping_address['object_id'])) {
                $this->context->smarty->assign('object_id', $shipping_address['object_id']);
            } else {
                $this->context->smarty->assign('object_id', 0);
            }

            if (Tools::getIsset('street')) {
                $this->context->smarty->assign('street', Tools::getValue('street'));
            } elseif (isset($shipping_address['street'])) {
                $this->context->smarty->assign('street', $shipping_address['street']);
            } else {
                $this->context->smarty->assign('street', '');
            }

            if (Tools::getIsset('street_id')) {
                $this->context->smarty->assign('street_id', Tools::getValue('street_id'));
            } elseif (isset($shipping_address['street_id'])) {
                $this->context->smarty->assign('street_id', $shipping_address['street_id']);
            } else {
                $this->context->smarty->assign('street_id', 0);
            }

            if (Tools::getIsset('street_no')) {
                $this->context->smarty->assign('street_no', Tools::getValue('street_no'));
            } elseif (isset($shipping_address['street_no'])) {
                $this->context->smarty->assign('street_no', $shipping_address['street_no']);
            } else {
                $this->context->smarty->assign('street_no', '');
            }

            if (Tools::getIsset('block_no')) {
                $this->context->smarty->assign('block_no', Tools::getValue('block_no'));
            } elseif (isset($shipping_address['block_no'])) {
                $this->context->smarty->assign('block_no', $shipping_address['block_no']);
            } else {
                $this->context->smarty->assign('block_no', '');
            }

            if (Tools::getIsset('entrance_no')) {
                $this->context->smarty->assign('entrance_no', Tools::getValue('entrance_no'));
            } elseif (isset($shipping_address['entrance_no'])) {
                $this->context->smarty->assign('entrance_no', $shipping_address['entrance_no']);
            } else {
                $this->context->smarty->assign('entrance_no', '');
            }

            if (Tools::getIsset('floor_no')) {
                $this->context->smarty->assign('floor_no', Tools::getValue('floor_no'));
            } elseif (isset($shipping_address['floor_no'])) {
                $this->context->smarty->assign('floor_no', $shipping_address['floor_no']);
            } else {
                $this->context->smarty->assign('floor_no', '');
            }

            if (Tools::getIsset('apartment_no')) {
                $this->context->smarty->assign('apartment_no', Tools::getValue('apartment_no'));
            } elseif (isset($shipping_address['apartment_no'])) {
                $this->context->smarty->assign('apartment_no', $shipping_address['apartment_no']);
            } else {
                $this->context->smarty->assign('apartment_no', '');
            }

            if (Tools::getIsset('office_id')) {
                $this->context->smarty->assign('office_id', Tools::getValue('office_id'));
            } elseif (isset($shipping_address['office_id'])) {
                $this->context->smarty->assign('office_id', $shipping_address['office_id']);
            } else {
                $this->context->smarty->assign('office_id', 0);
            }

            if (Tools::getIsset('is_apt')) {
                $this->context->smarty->assign('is_apt', Tools::getValue('is_apt'));
                $is_apt = Tools::getValue('is_apt');
            } elseif (isset($shipping_address['is_apt'])) {
                $this->context->smarty->assign('is_apt', $shipping_address['is_apt']);
                $is_apt = $shipping_address['is_apt'];
            }

            if (Tools::getIsset('to_office')) {
                $this->context->smarty->assign('to_office', Tools::getValue('to_office'));
                $to_office = Tools::getValue('to_office');
            } elseif (isset($shipping_address['to_office'])) {
                $this->context->smarty->assign('to_office', $shipping_address['to_office']);
                $to_office = $shipping_address['to_office'];
            }

            if (Tools::getIsset('note')) {
                $this->context->smarty->assign('note', Tools::getValue('note'));
            } elseif (isset($shipping_address['note'])) {
                $this->context->smarty->assign('note', $shipping_address['note']);
            } else {
                $this->context->smarty->assign('note', '');
            }

            if (Tools::getIsset('country')) {
                $this->context->smarty->assign('country', Tools::getValue('country'));
            } elseif (isset($shipping_address['country'])) {
                $this->context->smarty->assign('country', $shipping_address['country']);
            } else {
                $this->context->smarty->assign('country', '');
            }

            if (Tools::getIsset('country_id')) {
                $country_id = Tools::getValue('country_id');
            } elseif (isset($shipping_address['country_id'])) {
                $country_id = $shipping_address['country_id'];
            } else {
                $country_id = '';
            }

            $this->context->smarty->assign('country_id', $country_id);

            if ($delivery_country->iso_code == 'RO') {
                $this->context->smarty->assign('allowed_country', 1);
            } else {
                $this->context->smarty->assign('allowed_country', 0);
            }

            if (Tools::getIsset('country_nomenclature')) {
                $this->context->smarty->assign('country_nomenclature', Tools::getValue('country_nomenclature'));
            } elseif (isset($shipping_address['country_nomenclature'])) {
                $this->context->smarty->assign('country_nomenclature', $shipping_address['country_nomenclature']);
            } else {
                $this->context->smarty->assign('country_nomenclature', '');
            }

            if (Tools::getIsset('country_address_nomenclature')) {
                $this->context->smarty->assign('country_address_nomenclature', Tools::getValue('country_address_nomenclature'));
            } elseif (isset($shipping_address['country_address_nomenclature'])) {
                $this->context->smarty->assign('country_address_nomenclature', $shipping_address['country_address_nomenclature']);
            } else {
                $this->context->smarty->assign('country_address_nomenclature', '');
            }

            if (Tools::getIsset('required_state')) {
                $this->context->smarty->assign('required_state', Tools::getValue('required_state'));
            } elseif (isset($shipping_address['required_state'])) {
                $this->context->smarty->assign('required_state', $shipping_address['required_state']);
            } else {
                $this->context->smarty->assign('required_state', '');
            }

            if (Tools::getIsset('required_postcode')) {
                $this->context->smarty->assign('required_postcode', Tools::getValue('required_postcode'));
            } elseif (isset($shipping_address['required_postcode'])) {
                $this->context->smarty->assign('required_postcode', $shipping_address['required_postcode']);
            } else {
                $this->context->smarty->assign('required_postcode', '');
            }

            if (Tools::getIsset('active_currency_code')) {
                $this->context->smarty->assign('active_currency_code', Tools::getValue('active_currency_code'));
            } elseif (isset($_SESSION['speedy']['active_currency_code'])) {
                $this->context->smarty->assign('active_currency_code', $_SESSION['speedy']['active_currency_code']);
            } else {
                $this->context->smarty->assign('active_currency_code', '');
            }

            if (Tools::getIsset('state')) {
                $this->context->smarty->assign('state', Tools::getValue('state'));
            } elseif (isset($shipping_address['state'])) {
                $this->context->smarty->assign('state', $shipping_address['state']);
            } else {
                $this->context->smarty->assign('state', '');
            }

            if (Tools::getIsset('state_id')) {
                $this->context->smarty->assign('state_id', Tools::getValue('state_id'));
            } elseif (isset($shipping_address['state_id'])) {
                $this->context->smarty->assign('state_id', $shipping_address['state_id']);
            } else {
                $this->context->smarty->assign('state_id', '');
            }

            if (Tools::getIsset('address_1')) {
                $this->context->smarty->assign('address_1', Tools::getValue('address_1'));
            } elseif (isset($shipping_address['address_1'])) {
                $this->context->smarty->assign('address_1', $shipping_address['address_1']);
            } elseif (isset($store_shipping_address['address1'])) {
                $this->context->smarty->assign('address_1', $store_shipping_address['address1']);
            } else {
                $this->context->smarty->assign('address_1', '');
            }

            if (Tools::getIsset('address_2')) {
                $this->context->smarty->assign('address_2', Tools::getValue('address_2'));
            } elseif (isset($shipping_address['address_2'])) {
                $this->context->smarty->assign('address_2', $shipping_address['address_2']);
            } elseif (isset($store_shipping_address['address2'])) {
                $this->context->smarty->assign('address_2', $store_shipping_address['address2']);
            } else {
                $this->context->smarty->assign('address_2', '');
            }

            if (isset($_SESSION['speedy']['fixed_time_cb'])) {
                $fixed_time_cb = $_SESSION['speedy']['fixed_time_cb'];
            } else {
                $fixed_time_cb = false;
            }

            if (isset($_SESSION['speedy']['fixed_time_hour'])) {
                $fixed_time_hour = $_SESSION['speedy']['fixed_time_hour'];
            } else {
                $fixed_time_hour = '10';
            }

            if (isset($_SESSION['speedy']['fixed_time_min'])) {
                $fixed_time_min = $_SESSION['speedy']['fixed_time_min'];
            } else {
                $fixed_time_min = '30';
            }

            $this->context->smarty->assign('fixed_time_cb', $fixed_time_cb);
            $this->context->smarty->assign('fixed_time_hour', $fixed_time_hour);
            $this->context->smarty->assign('fixed_time_min', $fixed_time_min);

            $this->context->smarty->assign('fixed_time', Configuration::get('SPEEDY_FIXED_TIME'));

            $this->context->smarty->assign('offices', array());

            if (Context::getContext()->customer->logged && !empty(Context::getContext()->cart->id_address_delivery)) {
                $shipping_address = $store_shipping_address;
            }

            $this->context->smarty->assign('cod_status', $speedypayment);

            $lang = (!empty($shipping_address['id_country']) && Country::getIsoById($shipping_address['id_country']) != 'BG') ? 'en' : $this->context->language->iso_code;

            $country_disabled = true;
            $state_disabled = true;
            $country_nomenclature = false;

            if (!$country_id && !empty($shipping_address['id_country'])) {
                $country_filter = array('iso_code_2' => Country::getIsoById($shipping_address['id_country']));

                SpeedyCache::clean();
                $countryCache = SpeedyCache::get('speedy.countries.' . md5(json_encode($country_filter) . $lang));

                if ($countryCache) {
                    $countries = $countryCache;
                } else {
                    $countries = $this->speedy->getCountries($country_filter, $lang);
                    SpeedyCache::set('speedy.countries.' . md5(json_encode($country_filter) . $lang), $countries);
                }

                if (!$this->speedy->getError()) {
                    if (count($countries) == 1) {
                        $country = $countries[0];
                        $country_id = $country['id'];
                        $country_disabled = true;
                        $country_nomenclature = $country['nomenclature'];

                        $this->context->smarty->assign('country', $country['name']);
                        $this->context->smarty->assign('country_id', $country['id']);
                        $this->context->smarty->assign('country_nomenclature', $country['nomenclature']);
                        $this->context->smarty->assign('required_state', $country['required_state']);
                        $this->context->smarty->assign('required_postcode', $country['required_postcode']);
                        $this->context->smarty->assign('active_currency_code', $country['active_currency_code']);

                        if (!$country['active_currency_code']) {
                            $this->context->smarty->assign('cod_status', 0);
                        }

                        $shipping_state = (array) new State($shipping_address['id_state']);

                        if ($abroad) {
                            SpeedyCache::clean();
                            $stateCache = SpeedyCache::get('speedy.states.' . md5($country['id'] . $shipping_state['iso_code']));

                            if ($stateCache) {
                                $states = $stateCache;
                            } else {
                                $states = $this->speedy->getStates($country['id'], $shipping_state['iso_code']);
                                SpeedyCache::set('speedy.states.' . md5($country['id'] . $shipping_state['iso_code']), $states);
                            }

                            if (!$this->speedy->getError()) {
                                if (count($states) == 1) {
                                    $state = $states[0];
                                    $this->context->smarty->assign('state', $state['name']);
                                    $this->context->smarty->assign('state_id', $state['id']);
                                } else {
                                    foreach ($states as $state) {
                                        if ($shipping_state['iso_code'] == $state['code']) {
                                            $this->context->smarty->assign('state', $state['name']);
                                            $this->context->smarty->assign('state_id', $state['id']);
                                        }
                                    }

                                    $state_disabled = false;
                                }
                            } else {
                                $this->context->smarty->assign('error_address', $this->speedy->getError());
                            }
                        }
                    } else {
                        $country_disabled = false;
                    }
                } else {
                    $this->context->smarty->assign('error_address', $this->speedy->getError());
                }
            } else {
                $countries = $this->speedy->getCountries(array('country_id' => $country_id), $lang);

                if (count($countries) == 1) {
                    $country = $countries[0];
                    $this->context->smarty->assign('active_currency_code', $country['active_currency_code']);
                    if (!$country['active_currency_code']) {
                        $this->context->smarty->assign('cod_status', 0);
                    }
                }
            }

            $this->context->smarty->assign('country_disabled', $country_disabled);
            $this->context->smarty->assign('state_disabled', $state_disabled);

            if (!$city_id && !empty($countries[0]['id'])) {
                $cities = $this->speedy->getCities($shipping_address['city'], $shipping_address['postcode'], $country_id, $lang);

                if (!$this->speedy->getError()) {
                    if (count($cities) == 1) {
                        $this->context->smarty->assign('postcode', $cities[0]['postcode'] ? $cities[0]['postcode'] : $shipping_address['postcode']);
                        $this->context->smarty->assign('city', $cities[0]['value']);
                        $this->context->smarty->assign('city_id', $cities[0]['id']);
                        $city_id = $cities[0]['id'];
                        $this->context->smarty->assign('city_nomenclature', $cities[0]['nomenclature']);
                    } elseif ($country_nomenclature != 'FULL') {
                        if (Tools::getIsset('city') && Tools::getIsset('postcode')) {
                            $this->context->smarty->assign('city', Tools::getValue('city'));
                            $this->context->smarty->assign('postcode', Tools::getValue('postcode'));
                        } elseif (isset($_SESSION['speedy'])) {
                            $this->context->smarty->assign('city', $_SESSION['speedy']['city']);
                            $this->context->smarty->assign('postcode', $_SESSION['speedy']['postcode']);
                        } else {
                            $this->context->smarty->assign('city', $shipping_address['city']);
                            $this->context->smarty->assign('postcode', $shipping_address['postcode']);
                        }
                    }
                } else {
                    $this->context->smarty->assign('error_address', $this->speedy->getError());
                }
            }

            if ($city_id && $country_id) {
                SpeedyCache::clean();
                $officeCache = SpeedyCache::get('speedy.offices.' . md5($city_id . $lang . $country_id));

                if ($officeCache) {
                    $this->context->smarty->assign('offices', $officeCache);
                } else {
                    $officeCache = $this->speedy->getOffices(null, $city_id, $lang, $country_id);
                    $this->context->smarty->assign('offices', $officeCache);
                    SpeedyCache::set('speedy.offices.' . md5($city_id . $lang . $country_id), $officeCache);
                }

                if (isset($officeCache) && !isset($to_office)) {
                    $this->context->smarty->assign('to_office', 1);

                    if (!isset($is_apt)) {
                        foreach ($officeCache as $office) {
                            if (!empty($office['is_apt'])) {
                                $this->context->smarty->assign('is_apt', 1);
                            }
                        }
                    }
                }

                if ($this->speedy->getError()) {
                    $this->context->smarty->assign('error_office', $this->speedy->getError());
                }
            }

            if (isset($_SESSION['error_speedy_calculate'])) {
                $this->context->smarty->assign('error_speedy_calculate', $_SESSION['error_speedy_calculate']);
                unset($_SESSION['error_speedy_calculate']);
            } else {
                $this->context->smarty->assign('error_speedy_calculate', false);
            }
        } else {
            $speedy_error = 1;
        }

        $this->context->smarty->assign(array(
            'speedy_carrier_id' => Configuration::get('SPEEDY_CARRIER_ID'),
            'this_path' => $this->_path,
            'speedy_error' => $speedy_error,
            'calculated_price' => isset($_SESSION['speedy']['shipping_method_cost']) ? Tools::displayPrice(Tools::convertPriceFull((float)$_SESSION['speedy']['shipping_method_cost'], $this->bg_currency, Context::getContext()->currency)) : 'not_calculated',
            'is_logged' => $this->context->customer->logged ? true : false,
            'this_path_ssl' => Tools::getShopDomainSsl(true, true) . __PS_BASE_URI__ . 'modules/' . $this->name . '/'
        ));

        if (version_compare(@constant('_PS_VERSION_'), '1.7', '>=')) {
            return $this->display(__FILE__, 'ps17/speedy.tpl');
        } else {
            return $this->display(__FILE__, 'ps16/speedy.tpl');
        }
    }

    public function hookBeforeCarrier($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        if (!$this->active || !$carrier_active)
            return;

        $this->context->smarty->assign(array(
            'speedy_carrier_id' => Configuration::get('SPEEDY_CARRIER_ID'),
            'calculated_price' => isset($_SESSION['speedy']['shipping_method_cost']) ? Tools::displayPrice(Tools::convertPriceFull((float)$_SESSION['speedy']['shipping_method_cost'], $this->bg_currency, Context::getContext()->currency)) : 'not_calculated',
        ));

        if (Context::getContext()->cart->id_carrier == Configuration::get('SPEEDY_CARRIER_ID') && empty(Context::getContext()->cart->id_address_delivery)) {
            $this->context->smarty->assign('speedy_address_error', $this->displayError($this->l('Моля въведете адрес за доставка!')));
        }

        return $this->display(__FILE__, 'speedy_before_carrier.tpl');
    }

    public function hookDisplayMobileHeader($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        if (!$this->active || !$carrier_active || !$this->validateCurrency())
            return;

        if (method_exists($this->context->controller, "addCSS")) {
            $this->context->controller->addCSS(($this->_path).'speedy.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.theme.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.autocomplete.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.core.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.menu.css', 'all');
        }

        if (method_exists($this->context->controller, "addJS")) {
            $this->context->controller->addJquery();
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.core.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.widget.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.position.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.menu.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.autocomplete.min.js');
        }

        if (Tools::getIsset('id_order') && Tools::getIsset('id_cart') && isset($_SESSION['speedy']) && !empty($_SESSION['speedy']['shipping_method_id']) && isset($_SESSION['speedy']['shipping_method_cost'])) {
            $orders = $this->getOrdersByCartId(Tools::getValue('id_cart'));
            if (isset($orders[Configuration::get('SPEEDY_CARRIER_ID')])) {
                $this->_addOrder(Tools::getValue('id_order'), $_SESSION['speedy']);
                unset($_SESSION['speedy']);
            }
        }
    }

    public function hookDisplayPaymentTop($params)
    {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        $allowed_pricings = array(
            'calculator',
            'free',
            'calculator_fixed'
        );

        if (!$this->active || !$carrier_active || !Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT') || !in_array(Configuration::get('SPEEDY_PRICING'), $allowed_pricings) || (isset($_SESSION['speedy']['cod']) && $_SESSION['speedy']['cod']))
            return;

        if (Context::getContext()->cart->id_carrier == Configuration::get('SPEEDY_CARRIER_ID') && isset($_SESSION['speedy']['shipping_method_text']) && !empty($_SESSION['speedy']['shipping_method_cost'])) {
            $this->context->smarty->assign('speedy_label', sprintf($this->l('Спиди (%s дължими при доставка)'), $_SESSION['speedy']['shipping_method_text']));
            $this->context->smarty->assign('speedy_price', Tools::displayPrice(0.00, Context::getContext()->currency));
        } else {
            $this->context->smarty->assign('speedy_label', '');
            $this->context->smarty->assign('speedy_price', Tools::displayPrice(0.00, Context::getContext()->currency));
        }

        return $this->display(__FILE__, 'speedy_shopping_cart.tpl');
    }

    public function hookDisplayAdminProductsExtra($params) {
        if (!empty(Tools::getValue('id_product'))) {
            $quantity_dimentions = $this->_getSpeedyDimentions(Tools::getValue('id_product'));
        } elseif (!empty($params['id_product'])) {
            $quantity_dimentions = $this->_getSpeedyDimentions($params['id_product']);
        } else {
            $quantity_dimentions = array();
        }

        $this->context->smarty->assign('quantity_dimentions', $quantity_dimentions);
        return $this->display(__FILE__, 'speedy_product.tpl');
    }

    public function hookActionProductSave($params) {
        $this->_editSpeedyDimentions($params['id_product'], Tools::getValue('speedy_quantity_dimentions'));
    }

    public function hookDisplayOrderDetail($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        $allowed_pricings = array(
            'calculator',
            'free',
            'calculator_fixed'
        );

        $table_speedy_label = '';

        if (!(!$this->active || !$carrier_active || !Tools::getValue('id_order') || !Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT') || !in_array(Configuration::get('SPEEDY_PRICING'), $allowed_pricings) || empty($params['order']->id))) {
            $speedy_order_info = $this->_getOrder($params['order']->id);

            if (!(isset($speedy_order_info['cod']) && $speedy_order_info['cod'])) {
                if ($speedy_order_info) {
                    $speedy_order_data = unserialize($speedy_order_info['data']);

                    if (isset($speedy_order_data['shipping_method_text']) && !empty($speedy_order_data['shipping_method_cost'])) {
                        $speedy_label = sprintf($this->l('Спиди (%s дължими при доставка)'), $speedy_order_data['shipping_method_text']);

                        $table_speedy_label = '<table class="table" style="background-color: #2d2d2d; color: #fff;"><tr><td>'.$speedy_label.'</td></tr></table>';
                    }
                }
            }
        }

        $this->context->smarty->assign('table_speedy_label', $table_speedy_label);

        return $this->display(__FILE__, 'speedy_order_detail.tpl');
    }

    public function hookDisplayPDFInvoice($params) {
        if (Configuration::get('SPEEDY_CARRIER_ID')) {
            $carrier = new Carrier(Configuration::get('SPEEDY_CARRIER_ID'));
            $carrier_active = $carrier->active;
        } else {
            $carrier_active = false;
        }

        $allowed_pricings = array(
            'calculator',
            'free',
            'calculator_fixed'
        );

        if (!$this->active || !$carrier_active || !Tools::getValue('id_order') || !Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT') || !in_array(Configuration::get('SPEEDY_PRICING'), $allowed_pricings) || empty($params['object']->id_order))
            return ;

        $speedy_order_info = $this->_getOrder($params['object']->id_order);

        if (isset($speedy_order_info['cod']) && $speedy_order_info['cod']) {
            return;
        }

        if ($speedy_order_info) {
            $speedy_order_data = unserialize($speedy_order_info['data']);

            if (isset($speedy_order_data['shipping_method_text']) && !empty($speedy_order_data['shipping_method_cost'])) {
                $speedy_label =sprintf($this->l('Спиди (%s дължими при доставка)'), $speedy_order_data['shipping_method_text']);

                return '<table class="table" style="background-color: #2d2d2d; color: #fff;"><tr><td style="padding: 10px;">'.$speedy_label.'</td></tr></table>';
            }
        }
    }

    public function hookBackOfficeHeader($params) {
        if (!$this->active || !$this->validateCurrency())
            return;

        if (method_exists($this->context->controller, "addCSS")) {
            $this->context->controller->addCSS(($this->_path).'speedy.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.theme.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.autocomplete.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.core.css', 'all');
            $this->context->controller->addCSS(($this->_path).'js/themes/base/jquery.ui.menu.css', 'all');
        }

        if (method_exists($this->context->controller, "addJS")) {
            $this->context->controller->addJquery();
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.core.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.widget.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.position.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.menu.min.js');
            $this->context->controller->addJS(($this->_path).'js/jquery.ui.autocomplete.min.js');
        }
    }

    public function getOrderShippingCost($params, $shipping_cost) {
        $shouldSubstractFromTotal = false;
        $shippingAmount = 0;

        $allowed_pricings = array(
            'calculator',
            'free',
            'calculator_fixed'
        );
        
        if (Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT') && isset($_SESSION['speedy']['shipping_method_cost'])) {
            if(in_array(Configuration::get('SPEEDY_PRICING'), $allowed_pricings) && (!isset($_SESSION['speedy']['cod']) || !$_SESSION['speedy']['cod'])){
                $shippingAmount = (float)$_SESSION['speedy']['shipping_method_cost'];
                if(Configuration::get('SPEEDY_PRICING') == 'free'){
                    $delta = 0.0001;

                    if( abs($shippingAmount - 0.0000) > $delta ){
                        $shouldSubstractFromTotal = true;
                    }
                } else {
                    $shouldSubstractFromTotal = true;
                }
            }
        }

        if (!$shouldSubstractFromTotal && isset($_SESSION['speedy']['shipping_method_cost'])) {
            return (float)$_SESSION['speedy']['shipping_method_cost'];
        } else {
            return 0;
        }
    }

    public function getOrderShippingCostExternal($params) {
        $shouldSubstractFromTotal = false;
        $shippingAmount = 0;

        $allowed_pricings = array(
            'calculator',
            'free',
            'calculator_fixed'
        );

        if (Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT') && isset($_SESSION['speedy']['shipping_method_cost'])) {
            if(in_array(Configuration::get('SPEEDY_PRICING'), $allowed_pricings) && (!isset($_SESSION['speedy']['cod']) || !$_SESSION['speedy']['cod'])){
                $shippingAmount = (float)$_SESSION['speedy']['shipping_method_cost'];
                if(Configuration::get('SPEEDY_PRICING') == 'free'){
                    $delta = 0.0001;

                    if( abs($shippingAmount - 0.0000) > $delta ){
                        $shouldSubstractFromTotal = true;
                    }
                }else{
                    $shouldSubstractFromTotal = true;
                }
            }
        }

        if (!$shouldSubstractFromTotal && isset($_SESSION['speedy']['shipping_method_cost'])) {
            return Tools::convertPriceFull((float)$_SESSION['speedy']['shipping_method_cost'], $this->bg_currency, Context::getContext()->currency);
        } else {
            return 0;
        }
    }

    public function validateCurrency() {
        if (Currency::getIdByIsoCode('BGN')) {
            return true;
        } else {
            return false;
        }
    }

    public function printPDF($speedy_order_info) {
        if (!empty($speedy_order_info) && !empty($speedy_order_info['bol_id'])) {
            if (!isset($speedy_order_info['speedy_additional_copy_for_sender'])) {
                $speedy_order_info['speedy_additional_copy_for_sender'] = null;
            }
            $pdf = $this->speedy->createPDF($speedy_order_info['bol_id'], $speedy_order_info['speedy_additional_copy_for_sender']);

            if (!$this->speedy->getError() && $pdf) {
                Tools::redirectAdmin($this->context->link->getModuleLink($this->name, 'print_pdf', array('bol_id' => $speedy_order_info['bol_id'])));
                exit;
            } else {
                $_SESSION['warning'] = $this->speedy->getError();
                return false;
            }
        } else {
            $_SESSION['warning'] = $this->l('Внимание: Товарителницата не съществува!');
            return false;
        }

        return false;
    }

    public function printReturnVoucher($speedy_order_info) {
        if (!empty($speedy_order_info) && !empty($speedy_order_info['bol_id'])) {
            if (!isset($speedy_order_info['speedy_additional_copy_for_sender'])) {
                $speedy_order_info['speedy_additional_copy_for_sender'] = null;
            }
            $pdf = $this->speedy->createReturnVoucher($speedy_order_info['bol_id'], $speedy_order_info['speedy_additional_copy_for_sender']);

            if (!$this->speedy->getError() && $pdf) {
                Tools::redirectAdmin($this->context->link->getModuleLink($this->name, 'print_return_voucher', array('bol_id' => $speedy_order_info['bol_id'])));
                exit;
            } else {
                $_SESSION['warning'] = $this->speedy->getError();
                return false;
            }
        } else {
            $_SESSION['warning'] = $this->l('Внимание: Товарителницата не съществува!');
            return false;
        }

        return false;
    }

    public function speedyCourier($selected) {
        $bol_ids = array();

        foreach ($selected as $order_id) {
            $speedy_order_info = $this->_getOrder($order_id);

            if ($speedy_order_info['bol_id']) {
                $bol_ids[] = $speedy_order_info['bol_id'];
            }
        }

        if ($bol_ids) {
            $results = $this->speedy->requestCourier($bol_ids);

            if (!$this->speedy->getError()) {
                $error = array();

                foreach ($results as $result) {
                    if (!$result->getErrorDescriptions()) {
                        $this->_editOrderCourier($result->getBillOfLading(), true);
                    } else {
                        $error[] = $result->getBillOfLading() . ' - ' . implode(', ', $result->getErrorDescriptions());
                    }
                }

                if ($error) {
                    $_SESSION['courier_warning'] = implode('<br />', $error);
                } else {
                    $_SESSION['courier_success'] = $this->l('Готово, заявихте куриер!');
                }
            } else {
                $_SESSION['courier_warning'] = $this->speedy->getError();
            }
        } else {
            $_SESSION['courier_warning'] = $this->l('Няма избрани товарителници!');
        }
    }

    public function cancelLoading($speedy_order_info) {
        if (!empty($speedy_order_info) && !empty($speedy_order_info['bol_id'])) {
            $cancelled = $this->speedy->cancelBol($speedy_order_info['bol_id']);

            if (!$this->speedy->getError() && $cancelled) {
                $this->_deleteOrder($speedy_order_info['order_id']);
                $order = new Order($speedy_order_info['order_id']);
                $order->setWsShippingNumber('');

                $_SESSION['success'] = $this->l('Готово, анулирахте товарителница!');
                return true;
            } else {
                $_SESSION['warning'] = $this->speedy->getError();
                return false;
            }
        } else {
            $_SESSION['warning'] = $this->l('Внимание: Товарителницата не съществува!');
            return false;
        }
    }

// End speedy currency convertion function
//START AJAX methods
    public function getCitiesByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('country_id')) {
            $country_id = Tools::getValue('country_id');
        } else {
            $country_id = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        $data = $this->speedy->getCities($name, null, $country_id, $lang);

        if ($this->speedy->getError()) {
            $data = array('error' => $this->speedy->getError());
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getQuartersByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('city_id')) {
            $city_id = Tools::getValue('city_id');
        } else {
            $city_id = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        if ($city_id) {
            $data = $this->speedy->getQuarters($name, $city_id, $lang);

            if ($this->speedy->getError()) {
                $data = array('error' => $this->speedy->getError());
            }
        } else {
            $data = array('error' => $this->l('Моля, въведете населено място!'));
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getStreetsByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('city_id')) {
            $city_id = Tools::getValue('city_id');
        } else {
            $city_id = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        if ($city_id) {
            $data = $this->speedy->getStreets($name, $city_id, $lang);

            if ($this->speedy->getError()) {
                $data = array('error' => $this->speedy->getError());
            }
        } else {
            $data = array('error' => $this->l('Моля, въведете населено място!'));
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getObjectByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('city_id')) {
            $city_id = Tools::getValue('city_id');
        } else {
            $city_id = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        if ($city_id) {
            $data = $this->speedy->getObject($name, $city_id, $lang);

            if ($this->speedy->getError()) {
                $data = array('error' => $this->speedy->getError());
            }
        } else {
            $data = array('error' => $this->l('Моля, въведете населено място!'));
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getBlocksByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('city_id')) {
            $city_id = Tools::getValue('city_id');
        } else {
            $city_id = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        if ($city_id) {
            $data = $this->speedy->getBlocks($name, $city_id, $lang);

            if ($this->speedy->getError()) {
                $data = array('error' => $this->speedy->getError());
            }
        } else {
            $data = array('error' => $this->l('Моля, въведете населено място!'));
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getOfficesByCityId() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('city_id')) {
            $city_id = Tools::getValue('city_id');
        } else {
            $city_id = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        if (Tools::getValue('country_id')) {
            $country_id = Tools::getValue('country_id');
        } else {
            $country_id = SpeedyEpsLib::BULGARIA;
        }

        if ($city_id && $country_id) {
            SpeedyCache::clean();
            $data = SpeedyCache::get('speedy.offices.' . md5($city_id . $lang . $country_id));

            if ((empty($data) && empty($name)) || empty($name)) {
                $data = $this->speedy->getOffices('', $city_id, $lang, $country_id);
                SpeedyCache::set('speedy.offices.' . md5($city_id . $lang . $country_id), $data);
            } else {
                $data = $this->speedy->getOffices($name, $city_id, $lang, $country_id);
            }

            if ($this->speedy->getError()) {
                $data = array('error' => $this->speedy->getError());
            }
        } else {
            $data = array('error' => $this->l('Моля, въведете населено място!'));
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getCountriesByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('abroad') && Tools::getValue('abroad')) {
            $lang = 'en';
        } else {
            $lang = $this->context->language->iso_code;
        }

        $data = $this->speedy->getCountries($name, $lang);

        if ($this->speedy->getError()) {
            $data = array('error' => $this->speedy->getError());
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function getStatesByName() {
        if (Tools::getIsset('term')) {
            $name = Tools::getValue('term');
        } else {
            $name = '';
        }

        if (Tools::getIsset('country_id')) {
            $country_id = Tools::getValue('country_id');
        } else {
            $country_id = '';
        }

        $data = $this->speedy->getStates($country_id, $name);

        if ($this->speedy->getError()) {
            $data = array('error' => $this->speedy->getError());
        }

        echo Tools::jsonEncode($data);
        exit;
    }

    public function validateBillOfLading() {
        $json = array();

        // check APT office
        if (!Tools::getValue('abroad') && Tools::getValue('speedy_shipping_to_office') && Tools::getValue('speedy_option_before_payment') != 'no_option' && Tools::getIsset('speedy_office_id') && Tools::getIsset('speedy_city_id')) {
            $office = $this->speedy->getOfficeById(Tools::getValue('speedy_office_id'), Tools::getValue('speedy_city_id'));

            if(!empty($office) && $office->getOfficeType() == 3) { // 3 for APT office
                $json['error'] = true;
                $json['errors']['APT_office'] = $this->l('Избраният офис е АПС и няма да се вземат под внимане опциите за ОПП, ТПП, Обратни Документи и Обратна Разписка');
            }
        }

        // checkDate
        if (Tools::getIsset('shipping_method_id')) {
            $shipping_method_id = Tools::getValue('shipping_method_id');
        } else {
            $shipping_method_id = '';
        }

        $taking_date = (Configuration::get('SPEEDY_TAKING_DATE') ? strtotime('+' . (int) Configuration::get('SPEEDY_TAKING_DATE') . ' day', mktime(9, 0, 0)) : time());
        $first_available_date = strtotime($this->speedy->getAllowedDaysForTaking(array('shipping_method_id' => $shipping_method_id, 'taking_date' => $taking_date)));

        if (!$this->speedy->getError() && $first_available_date) {
            if (date('d-m-Y', $first_available_date) != date('d-m-Y', $taking_date)) {
                $json['error'] = true;
                $json['errors']['warning'] = sprintf($this->l('Първата възможна дата за вземане на пратката е: %s. Желаете ли да създадете товарителницата?'), date("d/m/Y", $first_available_date));
                $json['taking_date'] = date('d-m-Y', $first_available_date);
            }
        } else {
            $json['error'] = true;
            $json['errors']['warning'] = $this->speedy->getError();
        }

        // check BackDocumentsRequest and BackReceiptRequest
        if (!empty($shipping_method_id)) {
            $service = $this->speedy->getServiceById($shipping_method_id);

            if(!empty($service)) {
                if($service->getAllowanceBackDocumentsRequest()->getValue() == 'BANNED' && $service->getAllowanceBackReceiptRequest()->getValue() == 'BANNED') {
                    $json['error'] = true;
                    $json['errors']['document_receipt'] = $this->l('Няма да се вземат под внимане опциите за Обратни Документи и Обратна Разписка');
                } elseif($service->getAllowanceBackDocumentsRequest()->getValue() == 'BANNED') {
                    $json['error'] = true;
                    $json['errors']['document'] = $this->l('Обратни Документи няма да се вземат под внимане');
                } elseif($service->getAllowanceBackReceiptRequest()->getValue() == 'BANNED') {
                    $json['error'] = true;
                    $json['errors']['receipt'] = $this->l('Обратна Разписка няма да се вземат под внимане');
                } else {}
            }
        }

        echo Tools::jsonEncode($json);
        exit;
    }

    public function compareAddresses() {
        $json = array();

        if (!empty($this->context->cart->id_address_delivery)) {
            $delivery_address = new Address((int)$this->context->cart->id_address_delivery);

            if ($delivery_address->id) {
                if (Tools::getValue('postcode') != $delivery_address->postcode) {
                    $json['error'] = true;
                    $json['warning'] = $this->l('Вашите данни за доставка са различни от данните за Спиди!');
                } else {
                    $lang = Tools::getValue('abroad') ? 'en' : $this->context->language->iso_code;
                    $cities = $this->speedy->getCities($delivery_address->city, $delivery_address->postcode, Tools::getValue('country_id'), $lang);

                    if (!$this->speedy->getError()) {
                        if (empty($cities)) {
                            if (Tools::getValue('city') != $delivery_address->city) {
                                $json['error'] = true;
                                $json['warning'] = $this->l('Вашите данни за доставка са различни от данните за Спиди!');
                            }
                        } elseif (Tools::getIsset('city_id')) {
                            if (Tools::getValue('city_id') != $cities[0]['id']) {
                                $json['error'] = true;
                                $json['warning'] = $this->l('Вашите данни за доставка са различни от данните за Спиди!');
                            }
                        }
                    }
                }
            }
        }

        echo Tools::jsonEncode($json);
        exit;
    }

//END AJAX methods
//START SQL methods
    public function _getOrder($order_id) {
        $sql = "SELECT * FROM " . _DB_PREFIX_ . "speedy_order WHERE order_id = '" . (int) $order_id . "'";

        $result = Db::getInstance()->ExecuteS($sql);
        if ($result && isset($result[0])) {
            return $result[0];
        } else {
            return false;
        }
    }

    public function _getOrderByBolId($bol_id) {
        $sql = "SELECT * FROM " . _DB_PREFIX_ . "speedy_order WHERE bol_id = '" . pSQL($bol_id) . "'";

        $result = Db::getInstance()->ExecuteS($sql);
        if ($result && isset($result[0])) {
            return $result[0];
        } else {
            return false;
        }
    }

    public function _editOrder($order_id, $data) {
        $sql = "UPDATE " . _DB_PREFIX_ . "speedy_order SET bol_id = '" . pSQL($data['bol_id']) . "', taking_date = '" . pSQL($data['taking_date']) . "', speedy_additional_copy_for_sender = '" . pSQL($data['speedy_additional_copy_for_sender']) . "', date_created = NOW() WHERE order_id  = '" . (int) $order_id . "'";

        Db::getInstance()->Execute($sql);
    }

    public function _editOrderCourier($bol_id, $courier) {
        $sql = "UPDATE " . _DB_PREFIX_ . "speedy_order SET courier = '" . (int) $courier . "' WHERE bol_id  = '" . pSQL($bol_id) . "'";

        Db::getInstance()->Execute($sql);
    }

    public function _updateOrderInfo($order_id, $data = array(), $cost, $bol_id) {
        $order = new Order($order_id);

        $order->setWsShippingNumber($bol_id);

        if (!Configuration::get('SPEEDY_INVOICE_COURIER_SEVICE_AS_TEXT')) {
            $difference = $cost - $order->total_shipping;

            $order->total_shipping = $cost;
            $order->total_shipping_tax_excl = $cost;
            $order->total_shipping_tax_incl = $cost;
            $order->total_paid += $difference;
            $order->total_paid_real += $difference;
            $order->total_paid_tax_incl += $difference;
            $order->total_paid_tax_excl += $difference;

            $order->update();

            $id_order_carrier = Db::getInstance()->getValue('
                SELECT `id_order_carrier`
                FROM `'._DB_PREFIX_.'order_carrier`
                WHERE `id_order` = '.(int)$order_id);

            if ($id_order_carrier) {
                $orderCarrier = new OrderCarrier($id_order_carrier);
                $orderCarrier->weight = $weight;
                $orderCarrier->shipping_cost_tax_excl = $cost;
                $orderCarrier->shipping_cost_tax_incl = $cost;
                $orderCarrier->update();
            }

            $sql = "UPDATE `" . _DB_PREFIX_ . "orders` SET `total_paid` = '" . $order->total_paid . "', `total_paid_tax_incl` = '" . $order->total_paid_tax_incl . "', `total_paid_tax_excl` = '" . $order->total_paid_tax_excl . "', `total_paid_real` = '" . $order->total_paid_real . "', `total_shipping` = '" . $order->total_shipping . "', `total_shipping_tax_incl` = '" . $order->total_shipping_tax_incl . "', `total_shipping_tax_excl` = '" . $order->total_shipping_tax_excl . "' WHERE id_order = '" . (int) $order_id . "'";

            Db::getInstance()->Execute($sql);

            $sql = "UPDATE `" . _DB_PREFIX_ . "order_invoice` SET `total_paid_tax_incl` = '" . $order->total_paid_tax_incl . "', `total_shipping_tax_excl` = '" . $order->total_shipping_tax_excl . "', `total_shipping_tax_incl` = '" . $order->total_shipping_tax_incl . "' WHERE id_order = '" . (int) $order_id . "'";

            Db::getInstance()->Execute($sql);

            $sql = "UPDATE `" . _DB_PREFIX_ . "order_payment` SET `amount` = '" . $order->total_paid_real . "' WHERE order_reference = '" . $order->reference . "'";

            Db::getInstance()->Execute($sql);
        }

        $sql = "UPDATE " . _DB_PREFIX_ . "speedy_order SET data = '" . pSQL(serialize($data)) . "' WHERE order_id = '" . (int) $order_id . "' ";

        Db::getInstance()->Execute($sql);
    }

    public function _deleteOrder($order_id) {
        $sql = "UPDATE " . _DB_PREFIX_ . "speedy_order SET bol_id = '', date_created = '0000-00-00 00:00:00', courier = '0' WHERE order_id  = '" . (int) $order_id . "'";

        return Db::getInstance()->Execute($sql);
    }

    public function _getOrders($data = array()) {
        $sql = "SELECT so.*, o.id_customer, o.id_currency FROM " . _DB_PREFIX_ . "speedy_order so LEFT JOIN " . _DB_PREFIX_ . "orders o ON so.order_id = o.id_order  WHERE so.order_id > 0 AND so.bol_id > 0";

        if (!empty($data['filter_bol_id'])) {
            $sql .= " AND so.bol_id = '" . pSQL($data['filter_bol_id']) . "'";
        }

        if (!empty($data['filter_order_id'])) {
            $sql .= " AND so.order_id = '" . (int) $data['filter_order_id'] . "'";
        }

        if (!empty($data['filter_date_created'])) {
            $sql .= " AND DATE(so.date_created) = DATE('" . pSQL($data['filter_date_created']) . "')";
        }

        if (!empty($data['taking_date'])) {
            $sql .= " AND DATE(so.taking_date) = DATE('" . pSQL($data['taking_date']) . "')";
        }

        $sort_data = array(
            'so.bol_id',
            'so.order_id',
            'so.date_created'
        );

        if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
            $sql .= " ORDER BY " . $data['sort'];
        } else {
            $sql .= " ORDER BY so.bol_id";
        }

        if (isset($data['order']) && ($data['order'] == 'DESC')) {
            $sql .= " DESC";
        } else {
            $sql .= " ASC";
        }

        if (isset($data['start']) || isset($data['limit'])) {
            if ($data['start'] < 0) {
                $data['start'] = 0;
            }

            if ($data['limit'] < 1) {
                $data['limit'] = 20;
            }

            $sql .= " LIMIT " . (int) $data['start'] . "," . (int) $data['limit'];
        }

        return Db::getInstance()->ExecuteS($sql);
    }

    public function _addAddress($address_id, $data) {
        $sql = "DELETE FROM " . _DB_PREFIX_ . "speedy_address WHERE address_id = '" . (int) $address_id . "' AND customer_id = '" . (int) Context::getContext()->customer->id . "'";

        Db::getInstance()->Execute($sql);

        $sql = "INSERT INTO " . _DB_PREFIX_ . "speedy_address SET address_id = '" . (int) $address_id . "', customer_id = '" . (int) Context::getContext()->customer->id . "', postcode = '" . pSQL($data['postcode']) . "', city = '" . pSQL($data['city']) . "', city_id = '" . (int) $data['city_id'] . "', city_nomenclature = '" . pSQL($data['city_nomenclature']) . "', to_office = '" . (int) $data['to_office'] . "', office_id = '" . (int) $data['office_id'] . "', quarter = '" . pSQL($data['quarter']) . "', quarter_id = '" . (int) $data['quarter_id'] . "', street = '" . pSQL($data['street']) . "', street_id = '" . (int) $data['street_id'] . "', street_no = '" . pSQL($data['street_no']) . "', block_no = '" . pSQL($data['block_no']) . "', entrance_no = '" . pSQL($data['entrance_no']) . "', floor_no = '" . pSQL($data['floor_no']) . "', apartment_no = '" . pSQL($data['apartment_no']) . "', object = '" . pSQL($data['object']) . "', object_id = '" . (int) $data['object_id'] . "', note = '" . pSQL($data['note']) . "', country = '" . pSQL($data['country']) . "', country_id = '" . pSQL($data['country_id']) . "', country_nomenclature = '" . pSQL($data['country_nomenclature']) . "', state = '" . pSQL($data['state']) . "', state_id = '" . pSQL($data['state_id']) . "', required_state = '" . pSQL($data['required_state']) . "', required_postcode = '" . pSQL($data['required_postcode']) . "', address_1 = '" . pSQL($data['address_1']) . "', address_2 = '" . pSQL($data['address_2']) . "', abroad = '" . pSQL($data['abroad']) . "'";

        Db::getInstance()->Execute($sql);
    }

    public function _getAddress($address_id) {
        $sql = "SELECT * FROM " . _DB_PREFIX_ . "speedy_address WHERE address_id = '" . (int) $address_id . "' AND customer_id = '" . (int) Context::getContext()->customer->id . "'";

        $result = Db::getInstance()->ExecuteS($sql);
        if ($result && isset($result[0])) {
            return $result[0];
        } else {
            return array();
        }
    }

    public function _addOrder($order_id, $data) {
        $sql = "INSERT INTO " . _DB_PREFIX_ . "speedy_order SET order_id = '" . (int) $order_id . "', data = '" . pSQL(serialize($data)) . "'";

        Db::getInstance()->Execute($sql);
    }
    private function _updateOrderDeliveryAddressId($address_id, $order_id) {
        $sql = "UPDATE " . _DB_PREFIX_ . "orders SET id_address_delivery = '" . (int) $address_id . "' WHERE id_order = '" . (int) $order_id . "' ";

        Db::getInstance()->Execute($sql);
    }

    public function _importFilePrice($data) {
        $sql = array();
        $sql[] = "TRUNCATE `" . _DB_PREFIX_ . "speedy_table_rate`";

        foreach ($data as $row) {
            $sql[] = "INSERT INTO " . _DB_PREFIX_ . "speedy_table_rate SET service_id = '" . (int)$row['service_id'] . "', take_from_office = '" . (int)$row['take_from_office'] . "', weight = '" . (float)$row['weight'] . "', order_total = '" . (float)$row['order_total'] . "', price_without_vat = '" . (float)$row['price_without_vat'] . "', fixed_time_delivery = '" . (int)$row['fixed_time_delivery'] . "'";
        }

        foreach ($sql as $s) {
            if (!Db::getInstance()->Execute($s)) {
                return false;
            }
        }
    }

    public function _getSpeedyTableRate($data) {
        $sql = "SELECT price_without_vat FROM " . _DB_PREFIX_ . "speedy_table_rate WHERE service_id = '" . (int)$data['service_id'] . "' AND take_from_office = '" . (int)$data['take_from_office'] . "' AND weight >= '" . (float)$data['weight'] . "' AND order_total >= '" . (int)$data['order_total'] . "' AND fixed_time_delivery = '" . (int)$data['fixed_time_delivery'] . "' ORDER BY weight, order_total ASC";

        $result = Db::getInstance()->ExecuteS($sql);
        if ($result && isset($result[0])) {
            return $result[0];
        } else {
            return false;
        }
    }

    public function _getSpeedyDimentions($product_id) {
        $query = Db::getInstance()->ExecuteS("SHOW TABLES LIKE '" . _DB_PREFIX_ . "speedy_product_settings'");

        if (!empty($query)) {
            $dimentions_rows = Db::getInstance()->ExecuteS("SELECT * FROM " . _DB_PREFIX_ . "speedy_product_settings WHERE product_id = " . (int)$product_id . " LIMIT 1");

            $result = array();

            if(!empty($dimentions_rows)) {
                $result = unserialize($dimentions_rows[0]['quantity_dimentions']);
            }

            return $result;
        }

        return array();
    }

    public function _editSpeedyDimentions($product_id, $data) {
        $query = Db::getInstance()->ExecuteS("SHOW TABLES LIKE '" . _DB_PREFIX_ . "speedy_product_settings'");

        if (!empty($query)) {
            Db::getInstance()->Execute("DELETE FROM " . _DB_PREFIX_ . "speedy_product_settings WHERE product_id = " . (int)$product_id);

            if ($data['XS'] || $data['S'] || $data['M'] || $data['L'] || $data['XL']) {
                Db::getInstance()->Execute("INSERT INTO " . _DB_PREFIX_ . "speedy_product_settings SET product_id = '" . (int)$product_id . "', quantity_dimentions = '" . pSQL(serialize($data)) . "'");
            }
        }
    }

    public function _getWeightDimentions() {
        $query = Db::getInstance()->ExecuteS("SHOW TABLES LIKE '" . _DB_PREFIX_ . "speedy_weight_dimensions'");

        if (!empty($query)) {
            return Db::getInstance()->ExecuteS("SELECT * FROM `" . _DB_PREFIX_ . "speedy_weight_dimensions`");
        } else {
            return array();
        }
    }

    public function _addWeightDimentions($data) {
        $query = Db::getInstance()->ExecuteS("SHOW TABLES LIKE '" . _DB_PREFIX_ . "speedy_weight_dimensions'");

        if (!empty($query)) {
            Db::getInstance()->Execute("DELETE FROM `" . _DB_PREFIX_ . "speedy_weight_dimensions`");

            foreach ($data as $row) {
                Db::getInstance()->Execute("INSERT INTO " . _DB_PREFIX_ . "speedy_weight_dimensions SET WEIGHT = '" . (int)$row['WEIGHT'] . "', XS = '" . (int)$row['XS'] . "', S = '" . (int)$row['S'] . "', M ='" . (int)$row['M'] . "', L = '" . (int)$row['L'] . "', XL ='" . (int)$row['XL'] . "'");
            }
        }
    }

    public function autoLoad($class_name)
    {
        $mainDir = _PS_MODULE_DIR_ . 'speedy' . DIRECTORY_SEPARATOR . 'classes';
        $file = $this->searchFileAutoload($mainDir, $class_name);

        if (!empty($file)) {
            require_once($file);
        }
    }

    private function searchFileAutoload($dir, $class_name)
    {
        $files = glob($dir . '/*');

        if ($files) {
            foreach ($files as $file) {
                if (is_dir($file)) {
                    $return = $this->searchFileAutoload($file, $class_name);

                    if (!empty($return)) {
                        return $return;
                    }
                } elseif (stripos($file, $class_name . '.php') !== false) {
                    return $file;
                }
            }
        }
    }

    private function _getSpeedyQuantityDimention($product_id, $product_quantity) {
        $data = Db::getInstance()->ExecuteS("SELECT * FROM `" . _DB_PREFIX_ . "speedy_product_settings` WHERE product_id = " . (int)$product_id . " LIMIT 1");

        if (!empty($data)) {
            $sizes = unserialize($data[0]['quantity_dimentions']);

            uasort($sizes, array('Speedy', '_cmp'));

            foreach ($sizes as $size => $quantity) {
                if ($quantity >= $product_quantity) {
                    return array(
                                'size'     => $size,
                                'sizes'    => $sizes,
                            );
                }
            }

            return false;
        } else {
            return false;
        }
    }

    private function _speedyHasQuantityDimention($product_id) {
        $data = Db::getInstance()->ExecuteS("SELECT * FROM `" . _DB_PREFIX_ . "speedy_product_settings` WHERE product_id = " . (int)$product_id);

        return (bool)$data;
    }

    private function _getSpeedyWeightDimention($weight, $product_quantity) {
        $sizes = Db::getInstance()->ExecuteS("SELECT " . implode(',', $this->parcel_sizes) . " FROM `" . _DB_PREFIX_ . "speedy_weight_dimensions` WHERE WEIGHT >= " . (int)$weight . " ORDER BY WEIGHT DESC LIMIT 1");

        if (!empty($sizes)) {
            $sizes = $sizes[0];
            uasort($sizes, array('Speedy', '_cmp'));

            foreach($sizes as $size => $quantity) {
                if($quantity >= $product_quantity) {
                    return $size;
                }
            }
        } else {
            return false;
        }
    }

    // sorts the array by quantity without deleting the keys
    private function _cmp($a, $b) {
        if ($a == $b) {
            return 0;
        }
        return ($a < $b) ? -1 : 1;
    }

    private function _compareSizes($current_size, $compare_size) {
        if (!in_array($current_size, $this->parcel_sizes) || !in_array($compare_size, $this->parcel_sizes)) {
            return '';
        }

        if (array_search($current_size, $this->parcel_sizes) < array_search($compare_size, $this->parcel_sizes)) {
            return $compare_size;
        } else {
            return $current_size;
        }
    }

    private function _calculateSize($products, $size_compare) {
        if(!empty($products)) {
            for ($i = 1;$i <= count($this->parcel_sizes); $i++) {
                $parcel_full = 0;

                foreach ($products as $product) {
                    if (!empty($product['sizes'])) {
                        $parcel_full += $product['quantity'] / $product['sizes'][$size_compare];
                    }
                }

                if ($parcel_full > 1) {
                    $next_size = array_search($size_compare, $this->parcel_sizes) + 1;

                    if (isset($this->parcel_sizes[$next_size])) {
                        $size_compare = $this->parcel_sizes[$next_size];
                    } else {
                        $size_compare = '';
                        break;
                    }
                } else {
                    break;
                }
            }
        }

        return $size_compare;
    }

    //Get all orders by cart id
    public static function getOrdersByCartId($id_cart) {
        $orders_data = array();

        $sql = 'SELECT `id_order`, `id_carrier`
            FROM `' . _DB_PREFIX_ . 'orders`
            WHERE `id_cart` = ' . (int) ($id_cart);
        $results = Db::getInstance()->ExecuteS($sql);

        if ($results) {
            foreach ($results as $result) {
                $orders_data[$result['id_carrier']] = $result['id_order'];
            }
        }
        return $orders_data;
    }

    public static function getProductWeight($product) {
        $product_weight = 0;

        if (!empty($product['id_product_attribute'])) {
            $sql = 'SELECT *
                FROM `' . _DB_PREFIX_ . 'product_attribute`
                WHERE `id_product_attribute` = ' . (int) $product['id_product_attribute'];

            $product_attribute = Db::getInstance()->getRow($sql);

            if (!empty($product_attribute['weight'])) {
                $product_weight = (float) $product_attribute['weight'];
            } else {
                $product_weight = (float) $product['weight'];
            }
        } else {
            $product_weight = (float) $product['weight'];
        }

        return $product_weight;
    }

    public function setSpeedyMethod() {
        $json = array();

        if (Tools::getIsset('method_id') && Tools::getValue('method_id') && Tools::getIsset('method_price')) {
            $_SESSION['speedy']['shipping_method_cost'] = Tools::getValue('method_price');
            $_SESSION['speedy']['shipping_method_text'] = Tools::displayPrice($_SESSION['speedy']['shipping_method_cost'], Context::getContext()->currency);

            $json['price_text'] = $_SESSION['speedy']['shipping_method_text'];
            $_SESSION['speedy']['shipping_method_id'] = Tools::getValue('method_id');
        }

        echo json_encode($json);
        exit;
    }

    public function _getQuotePublic() {
        $quote_data = array();

        $method_data = array();

        if (!empty($_SESSION['speedy'])) {
            if (!empty($_SESSION['speedy']['carrier_ids'])) {
                $carrier_ids = trim(rtrim($_SESSION['speedy']['carrier_ids'], ','));
                $carrier_ids = explode(',', $carrier_ids);
                foreach ($carrier_ids as $carrier_id) {
                    $carr_id = trim((int) $carrier_id);
                    if ($carr_id != Configuration::get('SPEEDY_CARRIER_ID')) {
                        if (isset($carr_cost)) {
                            $carr_cost += Context::getContext()->cart->getPackageShippingCost($carr_id);
                        } else {
                            $carr_cost = Context::getContext()->cart->getPackageShippingCost($carr_id);
                        }
                    }
                }
            }

            $speedy_products = array();
            $data = array();
            $total = 0;
            $weight = 0;
            $totalNoShipping = 0;

            if (isset($carr_cost)) {
                foreach (Context::getContext()->cart->getProducts() as $product) {
                    $new_product = new Product($product['id_product']);
                    foreach ($new_product->getCarriers() as $product_carrier) {
                        if ($product_carrier['id_carrier'] == Configuration::get('SPEEDY_CARRIER_ID')) {
                            $total += $product['total_wt'];

                            if (!ProductDownload::getIdFromIdProduct((int) ($product['id_product']))) {
                                $product_weight = (float) $this->getProductWeight($product);
                                if (!empty($product_weight)) {
                                    $weight += $product_weight * $product['cart_quantity'];
                                } else {
                                    $weight += Configuration::get('SPEEDY_DEFAULT_WEIGHT') * $product['cart_quantity'];
                                }
                            } else {
                                $totalNoShipping += $product['total_wt'];
                            }
                        }
                    }
                }
            } else {
                foreach (Context::getContext()->cart->getProducts() as $product) {
                    $description[] = $product['name'];

                    $total += $product['total_wt'];

                    if (!ProductDownload::getIdFromIdProduct((int) ($product['id_product']))) {
                        $product_weight = (float) $this->getProductWeight($product);
                        if (!empty($product_weight)) {
                            $weight += $product_weight * $product['cart_quantity'];
                        } else {
                            $weight += Configuration::get('SPEEDY_DEFAULT_WEIGHT') * $product['cart_quantity'];
                        }
                    } else {
                        $totalNoShipping += $product['total_wt'];
                    }
                }
            }

            $taxCalculationMethod = Group::getPriceDisplayMethod((int)Group::getCurrent()->id);
            $useTax = !($taxCalculationMethod == PS_TAX_EXC);

            $freeShipping = false;
            $cartRules = Context::getContext()->cart->getCartRules();
            if ($cartRules) {
                foreach ($cartRules as $cartRule) {
                    if (!$cartRule['free_shipping']) {
                        $total -= ($useTax) ? $cartRule['value_real'] : $cartRule['value_tax_exc'];
                    } else {
                        $freeShipping = true;
                    }
                }
            }

            $total = Tools::convertPriceFull($total, Context::getContext()->currency, $this->bg_currency);
            $total = defined(_PS_PRICE_COMPUTE_PRECISION_) ? Tools::ps_round($total, _PS_PRICE_COMPUTE_PRECISION_) : Tools::ps_round($total, 2);
            $totalNoShipping = Tools::convertPriceFull($totalNoShipping, Context::getContext()->currency, $this->bg_currency);

            $totalNoShipping = $total - $totalNoShipping;

            if (Configuration::get('SPEEDY_DOCUMENTS') && (float) $weight > 0.25) {
                $weight = 0.25;
            }

            $_SESSION['speedy']['calculated_currency'] = Context::getContext()->currency->id;
            $_SESSION['speedy']['id_address_delivery'] = Context::getContext()->cart->id_address_delivery;
            $_SESSION['speedy']['total'] = $total;
            $_SESSION['speedy']['totalNoShipping'] = $totalNoShipping;
            $_SESSION['speedy']['weight'] = $weight;
            $_SESSION['speedy']['count'] = 1;
            $_SESSION['speedy']['taking_date'] = (Configuration::get('SPEEDY_TAKING_DATE') ? strtotime('+' . (int) Configuration::get('SPEEDY_TAKING_DATE') . ' day', mktime(9, 0, 0)) : time());
            $_SESSION['speedy']['client_id'] = Configuration::get('SPEEDY_CLIENT_ID');
            $_SESSION['speedy']['convertion_to_win1251'] = Configuration::get('SPEEDY_CONVERTION_TO_WIN1251');

            if (Configuration::get('SPEEDY_PRICING') == 'fixed' || Configuration::get('SPEEDY_PRICING') == 'calculator_fixed') {
                $_SESSION['speedy']['total'] += Configuration::get('SPEEDY_FIXED_PRICE');
            }

            $_SESSION['speedy']['fixed_time'] = null;

            $module_speedypayment = Module::getInstanceByName('speedypayment');
            if (Validate::isLoadedObject($module_speedypayment) && $module_speedypayment->active) {
                $speedypayment = true;
            } else {
                $speedypayment = false;
            }

            if (!$speedypayment) {
                $_SESSION['speedy']['cod'] = false;
            }

            $_SESSION['speedy']['parcels_size'] = array(
                1 => array(
                    'weight' => '',
                    'width'  => '',
                    'height' => '',
                    'depth'  => '',
                )
            );

            $cart_products = Context::getContext()->cart->getProducts();
            $countProducts = 0;
            $parcel_size = $this->parcel_sizes[1];
            $products = array();

            if (empty($_SESSION['speedy']['abroad'])) {
                foreach ($cart_products as $product) {
                    if (!$product['is_virtual']) {
                        $countProducts += $product['quantity'];
                        $sizes = $this->_getSpeedyQuantityDimention($product['id_product'], $product['quantity']);

                        if (!empty($sizes) || $this->_speedyHasQuantityDimention($product['id_product'])) {
                            $sizes['quantity'] = $product['quantity'];
                            $products[] = $sizes;
                            if (!empty($sizes['size'])) {
                                $parcel_size = $this->_compareSizes($parcel_size, $sizes['size']);
                            }
                        } else {
                            $no_parcel_size = true;
                        }
                    }
                }

                $weight_size = $this->_getSpeedyWeightDimention(Context::getContext()->cart->getTotalWeight(), $countProducts);

                if (!empty($products) && empty($no_parcel_size)) {
                    for ($i = 1;$i <= count($this->parcel_sizes); $i++) {
                        $parcel_full = 0;

                        foreach ($products as $product) {
                            if (empty($product['sizes'])) {
                                $parcel_size = '';
                                break 2;
                            }
                            $parcel_full += $product['quantity'] / $product['sizes'][$parcel_size];
                        }

                        if ($parcel_full > 1) {
                            $next_size = array_search($parcel_size, $this->parcel_sizes) + 1;

                            if (isset($this->parcel_sizes[$next_size])) {
                                $parcel_size = $this->parcel_sizes[$next_size];
                            } else {
                                $parcel_size = '';
                                break;
                            }
                        } else {
                            break;
                        }
                    }
                } elseif($weight_size) {
                    $size_compare = $this->_calculateSize($products, $parcel_size);

                        if($size_compare) {
                            $parcel_size = $this->_compareSizes($size_compare, $weight_size);
                        } else {
                            $parcel_size = $weight_size;
                        }
                } elseif(Configuration::get('SPEEDY_MIN_PACKAGE_DIMENTION')) {
                    $size_compare = $this->_calculateSize($products, $parcel_size);

                    if($size_compare) {
                        $parcel_size = $this->_compareSizes($size_compare, Configuration::get('SPEEDY_MIN_PACKAGE_DIMENTION'));
                    } else {
                        $parcel_size = Configuration::get('SPEEDY_MIN_PACKAGE_DIMENTION');
                    }
                } else {
                    $parcel_size = '';
                }
            } else {
                $parcel_size = '';
            }

            $_SESSION['speedy']['parcel_size'] = $parcel_size;

            $methods = $this->speedy->calculate($_SESSION['speedy']);

            $_SESSION['speedy']['default_methods_fixed_time'] = array();

            if (Configuration::get('SPEEDY_FIXED_TIME')) {
                $methods_fixed_time = $this->speedy->calculate(array_merge($_SESSION['speedy'], array('fixed_time' => '1030')));

                foreach ($methods_fixed_time as $method) {
                    if (!$method->getErrorDescription()) {
                        $_SESSION['speedy']['default_methods_fixed_time'][$method->getServiceTypeId()] = $method;
                    }
                }
            }

            $lang = (isset($_SESSION['speedy']['abroad']) && $_SESSION['speedy']['abroad']) ? 'en' : $this->context->language->iso_code;
            $services = $this->speedy->getServices($lang);
            $methods_count = 0;

            if (!$this->speedy->getError()) {
                foreach ($methods as $method) {
                    $error_fixed_time = true;
                    if (Configuration::get('SPEEDY_FIXED_TIME')) {
                        if (isset($_SESSION['speedy']['fixed_time_cb'])) {
                            $method_fixed_time = $this->speedy->calculate(array_merge($_SESSION['speedy'], array('fixed_time' => $_SESSION['speedy']['fixed_time_hour'] . $_SESSION['speedy']['fixed_time_min'])));

                            foreach ($method_fixed_time as $method_fixed_time_value) {
                                if (!$method->getErrorDescription() && $method_fixed_time_value->getServiceTypeId() == $method->getServiceTypeId()) {
                                    $method = $method_fixed_time_value;
                                    $error_fixed_time = false;
                                    break;
                                }
                            }
                        }
                    }

                    $total_form = array();

                    if (!$method->getErrorDescription()) {
                        if ((Configuration::get('SPEEDY_PRICING') == 'free') && ($totalNoShipping >= (float) Configuration::get('SPEEDY_FREE_SHIPPING_TOTAL')) &&
                                ($method->getServiceTypeId() == Configuration::get('SPEEDY_FREE_METHOD_CITY') || $method->getServiceTypeId() == Configuration::get('SPEEDY_FREE_METHOD_INTERCITY') || in_array($method->getServiceTypeId(), unserialize(Configuration::get('SPEEDY_FREE_METHOD_INTERNATIONAL'))))) {
                            $method_total = 0;
                        } elseif (Configuration::get('SPEEDY_PRICING') == 'fixed') {
                            $method_total = Configuration::get('SPEEDY_FIXED_PRICE');
                        } elseif (Configuration::get('SPEEDY_PRICING') == 'table_rate') {
                            $filter_data = array(
                                'service_id' => $method->getServiceTypeId(),
                                'take_from_office' => $_SESSION['speedy']['to_office'],
                                'weight' => $weight,
                                'order_total' => $total,
                            );

                            $speedy_table_rate = $this->_getSpeedyTableRate($filter_data);

                            if (empty($speedy_table_rate)) {
                                continue;
                            } else {
                                $method_total = $speedy_table_rate['price_without_vat'];
                            }
                        } else {
                            $method_total = $method->getResultInfo()->getAmounts()->getTotal();

                            if (Configuration::get('SPEEDY_PRICING') == 'calculator_fixed') {
                                $method_total += Configuration::get('SPEEDY_FIXED_PRICE');
                            }

                            $vat_fixedTimeDelivery = round(0.2 * $method->getResultInfo()->getAmounts()->getFixedTimeDelivery(), 2);
                            $vat_codPremium = round(0.2 * $method->getResultInfo()->getAmounts()->getCodPremium(), 2);

                            $total_form[] = array(
                                'label' => $this->l('Стойност'),
                                'value' => ($freeShipping) ? $this->l('Безплатна') : Tools::displayPrice(Tools::convertPriceFull((float)($method_total - ($method->getResultInfo()->getAmounts()->getCodPremium() + $vat_codPremium) - ($method->getResultInfo()->getAmounts()->getFixedTimeDelivery() + $vat_fixedTimeDelivery)), $this->bg_currency, Context::getContext()->currency))
                            );

                            if (!empty($_SESSION['speedy']['cod'])) {
                                $total_form[] = array(
                                    'label' => $this->l('Комисиона "Нал. платеж"'),
                                    'value' => ($freeShipping) ? $this->l('Безплатна') : Tools::displayPrice(Tools::convertPriceFull((float)$method->getResultInfo()->getAmounts()->getCodPremium() + $vat_codPremium, $this->bg_currency, Context::getContext()->currency))
                                );
                            }

                            $total_form[] = array(
                                'label' => $this->l('Всичко'),
                                'value' => ($freeShipping) ? $this->l('Безплатна') : Tools::displayPrice(Tools::convertPriceFull((float)$method_total, $this->bg_currency, Context::getContext()->currency))
                            );
                        }

                        $method_total = Tools::convertPriceFull((float)$method_total, $this->bg_currency, Context::getContext()->currency);

                        if($method->getServiceTypeId() == 500 && !empty($_SESSION['speedy']['parcel_size'])) { // for SPEEDY POST
                            $method_title = $this->l('Спиди') . ' - ' . $services[$method->getServiceTypeId()] . ' (' . $_SESSION['speedy']['parcel_size'] . ')';
                        } else {
                            $method_title = $this->l('Спиди') . ' - ' . $services[$method->getServiceTypeId()];
                        }

                        $quote_data[] = array(
                            'code' => $method->getServiceTypeId(),
                            'title' => $method_title,
                            'cost' => $method_total,
                            'total_form' => isset($total_form) ? $total_form : array(),
                            'tax_class_id' => 0,
                            'text' => ($freeShipping) ? $this->l('Безплатна') : Tools::displayPrice($method_total, Context::getContext()->currency)
                        );

                        $methods_count++;
                    }
                }

                if ($methods_count) {
                    $method_data['quote'] = $quote_data;
                } elseif (!$methods_count && Configuration::get('SPEEDY_PRICING') == 'table_rate') {
                    $method_data['speedy_error'] = $this->l('За тази поръчка не може да бъде калкулирана цена. Моля обърнете се към администраторите на магазина!');
                } else {
                    $method_data['speedy_error'] = $this->l('Няма налични методи от Спиди за избрания адрес!');
                }
            } else {
                $method_data['speedy_error'] = $this->speedy->getError();
            }
        } else {
            $method_data['speedy_error'] = $this->l('Моля, въведете коректно всички данни и кликнете Изчисли цена след това!');
        }

        if (isset($method_data['speedy_error'])) {
            $method_data['quote'] = array();
        }
        return $method_data;
    }

    private function checkCredentials() {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $username = Tools::getValue('username');

            if (str_replace(array('*', ' '), '', Tools::getValue('password'))) {
                $password = Tools::getValue('password');
            } else {
                $password = Configuration::get('SPEEDY_PASSWORD');
            }

            $isCredentialsCorrect = $this->speedy->checkCredentials($username, $password);

            if ($isCredentialsCorrect) {
                echo json_encode(array('ok' => TRUE));
                exit;
            } else {
                echo json_encode(array('error' => TRUE));
                exit;
            }
        }
    }

    public function _getQuoteAdmin() {
        if (!Tools::getValue('order_id')) {
            return false;
        }

        $speedy_order_info = $this->_getOrder(Tools::getValue('order_id'));
        $speedy_order_data = unserialize($speedy_order_info['data']);

        if (Tools::getIsset('shipping_method_id')) {
            $method_id = Tools::getValue('shipping_method_id');
        } elseif (isset($speedy_order_data['shipping_method_id'])) {
            $method_id = $speedy_order_data['shipping_method_id'];
        } else {
            $method_id = 0;
        }

        $quote_data = array();

        $method_data = array();

        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $total = Tools::getValue('total');
            $totalNoShipping = Tools::getValue('totalNoShipping');

            $weight = Tools::getValue('weight');
            $count = Tools::getValue('count');

            if (Configuration::get('SPEEDY_DOCUMENTS') && (float) $weight > 0.25) {
                $weight = 0.25;
            }

            $data['total'] = $total;
            $data['loading'] = true;

            if (Tools::getValue('insurance')) {
                $data['totalNoShipping'] = $totalNoShipping;
            } else {
                $data['totalNoShipping'] = 0;
            }

            $data['weight'] = $weight;
            $data['count'] = $count;
            $data['taking_date'] = (Configuration::get('SPEEDY_TAKING_DATE') ? strtotime('+' . (int) Configuration::get('SPEEDY_TAKING_DATE') . ' day', mktime(9, 0, 0)) : time());

            $module_speedypayment = Module::getInstanceByName('speedypayment');
            if (Validate::isLoadedObject($module_speedypayment) && $module_speedypayment->active) {
                $speedypayment = true;
            } else {
                $speedypayment = false;
            }

            if (!$speedypayment) {
                $data['cod'] = false;
            }

            $_POST['fixed_time'] = '';

            $_POST['taking_date'] = strtotime($_POST['taking_date']);

            if (!empty($_POST['shipping_method_id']) && $_POST['shipping_method_id'] != 500) {
                unset($_POST['parcel_size']);
            } else {
                foreach ($_POST['parcels_size'] as $key => $parcel_size) {
                    $_POST['parcels_size'][$key]['depth'] = '';
                    $_POST['parcels_size'][$key]['height'] = '';
                    $_POST['parcels_size'][$key]['width'] = '';
                }
            }

            $methods = $this->speedy->calculate(array_merge($data, $_POST));

            $_SESSION['loading_methods_fixed_time'] = array();

            if (Configuration::get('SPEEDY_FIXED_TIME')) {
                $_POST['fixed_time'] = '1030';

                $methods_fixed_time = $this->speedy->calculate(array_merge($data, $_POST));
                foreach ($methods_fixed_time as $method) {
                    if (!$method->getErrorDescription()) {
                        $_SESSION['loading_methods_fixed_time'][$method->getServiceTypeId()] = $method;
                        $_SESSION['loading_methods_fixed_time_serialize'][$method->getServiceTypeId()] = serialize($method);
                    }
                }
            }

            $lang = (isset($data['abroad']) && $data['abroad']) ? 'en' : $this->context->language->iso_code;
            $services = $this->speedy->getServices($lang);
            $methods_count = 0;

            if (!$this->speedy->getError()) {
                foreach ($methods as $method) {
                    $error_fixed_time = true;
                    if (Configuration::get('SPEEDY_FIXED_TIME')) {
                        if (!Tools::getIsset('shipping_method_id') && isset($speedy_order_data['fixed_time_cb']) && isset($_SESSION['loading_methods_fixed_time'])) {
                            $_POST['fixed_time_cb'] = $speedy_order_data['fixed_time_cb'];
                            $_POST['fixed_time_hour'] = $speedy_order_data['fixed_time_hour'];
                            $_POST['fixed_time_min'] = $speedy_order_data['fixed_time_min'];
                        }

                        if (isset($_POST['fixed_time_cb'])) {
                            $_POST['fixed_time'] = $_POST['fixed_time_hour'] . $_POST['fixed_time_min'];
                            $method_fixed_time = $this->speedy->calculate(array_merge($data, $_POST));

                            foreach ($method_fixed_time as $method_fixed_time_value) {
                                if (!$method->getErrorDescription() && $method_fixed_time_value->getServiceTypeId() == $method->getServiceTypeId()) {
                                    $method = $method_fixed_time_value;
                                    $error_fixed_time = false;
                                    break;
                                }
                            }
                        }
                    }

                    $total_form = array();

                    if (!$method->getErrorDescription()) {
                        if ((Configuration::get('SPEEDY_PRICING') == 'free') && ($data['totalNoShipping'] >= (float) Configuration::get('SPEEDY_FREE_SHIPPING_TOTAL')) &&
                                ($method->getServiceTypeId() == Configuration::get('SPEEDY_FREE_METHOD_CITY') || $method->getServiceTypeId() == Configuration::get('SPEEDY_FREE_METHOD_INTERCITY') || in_array($method->getServiceTypeId(), unserialize(Configuration::get('SPEEDY_FREE_METHOD_INTERNATIONAL'))))) {
                            $method_total = 0;
                        } elseif (Configuration::get('SPEEDY_PRICING') == 'fixed') {
                            $method_total = Configuration::get('SPEEDY_FIXED_PRICE');
                        } elseif (Configuration::get('SPEEDY_PRICING') == 'table_rate') {
                            $filter_data = array(
                                'service_id' => $method->getServiceTypeId(),
                                'take_from_office' => $_POST['to_office'],
                                'weight' => $data['weight'],
                                'order_total' => $data['total'],
                                'fixed_time_delivery' => isset($_POST['fixed_time_cb'][$method->getServiceTypeId()]) ? $_POST['fixed_time_cb'][$method->getServiceTypeId()] : 0,
                            );

                            $speedy_table_rate = $this->_getSpeedyTableRate($filter_data);

                            if (empty($speedy_table_rate)) {
                                continue;
                            } else {
                                $method_total = $speedy_table_rate['price_without_vat'];
                            }
                        } else {
                            $method_total = $method->getResultInfo()->getAmounts()->getTotal();

                            if (Configuration::get('SPEEDY_PRICING') == 'calculator_fixed') {
                                $method_total += Configuration::get('SPEEDY_FIXED_PRICE');
                            }

                            $vat_fixedTimeDelivery = round(0.2 * $method->getResultInfo()->getAmounts()->getFixedTimeDelivery(), 2);
                            $vat_codPremium = round(0.2 * $method->getResultInfo()->getAmounts()->getCodPremium(), 2);

                            $total_form[] = array(
                                'label' => $this->l('Стойност'),
                                'value' => Tools::displayPrice((float) ($method_total - ($method->getResultInfo()->getAmounts()->getCodPremium() + $vat_codPremium) - ($method->getResultInfo()->getAmounts()->getFixedTimeDelivery() + $vat_fixedTimeDelivery)), $this->bg_currency->id)
                            );

                            if (Tools::getValue('cod')) {
                                $total_form[] = array(
                                    'label' => $this->l('Комисиона "Нал. платеж"'),
                                    'value' => Tools::displayPrice((float) $method->getResultInfo()->getAmounts()->getCodPremium() + $vat_codPremium, $this->bg_currency->id)
                                );
                            }

                            $total_form[] = array(
                                'label' => $this->l('Всичко'),
                                'value' => Tools::displayPrice((float) $method_total, $this->bg_currency->id)
                            );
                        }

                        if (isset($_POST['fixed_time_cb'])) {
                            $fixed_time_cb = $_POST['fixed_time_cb'];
                        } elseif ($_SERVER['REQUEST_METHOD'] != 'POST' && isset($speedy_order_data['fixed_time_cb'])) {
                            $fixed_time_cb = $speedy_order_data['fixed_time_cb'];
                        } else {
                            $fixed_time_cb = false;
                        }

                        if (isset($_POST['fixed_time_hour'])) {
                            $fixed_time_hour = $_POST['fixed_time_hour'];
                        } elseif (isset($speedy_order_data['fixed_time_hour'])) {
                            $fixed_time_hour = $speedy_order_data['fixed_time_hour'];
                        } else {
                            $fixed_time_hour = '10';
                        }

                        if (isset($_POST['fixed_time_min'])) {
                            $fixed_time_min = $_POST['fixed_time_min'];
                        } elseif (isset($speedy_order_data['fixed_time_min'])) {
                            $fixed_time_min = $speedy_order_data['fixed_time_min'];
                        } else {
                            $fixed_time_min = '30';
                        }

                        $_SESSION['shipping_method_cost'][$method->getServiceTypeId()] = $method_total;
                        $_SESSION['shipping_method_title'][$method->getServiceTypeId()] = $services[$method->getServiceTypeId()];

                        $quote_data[] = array(
                            'code' => $method->getServiceTypeId(),
                            'title' => $this->l('Спиди') . ' - ' . $services[$method->getServiceTypeId()],
                            'cost' => $method_total,
                            'total_form' => isset($total_form) ? $total_form : array(),
                            'fixed_time_cb' => $fixed_time_cb,
                            'fixed_time_hour' => $fixed_time_hour,
                            'fixed_time_min' => $fixed_time_min,
                            'default_fixed_time' => (Configuration::get('SPEEDY_FIXED_TIME') && isset($_SESSION['loading_methods_fixed_time'][$method->getServiceTypeId()]) ? true : false),
                            'error_fixed_time' => ($fixed_time_cb && Configuration::get('SPEEDY_FIXED_TIME') && isset($_SESSION['loading_methods_fixed_time'][$method->getServiceTypeId()]) && $error_fixed_time ? true : false),
                            'tax_class_id' => 0,
                            'text' => Tools::displayPrice($method_total, Context::getContext()->currency)
                        );

                        $methods_count++;
                    }
                }

                if ($methods_count) {
                    unset($quote_data['speedy']);
                    $method_data['quote'] = $quote_data;
                    $method_data['shipping_method_id'] = $method_id;
                } elseif (!$methods_count && Configuration::get('SPEEDY_PRICING') == 'table_rate') {
                    $method_data['speedy_error'] = $this->l('За тази поръчка не може да бъде калкулирана цена. Моля обърнете се към администраторите на магазина!');
                } else {
                    $method_data['speedy_error'] = $this->l('Няма намерени услуги!');
                }
            } else {
                $method_data['speedy_error'] = $this->speedy->getError();
            }
        } else {
            $method_data['speedy_error'] = $this->l('Моля, изчислете цената за доставка отново и при нужда изберете друг метод за доставка!');
        }

        if (isset($method_data['speedy_error'])) {
            $method_data['quote']['speedy']['text'] = '';
        }

        return $method_data;
    }
}

?>