<?php
/**
 * 2007-2023 PrestaShop
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 * @author    PrestaShop SA <contact@prestashop.com>
 * @copyright 2007-2023 PrestaShop SA
 * @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PrestaShop SA
 */
if (!defined('_PS_VERSION_')) {
    exit;
}

use PrestaShop\Module\AgileMultisellerPro\Controller\Front\AgileModuleFrontController;
use PrestaShop\Module\AgileMultisellerPro\Controller\Front\Traits\SellerTrait;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoDelivery;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoLocationCarrier;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoRange;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoShipping;
use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\DataConfiguration;

class AgileMultiSellerProSellerShippingModuleFrontController extends AgileModuleFrontController
{
    use SellerTrait;

    public function setMedia()
    {
        parent::setMedia();

        Media::addJsDef([
            'idSellerInfo' => $this->sellerinfo->getIdSellerinfo(),
            'ajaxSellerShippingUrl' => Context::getContext()->link->getModuleLink(
                $this->module->name,
                'sellershipping',
                ['ajax' => true]
            ),
        ]);

        $this->registerJavascript(
            'agile_sellershipping',
            '/modules/agilemultisellerpro/views/js/sellershipping.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerStylesheet(
            'agilemultisellerpro-shipping',
            '/modules/agilemultisellerpro/views/css/shipping.seller.css',
            ['media' => 'all', 'priority' => 100]
        );
    }

    public function initContent()
    {
        parent::initContent();

        $this->context->smarty->assign([
            'seller_tab_id' => 6,
            'languages' => Language::getLanguages(true),
        ]);

        if (Tools::isSubmit('submitCarrierRanges')) {
            $this->setSellerRanges();
        }

        if (Tools::isSubmit('id_location_carrier') || Tools::isSubmit('submitCarrierLocation')) {
            $this->initLocation();

            return;
        } elseif (Tools::isSubmit('id_carrier_reference')) {
            $idCarrierReference = (int) Tools::getValue('id_carrier_reference');

            Media::addJsDef([
                'editCarrier' => true,
                'string_price' => $this->trans(
                    'When price',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'string_weight' => $this->trans(
                    'When weight',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'PS_WEIGHT_UNIT' => Configuration::get('PS_WEIGHT_UNIT'),
                'currency_sign' => $this->context->currency->sign,
                'labelDelete' => $this->trans(
                    'Delete',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'need_to_validate' => $this->trans(
                    'Please validate the last range before creating a new one.',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'delete_range_confirm' => $this->trans(
                    'Are you sure to delete this range ?',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'invalid_range' => $this->trans(
                    'This range is not valid',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'range_is_overlapping' => $this->trans(
                    'Ranges are overlapping',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
                'overlapping_range' => $this->trans(
                    'Ranges are overlapping',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),

                'idCarrierReference' => $idCarrierReference,
                'delete_location' => $this->trans(
                    'Are you sure to delete this location?',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                ),
            ]);

            if ($this->setRangesTplValues($idCarrierReference)) {
                $this->serLocationsTplValue($idCarrierReference);
                $this->setTemplate('module:agilemultisellerpro/views/templates/front/shipping/zoneranges.tpl');

                return;
            }
        }

        $this->addCarriersListSmartyVariables();

        $this->setTemplate('module:agilemultisellerpro/views/templates/front/shipping/sellershipping.tpl');
    }

    public function displayAjaxSetSellerCarrier()
    {
        $sellerinfoShipping = $this->entityManager->getRepository(SellerinfoShipping::class);

        $idSellerInfo = isset(Tools::getValue('requestData')['idSellerInfo']) ?
            (int) Tools::getValue('requestData')['idSellerInfo'] : false;

        $idCarrierReference = isset(Tools::getValue('requestData')['idCarrierReference']) ?
            (int) Tools::getValue('requestData')['idCarrierReference'] : false;

        $active = isset(Tools::getValue('requestData')['active']) ?
            (bool) Tools::getValue('requestData')['active'] : null;

        if (!$idSellerInfo || !$idCarrierReference || $active === null) {
            $this->ajaxRender(json_encode([
                'success' => false,
                'message' => $this->trans('Error - not valid data.', [], 'Modules.Agilemultisellerpro.Shipping'),
                'requestData' => Tools::getAllValues(),
            ]));

            return false;
        }

        $carrier = Carrier::getCarrierByReference($idCarrierReference);

        $shipping = $sellerinfoShipping->findOneBy([
            'idSellerInfo' => $idSellerInfo,
            'idCarrierReference' => $idCarrierReference,
        ]);

        if (!$shipping) {
            $shipping = new SellerinfoShipping();
            $shipping->setIdSellerInfo($idSellerInfo);
            $shipping->setIdCarrierReference($idCarrierReference);
            $shipping->setIsFree($carrier->is_free);
            $shipping->setidShippingMethod($carrier->shipping_method);
        }

        $shipping->setActive($active);

        try {
            $this->entityManager->persist($shipping);
            $this->entityManager->flush();
        } catch (Exception $e) {
            $this->ajaxRender(json_encode([
                'success' => false,
                'message' => $this->trans('Error - on database update.', [], 'Modules.Agilemultisellerpro.Shipping'),
                'error' => $e,
                'requestData' => Tools::getAllValues(),
            ]));

            return false;
        }

        $this->ajaxRender(json_encode([
            'success' => true,
            'message' => $this->trans('Status successfully changed.', [], 'Modules.Agilemultisellerpro.Shipping'),
            'requestData' => Tools::getAllValues(),
        ]));
    }

    private function addCarriersListSmartyVariables()
    {
        $sellerinfoShippingRepository = $this->entityManager->getRepository(SellerinfoShipping::class);

        $carriers = Carrier::getCarriers($this->context->language->id, true);

        foreach ($carriers as $key => $carrier) {
            if ($carrier['id_reference'] == Configuration::get('AGILE_DEFAULT_CARRIER_REFERENCE_ID')) {
                unset($carriers[$key]);
                continue;
            }

            $carriers[$key]['active_for_seller'] = $sellerinfoShippingRepository->getSellerCarrierStatus(
                $this->sellerinfo->getIdSellerinfo(),
                $carrier['id_reference']
            );

            $sellerFreeShippingStatus = $sellerinfoShippingRepository->getFreeShippingStatus(
                $this->sellerinfo->getIdSellerinfo(),
                $carrier['id_reference']
            );

            if ($sellerFreeShippingStatus !== null) {
                $carriers[$key]['is_free'] = $sellerFreeShippingStatus;
            }

            $logoFileName = $carrier['id_carrier'] . '.jpg';
            $carriers[$key]['logo_url'] = file_exists(_PS_SHIP_IMG_DIR_ . $logoFileName) ?
                _THEME_SHIP_DIR_ . $logoFileName : false;
        }

        $this->context->smarty->assign([
            'carriers' => $carriers,
            'sellerCarrierEditUrl' => Context::getContext()->link->getModuleLink(
                $this->module->name,
                'sellershipping',
                ['id_carrier_reference' => '']
            ),
        ]);
    }

    protected function setRangesTplValues($idCarrierReference, $shipping_method = null, $idSellerInfo = null)
    {
        if (!$idSellerInfo) {
            $idSellerInfo = $this->sellerinfo->getIdSellerinfo();
        }

        $sellerinfoShippingRepository = $this->entityManager->getRepository(SellerinfoShipping::class);
        $sellerinfoDeliveryRepository = $this->entityManager->getRepository(SellerinfoDelivery::class);

        $shipping = $sellerinfoShippingRepository->findOneBy([
            'idSellerInfo' => $idSellerInfo,
            'idCarrierReference' => $idCarrierReference,
        ]);

        if (!$shipping) {
            $carrierByReference = Carrier::getCarrierByReference($idCarrierReference);

            if ($carrierByReference) {
                $shipping = new SellerinfoShipping();
                $shipping->setIdSellerInfo($idSellerInfo);
                $shipping->setIdCarrierReference($idCarrierReference);
                $shipping->setIsFree($carrierByReference->is_free);
                $shipping->setidShippingMethod($carrierByReference->shipping_method);
                $shipping->setActive(false);

                $this->entityManager->persist($shipping);
                $this->entityManager->flush();
            } else {
                $this->errors[] = $this->trans(
                    'Error - the carrier does not exist.',
                    [],
                    'Modules.Agilemultisellerpro.Shipping'
                );

                return false;
            }
        }

        if (!$shipping_method) {
            $shipping_method = $shipping->getIdShippingMethod();
        }

        $deliveriesSearchParams = [
            'idSellerinfo' => $idSellerInfo,
            'idCarrierReference' => $idCarrierReference,
            'idShippingMethod' => $shipping_method,
        ];

        if ($shipping_method) {
            $deliveriesSearchParams['idShippingMethod'] = $shipping_method;
        } else {
            $deliveriesSearchParams['idShippingMethod'] = $shipping->getIdShippingMethod();
        }

        $deliveries = $sellerinfoDeliveryRepository->findBy($deliveriesSearchParams);

        $tpl_vars = [];
        $tpl_vars['PS_WEIGHT_UNIT'] = Configuration::get('PS_WEIGHT_UNIT');
        $tpl_vars['zones'] = Zone::getZones(false, true);

        $fields_value['zones'] = [];

        $carrier = Carrier::getCarrierByReference($idCarrierReference);

        $carrier_zones_ids = [];
        if (!empty($deliveries)) {
            foreach ($deliveries as $delivery) {
                $carrier_zones_ids[] = $delivery->getIdRangeZone();

                $tpl_vars['price_by_range'][$delivery->getIdSellerinfoRange()][$delivery->getIdRangeZone()] =
                    $delivery->getPrice();
            }

            $carrier_zones_ids = array_unique($carrier_zones_ids);

            $sellerinfoRangeRepository = $this->entityManager->getRepository(SellerinfoRange::class);

            $rangesBySeller = $sellerinfoRangeRepository->findBy($deliveriesSearchParams);

            foreach ($rangesBySeller as $sellerRange) {
                $tpl_vars['ranges'][] = [
                    'id_range' => $sellerRange->getIdSellerinfoRange(),
                    'delimiter1' => $sellerRange->getDelimiter1(),
                    'delimiter2' => $sellerRange->getDelimiter2(),
                ];
            }
        } else {
            $carrier_zones = $carrier->getZones();

            if (is_array($carrier_zones)) {
                foreach ($carrier_zones as $carrier_zone) {
                    $carrier_zones_ids[] = $carrier_zone['id_zone'];
                }
            }

            if ($carrier->is_free == true) {
                $shipping_method = Carrier::SHIPPING_METHOD_FREE;
            }

            if ($shipping_method === null) {
                $shipping_method = $carrier->getShippingMethod();
            }

            $range_table = $carrier->getRangeTable();

            if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) {
                $range_obj = $carrier->getRangeObject($carrier->shipping_method);
                $price_by_range = [];
            } else {
                $range_obj = $carrier->getRangeObject();
                $price_by_range = Carrier::getDeliveryPriceByRanges($range_table, (int) $carrier->id);
            }

            foreach ($price_by_range as $price) {
                $tpl_vars['price_by_range'][$price['id_' . $range_table]][$price['id_zone']] = $price['price'];
            }

            $tmp_range = $range_obj->getRanges((int) $carrier->id);

            $tpl_vars['ranges'] = [];
            if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) {
                foreach ($tmp_range as $id => $range) {
                    $tpl_vars['ranges'][$range['id_' . $range_table]] = $range;
                    $tpl_vars['ranges'][$range['id_' . $range_table]]['id_range'] = $range['id_' . $range_table];
                }
            }

            $range_table = $carrier->getRangeTable();

            if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) {
                $range_obj = $carrier->getRangeObject($carrier->shipping_method);
                $price_by_range = [];
            } else {
                $range_obj = $carrier->getRangeObject();
                $price_by_range = Carrier::getDeliveryPriceByRanges($range_table, (int) $carrier->id);
            }

            foreach ($price_by_range as $price) {
                $tpl_vars['price_by_range'][$price['id_' . $range_table]][$price['id_zone']] = $price['price'];
            }

            $tmp_range = $range_obj->getRanges((int) $carrier->id);

            $tpl_vars['ranges'] = [];
            if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) {
                foreach ($tmp_range as $id => $range) {
                    $tpl_vars['ranges'][$range['id_' . $range_table]] = $range;
                    $tpl_vars['ranges'][$range['id_' . $range_table]]['id_range'] = $range['id_' . $range_table];
                }
            }

            $shipping_method = $carrier->getShippingMethod();
        }

        $zones = Zone::getZones(false);
        foreach ($zones as $zone) {
            $fields_value['zones'][$zone['id_zone']] = Tools::getValue(
                'zone_' . $zone['id_zone'],
                in_array($zone['id_zone'], $carrier_zones_ids)
            );
        }

        // init blank range
        if (!isset($tpl_vars['ranges']) || !count($tpl_vars['ranges'])) {
            $tpl_vars['ranges'][] = ['id_range' => 0, 'delimiter1' => 0, 'delimiter2' => 0];
        }

        $range_behavior = $carrier->range_behavior == 0
            ? $this->trans('Apply the cost of the highest defined range', [], 'Modules.Agilemultisellerpro.Shipping')
            : $this->trans('Disable carrier', [], 'Modules.Agilemultisellerpro.Shipping');

        $id_tax_rules_group = (is_object($carrier) && !$carrier->id) ? Carrier::getIdTaxRulesGroupMostUsed() : Carrier::getIdTaxRulesGroupByIdCarrier($carrier->id);

        $taxRulesGroup = new TaxRulesGroup($id_tax_rules_group);

        $defaultCurrency = Currency::getDefaultCurrency();

        $this->context->smarty->assign('currency_sign', $defaultCurrency->sign);

        $this->context->smarty->assign($tpl_vars);

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

        $this->context->smarty->assign([
            'zones' => $zones,
            'sellerCarrierListUrl' => Context::getContext()->link->getModuleLink(
                $this->module->name,
                'sellershipping'
            ),
            'tax_rules_group_name' => $taxRulesGroup->name,
            'range_behavior' => $range_behavior,
            'isFree' => $shipping->getIsFree(),
            'shipping_method' => $shipping_method,
        ]);

        return true;
    }

    public function displayAjaxGetTableRanges()
    {
        $idCarrierReference = isset(Tools::getValue('requestData')['idCarrierReference']) ?
            (int) Tools::getValue('requestData')['idCarrierReference'] : false;

        $shipping_method = isset(Tools::getValue('requestData')['shipping_method']) ?
            (int) Tools::getValue('requestData')['shipping_method'] : null;

        if (!$idCarrierReference || !$shipping_method) {
            $this->ajaxRender(json_encode([
                'success' => false,
                'message' => $this->trans('Error - not valid data.', [], 'Modules.Agilemultisellerpro.Shipping'),
                'requestData' => Tools::getAllValues(),
            ]));

            return false;
        }

        $this->setRangesTplValues($idCarrierReference, $shipping_method);

        $rangesTable = $this->context->smarty->fetch('module:agilemultisellerpro/views/templates/front/shipping/rangestable.tpl');

        $this->ajaxRender(json_encode([
            'success' => true,
            'data' => $rangesTable,
            'message' => $this->trans('Ok', [], 'Modules.Agilemultisellerpro.Shipping'),
            'requestData' => Tools::getAllValues(),
        ]));
    }

    public function setSellerRanges()
    {
        $idSellerInfo = $this->sellerinfo->getIdSellerinfo();
        $idCarrierReference = Tools::getValue('id_carrier_reference');
        $fees = Tools::getValue('fees');
        $range_inf = Tools::getValue('range_inf');
        $range_sup = Tools::getValue('range_sup');
        $shipping_method = Tools::getValue('shipping_method');
        $isFree = Tools::getValue('is_free');
        $zones = Tools::getValue('zones');

        if (!$idSellerInfo || !$idCarrierReference || !$shipping_method) {
            $this->errors[] = $this->trans(
                'Error - invalid data.',
                [],
                'Modules.Agilemultisellerpro.Shipping'
            );

            return false;
        }

        $sellerinfoShippingRepository = $this->entityManager->getRepository(SellerinfoShipping::class);
        $sellerinfoDeliveryRepository = $this->entityManager->getRepository(SellerinfoDelivery::class);
        $sellerinfoRangeRepository = $this->entityManager->getRepository(SellerinfoRange::class);

        $shipping = $sellerinfoShippingRepository->findOneBy([
            'idSellerInfo' => $idSellerInfo,
            'idCarrierReference' => $idCarrierReference,
        ]);

        if (!$shipping) {
            $this->errors[] = $this->trans(
                'Error - seller carrier not found.',
                [],
                'Modules.Agilemultisellerpro.Shipping'
            );

            return false;
        }

        $shipping->setIsFree($isFree);
        $shipping->setIdShippingMethod($shipping_method);

        $this->entityManager->persist($shipping);
        $this->entityManager->flush();

        $deliveriesToDelete = $sellerinfoDeliveryRepository->findBy([
            'idSellerinfo' => $idSellerInfo,
            'idCarrierReference' => $idCarrierReference,
        ]);

        foreach ($deliveriesToDelete as $delivery) {
            $this->entityManager->remove($delivery);
        }

        $rangesToDelete = $sellerinfoRangeRepository->findBy([
            'idSellerinfo' => $idSellerInfo,
            'idCarrierReference' => $idCarrierReference,
        ]);

        foreach ($rangesToDelete as $range) {
            $this->entityManager->remove($range);
        }

        $this->entityManager->flush();

        if ($fees && $range_inf && $range_sup) {
            foreach ($range_inf as $rangeIndex => $delimiter1) {
                $sellerinfoRange[$rangeIndex] = new SellerinfoRange();
                $sellerinfoRange[$rangeIndex]->setIdSellerinfo($idSellerInfo);
                $sellerinfoRange[$rangeIndex]->setIdCarrierReference($idCarrierReference);
                $sellerinfoRange[$rangeIndex]->setIdShippingMethod($shipping_method);
                $sellerinfoRange[$rangeIndex]->setDelimiter1($delimiter1);
                $sellerinfoRange[$rangeIndex]->setDelimiter2($range_sup[$rangeIndex]);

                $this->entityManager->persist($sellerinfoRange[$rangeIndex]);
            }

            $this->entityManager->flush();

            foreach ($fees as $zone => $val) {
                if (!isset($zones[$zone]) || $zones[$zone] != 1) {
                    continue;
                }
                foreach ($val as $rangeIndex => $fee) {
                    $sellerinfoDelivery = new SellerinfoDelivery();

                    $sellerinfoDelivery->setIdSellerinfo($idSellerInfo);
                    $sellerinfoDelivery->setIdCarrierReference($idCarrierReference);
                    $sellerinfoDelivery->setIdShippingMethod($shipping_method);
                    $sellerinfoDelivery->setIdRangeZone($zone);
                    $sellerinfoDelivery->setIdSellerinfoRange($sellerinfoRange[$rangeIndex]->getIdSellerinfoRange());
                    $sellerinfoDelivery->setPrice($fee);

                    $this->entityManager->persist($sellerinfoDelivery);
                }
            }
        } else {
            foreach ($zones as $zone => $val) {
                if ($val != true) {
                    continue;
                }

                $sellerinfoDelivery = new SellerinfoDelivery();

                $sellerinfoDelivery->setIdSellerinfo($idSellerInfo);
                $sellerinfoDelivery->setIdCarrierReference($idCarrierReference);
                $sellerinfoDelivery->setIdShippingMethod($shipping_method);
                $sellerinfoDelivery->setIdRangeZone($zone);
                $sellerinfoDelivery->setIdSellerinfoRange(null);
                $sellerinfoDelivery->setPrice(0);

                $this->entityManager->persist($sellerinfoDelivery);
            }
        }

        $this->entityManager->flush();
    }

    protected function serLocationsTplValue($idCarrierReference)
    {
        $locations = $this->entityManager->getRepository(SellerinfoLocationCarrier::class)
            ->findBy([
                'sellerInfo' => $this->sellerinfo,
                'idCarrierReference' => $idCarrierReference,
                'deleted' => false,
            ]);

        $this->assignCountries();

        $this->context->smarty->assign([
            'idCarrierReference' => $idCarrierReference,
            'locations' => $locations,
            'countries' => $this->getAllCountries(),
        ]);
    }

    private function getAllCountries($isIso = false)
    {
        $countries = [];

        foreach (Country::getCountries($this->context->language->id, true) as $country) {
            if (true === $isIso) {
                $countries[$country['iso_code']] = (int) $country['id_country'];
            } else {
                $countries[$country['id_country']] = $country['name'];
            }
        }

        return $countries;
    }

    protected function initLocation()
    {
        $isRedirect = false;

        $location = $this->entityManager->getRepository(SellerinfoLocationCarrier::class)
            ->findOneBy([
                'idLocationCarrier' => (int) Tools::getValue('id_location_carrier'),
                'sellerInfo' => $this->sellerinfo,
                'deleted' => false,
            ]);

        if (!$location) {
            $location = new SellerinfoLocationCarrier();
            $location->setIdCarrierReference((int) Tools::getValue('id_carrier_reference'));
        }

        if (Tools::isSubmit('submitCarrierLocation')) {
            if (true === $this->saveLocation($location)) {
                $isRedirect = true;
            }
        } elseif (Tools::isSubmit('action')) {
            switch (Tools::getValue('action')) {
                case 'active':
                    $location->setActive(true);
                    break;
                case 'inactive':
                    $location->setActive(false);
                    break;
                case 'delete':
                    $location->setDeleted(true);
                    break;
            }

            $this->entityManager->persist($location);
            $this->entityManager->flush();

            $isRedirect = true;
        }

        if (true === $isRedirect) {
            Tools::redirect(
                $this->context->link->getModuleLink(
                    $this->module->name,
                    'sellershipping',
                    ['id_carrier_reference' => $location->getIdCarrierReference()]
                )
            );
        }

        $this->setLocationMedia($location);

        $this->context->smarty->assign([
            'location' => $location,
            'countries' => $this->getAllCountries(),
            'carriers' => $this->getAllCarriers(),
            'sellerCarrierListUrl' => $this->context->link->getModuleLink(
                $this->module->name,
                'sellershipping',
            ),
        ]);

        $this->setTemplate('module:agilemultisellerpro/views/templates/front/shipping/location_form.tpl');
    }

    protected function setLocationMedia($location)
    {
        $isMap = false;

        if (
            Configuration::get(DataConfiguration::AGILE_MS_GMAP)
            && Configuration::get(DataConfiguration::AGILE_MS_GMAP_KEY)
        ) {
            $this->registerJavascript(
                'agile_gmap_class',
                '/modules/agilemultisellerpro/views/js/agile.gmap.class.js',
                ['position' => 'bottom', 'priority' => 100]
            );

            $this->registerJavascript(
                'agile_gmap',
                '/modules/agilemultisellerpro/views/js/front/gmap.js',
                ['position' => 'bottom', 'priority' => 100]
            );

            $this->registerJavascript(
                'agile_statememneger',
                '/modules/agilemultisellerpro/views/js/AgileStatesManagement.js',
                ['position' => 'bottom', 'priority' => 100]
            );

            Media::addJsDef([
                'agileGmapKey' => Configuration::get(DataConfiguration::AGILE_MS_GMAP_KEY),
                'agileCountries' => $this->getCountries(),
                'curentIsoCode' => $this->context->language->iso_code,
            ]);

            $isMap = true;
        }

        Media::addJsDef([
            'idSelectedState' => $location->getIdState(),
            'idSelectedCountry' => $location->getIdCountry(),
        ]);

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

    private function getAllCarriers()
    {
        $result = [];

        $sellerinfoShippingRepository = $this->entityManager->getRepository(SellerinfoShipping::class);

        $carriers = Carrier::getCarriers($this->context->language->id, true);

        foreach ($carriers as $key => $carrier) {
            if ($carrier['id_reference'] == Configuration::get('AGILE_DEFAULT_CARRIER_REFERENCE_ID')) {
                unset($carriers[$key]);
                continue;
            }
            if ($sellerinfoShippingRepository->getSellerCarrierStatus(
                $this->sellerinfo->getIdSellerinfo(),
                $carrier['id_reference']
            )) {
                $result[(int) $carrier['id_reference']] = $carrier['name'];
            }
        }

        return $result;
    }

    protected function saveLocation($location)
    {
        $location->setSellerinfo($this->sellerinfo)
            ->setActive((bool) Tools::getValue('active'))
            ->setIdCarrierReference((int) Tools::getValue('id_carrier_reference'))
            ->setLocation(Tools::getValue('location'))
            ->setEmail(Tools::getValue('email'))
            ->setAddress1(Tools::getValue('address1'))
            ->setAddress2(Tools::getValue('address2'))
            ->setCity(Tools::getValue('city'))
            ->setPostcode(Tools::getValue('postcode'))
            ->setIdCountry((int) Tools::getValue('id_country'))
            ->setIdState((int) Tools::getValue('id_state'))
            ->setPhone(Tools::getValue('phone'))
            ->setDescription(Tools::getValue('description'))
            ->setLatitude((float) Tools::getValue('latitude'))
            ->setLongitude((float) Tools::getValue('longitude'))
        ;

        if (true === $this->validateLocation($location)) {
            $this->entityManager->persist($location);
            $this->entityManager->flush();

            return true;
        }

        return false;
    }

    protected function validateLocation($location)
    {
        $isValidate = true;
        $errorFields = [];

        if (!Validate::isUnsignedId($location->getIdCarrierReference())) {
            $errorFields['id_carrier_reference'] = $this->trans('Carrier - is required.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isCleanHtml($location->getLocation())) {
            $errorFields['location'] = $this->trans('Location is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isEmail($location->getEmail())) {
            $errorFields['email'] = $this->trans('Email is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isAddress($location->getAddress1())) {
            $errorFields['address1'] = $this->trans('Address is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isAddress($location->getAddress2())) {
            $errorFields['address2'] = $this->trans('Address (Line 2) is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isCityName($location->getCity())) {
            $errorFields['city'] = $this->trans('City is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!($country = new Country($location->getIdCountry())) || Validate::isLoadedObject($country)) {
            $errorFields['country'] = $this->trans('Country cannot be loaded with country', [], 'Modules.Agilemultisellerpro.Location');
        }

        if ((int) $country->contains_states && !$location->getIdState()) {
            $errorFields['id_state'] = $this->trans('This country requires a state selection.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if ($country->need_zip_code) {
            if (false === $country->checkZipCode($location->getPostcode())) {
                $errorFields['postcode'] = $this->trans('Zip / Postal code', [], 'Modules.Agilemultisellerpro.Location') . ' '
                    . $this->trans('is invalid.', [], 'Modules.Agilemultisellerpro.Location') . ' '
                    . $this->trans('Must be typed as follows:', [], 'Modules.Agilemultisellerpro.Location') . ' '
                    . str_replace(
                        'C',
                        $country->iso_code,
                        str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))
                    );
            }
        }

        if (!Validate::isPhoneNumber($location->getPhone())) {
            $errorFields['phone'] = $this->trans('Phone is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isCleanHtml($location->getDescription())) {
            $errorFields['description'] = $this->trans('Description is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isFloat($location->getLatitude())) {
            $errorFields['latitude'] = $this->trans('Latitude is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

        if (!Validate::isFloat($location->getLongitude())) {
            $errorFields['longitude'] = $this->trans('Longitude is invalid.', [], 'Modules.Agilemultisellerpro.Location');
        }

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

        return $isValidate;
    }

    public function displayAjaxGetLocationStates()
    {
        $idCountry = isset(Tools::getValue('requestData')['id_country']) ?
            (int) Tools::getValue('requestData')['id_country'] : 0;

        $country = new Country($idCountry, $this->context->language->id, $this->context->shop->id);

        if (!Validate::isLoadedObject($country)) {
            return $this->ajaxRender(
                json_encode([
                    'success' => false,
                    'message' => $this->trans('Wrong country id', [], 'Modules.Agilemultisellerpro.Shipping'),
                ])
            );
        }

        if ($country->contains_states) {
            $states = State::getStatesByIdCountry($country->id, true, 'name', 'asc');
            return $this->ajaxRender(
                json_encode([
                    'success' => true,
                    'displayState' => true,
                    'states' => $states,
                ])
            );
        }

        $this->ajaxRender(json_encode([
            'success' => true,
            'displayState' => false,
        ]));
    }
}
