<?php
/*
 * @package    ECLCDEK shipping plugin СДЭК to RadicalMart
 * @subpackage    ECLCDEK
 * @version    1.0.1
 * @author Econsult Lab.
 * @copyright  Copyright (c) 2025 Econsult Lab. All rights reserved.
 * @license    GNU/GPL license: https://www.gnu.org/copyleft/gpl.html
 * @link       https://econsultlab.ru
 */

namespace Joomla\Plugin\RadicalMartShipping\ECLCDEK\Extension;

defined('_JEXEC') or die;

use CdekSDK2\BaseTypes\Location;
use CdekSDK2\BaseTypes\Package;
use CdekSDK2\Dto\Region;
use CdekSDK2\Exceptions\AuthException;
use CdekSDK2\Exceptions\RequestException;
use Exception;
use JetBrains\PhpStorm\NoReturn;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Event\Plugin\AjaxEvent;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\WebAsset\WebAssetManager;
use Joomla\Component\RadicalMart\Administrator\Helper\PriceHelper as RadicalMartPriceHelper;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Event\SubscriberInterface;
use Joomla\Input\Input;
use Joomla\Plugin\RadicalMartShipping\ECLCDEK\CDEK\ECLTariffList;
use Joomla\Plugin\RadicalMartShipping\ECLCDEK\Helper\CDEKClientHelper;
use Joomla\Plugin\RadicalMartShipping\ECLCDEK\Helper\ECLCDEKHelper;
use Joomla\Registry\Registry;

require_once JPATH_PLUGINS . '/radicalmart_shipping/eclcdek/vendor/autoload.php';

class ECLCDEK extends CMSPlugin implements SubscriberInterface
{
	use DatabaseAwareTrait;

	/**
	 * Load the language file on instantiation.
	 *
	 * @var    bool
	 *
	 * @since  1.0.0
	 */
	protected $autoloadLanguage = true;

	/**
	 * Loads the application object.
	 *
	 * @var  CMSApplication
	 *
	 * @since  1.0.0
	 */
	protected $app = null;

	/**
	 * Enable on RadicalMart
	 *
	 * @var  bool
	 *
	 * @since  1.0.0
	 */
	public bool $radicalmart = true;

	/**
	 * Enable on RadicalMartExpress
	 *
	 * @var  bool
	 *
	 * @since  1.0.0
	 */
	public bool $radicalmart_express = true;

	/**
	 * Default shipping fields params.
	 *
	 * @var array|string[]
	 *
	 * @since 1.0.0
	 */
	public static array $defaultFieldsParams = [
		'country'   => 'required',
		'region'    => 'not_required',
		'city'      => 'required',
		'zip'       => 'required',
		'street'    => 'required',
		'house'     => 'required',
		'building'  => 'not_required',
		'entrance'  => 'not_required',
		'floor'     => 'not_required',
		'apartment' => 'not_required',
		'comment'   => 'not_required',
		'address'   => 'not_required'
	];

	/**
	 * @inheritDoc
	 * @return string[]
	 *
	 * @since 1.0.0
	 */
	public static function getSubscribedEvents(): array
	{
		return [
			'onAjaxEclcdek'                           => 'onAjaxECLCDEK',
			'onBeforeRender'                          => 'onBeforeRender',
			'onRadicalMartPrepareMethodForm'          => 'onRadicalMartPrepareMethodForm',
			'onRadicalMartNormaliseRequestData'       => 'onRadicalMartNormaliseRequestData',
			'onRadicalMartGetOrderShipping'           => 'onRadicalMartGetOrderShipping',
			'onRadicalMartGetOrderShippingMethods'    => 'onGetOrderShippingMethods',
			'onRadicalMartGetOrderForm'               => 'onGetOrderForm',
			'onRadicalMartLoadOrderMethodFormData'    => 'onLoadOrderMethodFormData',
			'onRadicalMartPrepareOrderMethodSaveData' => 'onPrepareOrderMethodSaveData',
			'onRadicalMartGetOrderTotal'              => 'onGetOrderTotal',
			'onRadicalMartGetOrderCustomerUpdateData' => 'onGetOrderCustomerUpdateData',
			'onRadicalMartGetCheckoutCustomerData'    => 'onGetCheckoutCustomerData',
			'onRadicalMartGetCustomerMethodForm'      => 'onGetCustomerMethodForm',
			'onRadicalMartGetPersonalShippingMethods' => 'onGetPersonalShippingMethods',
			'onRadicalMartGetPersonalMethodForm'      => 'onGetCustomerMethodForm',

//			'onRadicalMartExpressGetOrderShipping'           => 'onRadicalMartExpressGetOrderShipping',
//			'onRadicalMartExpressLoadOrderMethodFormData'    => 'onLoadOrderMethodFormData',
//			'onRadicalMartExpressPrepareOrderMethodSaveData' => 'onPrepareOrderMethodSaveData',
//			'onRadicalMartExpressGetOrderForm'               => 'onGetOrderForm',
//			'onRadicalMartExpressGetOrderShippingMethods'    => 'onGetOrderShippingMethods',
//			'onRadicalMartExpressGetOrderTotal'              => 'onGetOrderTotal',
//			'onRadicalMartExpressGetOrderCustomerUpdateData' => 'onGetOrderCustomerUpdateData',
//			'onRadicalMartExpressGetCheckoutCustomerData'    => 'onGetCheckoutCustomerData',
//			'onRadicalMartExpressGetCustomerMethodForm'      => 'onGetCustomerMethodForm',
//			'onRadicalMartExpressGetPersonalShippingMethods' => 'onGetPersonalShippingMethods',
//			'onRadicalMartExpressGetPersonalMethodForm'      => 'onGetCustomerMethodForm',
		];
	}

	/**
	 * Обработка события onBeforeRender
	 *
	 * @since 1.0.1
	 */
	public function onBeforeRender(): void
	{
		if ($this->app->isClient('site')
			&& $this->app->input->getCmd('option') === 'com_radicalmart'
			&& $this->app->input->getCmd('view') === 'checkout')
		{
			// Оформление заказа, грузим скрипты плагина
			/** @var WebAssetManager $assets */
			$wa = $this->app->getDocument()->getWebAssetManager();
			$wr = $wa->getRegistry();
			$wr->addRegistryFile('/media/plg_radicalmart_shipping_eclcdek/joomla.assets.json');
			$wa->useScript('eclcdek.widget');
			$wa->useScript('eclcdek.front-order');
			$wa->useStyle('eclcdek.front');
			if ($this->autoloadLanguage)
				$this->loadLanguage();
			Text::script("JSELECT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_COUNTRY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_TO_CITY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_ADDRESS");
			Text::script('PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_MESSAGE_TEXT');
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_OFFICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_DOOR");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_PRICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_TIME");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_OFFICE_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_DOOR_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_TARIFFS_TITLE");
		}
	}

	/**
	 * Prepare RadicalMart method prices data.
	 *
	 * @param   string  $context  Context selector string.
	 * @param   object  $objData  Form data object.
	 * @param   Form    $form     The form object.
	 *
	 * @throws \Exception
	 *
	 * @since 1.0.0
	 */
	public function onRadicalMartNormaliseRequestData(string $context, object $objData, Form $form)
	{
		if ($context === 'com_radicalmart.shippingmethod')
		{
			foreach ($objData->prices as &$price)
			{
				$price['base'] = RadicalMartPriceHelper::clean($price['base'], $price['currency']);
			}
		}
	}

	/**
	 * Обрабатывает данные формы настройки метода доставки
	 *
	 * @param   Form   $form     The form object.
	 * @param   array  $data     Form data object.
	 * @param   array  $tmpData  Temporary form data object.
	 *
	 * @since 1.0.0
	 */
	public function onRadicalMartPrepareMethodForm(Form $form, $data, $tmpData): void
	{
		if (is_object($tmpData))
		{
			$tmpData = json_decode(json_encode($tmpData), true);
		}
		if ($form->getName() === 'com_radicalmart.shippingmethod' && $tmpData["plugin"] === 'eclcdek')
		{

			$jform_params_address = new Registry($tmpData['params']['jform_params_address']);

			$params           = new Registry(
				array(
					'from_country_code' => $tmpData['params']['from_country_code'] ?? 'RU',
					'from_city'         => $tmpData['params']['from_city'] ?? '173',
					'from_postal_code'  => $jform_params_address->get('postal_code', ''),
					'address'           => $jform_params_address->get('address', ''),
					'delivery_options'  => 'door'
				)
			);
			$shipping         = new \stdClass();
			$shipping->params = $params;
			$shipping->id     = 1;
			$wp               = ECLCDEKHelper::buildWidgetParams($shipping, (object) null);
			if ($this->autoloadLanguage)
				$this->loadLanguage();
			Text::script("JSELECT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_COUNTRY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_TO_CITY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_ADDRESS");
			Text::script('PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_MESSAGE_TEXT');
			Text::script('PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_ADDRESS');
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOSE_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_FILTER_WRONG_TYPE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_FILTER_WRONG_PARAMETER");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_REQUEST_VALIDATION");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_DOOR_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_OFFICE_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_TARIFFS_TITLE");
			/** @var WebAssetManager $assets */
			$wa = $this->app->getDocument()->getWebAssetManager();
			$wr = $wa->getRegistry();
			$wr->addRegistryFile('/media/plg_radicalmart_shipping_eclcdek/joomla.assets.json');
			$wa->useScript('eclcdek.widget');
			$wa->useScript('eclcdek.settings');
			$js = '
			document.addEventListener("DOMContentLoaded",function (){
				if(typeof window.ECLCDEKSettings === "undefined") {
					const params = {
		                common: {
			                    core: {
			                        debug: ' . ECLCDEKHelper::isDebug() . ',
			                        ajaxLoader:null,
				                    disabled_class:"pe-none",
			                    },
			                    city_field_id:"jform_params_from_city",
			                    country_field_id:"jform_params_from_country_code",
			                    region_field_id:"jform_params_from_region",
			                    calculationParams: null,
			                    deliveryType:"door",
			                    task:"settings",
			                    client:"admin",
			                    result:"cdek-address-result",
			                    widgetParams: ' . $wp . '
			                }
		            };
		            window.ECLCDEKSettings = new ECLCDEKSettings(params);
	            }
	        });';
			$wa->addInlineScript($js);
			$wa->useStyle('eclcdek.admin-settings');

			try
			{
				// Заполняем поле стран
				/** @var ListField $fld_country */
				$fld_country = $form->getField('from_country_code', 'params');
				$countries   = CDEKClientHelper::getCountries();
				ECLCDEKHelper::addListFieldOptions($form, $fld_country, $countries, 'code', 'country');

				$filter_regions = [];
				$filter_cities  = [];

				$filter_regions['country_codes'] = $tmpData['params']['from_country_code'] ?? 'RU';
				$filter_cities['country_codes']  = $tmpData['params']['from_country_code'] ?? 'RU';

				if ($tmpData['params']['from_region'])
				{
					$filter_cities['region_code'] = $tmpData['params']['from_region'];
				}

				// Заполняем поле регионов
				/** @var ListField $fld_region */
				$fld_region = $form->getField('from_region', 'params');
				$regions    = CDEKClientHelper::getRegions($filter_regions);
				$regions    = $this->_buildResultArray($regions->items, 'region');
				ECLCDEKHelper::addListFieldOptions($form, $fld_region, $regions, 'region_code', 'region');

				// Заполняем поле городов
				/** @var ListField $fld_city */
				$fld_city = $form->getField('from_city', 'params');

				$cities = CDEKClientHelper::getCities($filter_cities);
				$cities = $this->_buildResultArray($cities->items, 'city');
				ECLCDEKHelper::addListFieldOptions($form, $fld_city, $cities, 'code', 'city');

				// Все данные получены успешно, скрываем предупреждение, о данных авторизации
				$form->setFieldAttribute('note_common', 'class', 'hidden', 'params');
			}
			catch (Exception|AuthException|RequestException $error)
			{
				$this->addLog("onRadicalMartPrepareMethodForm", 'error', $error->getMessage());

			}
		}
	}

	/**
	 * Prepare RadicalMart shipping  data.
	 *
	 * @param   string  $context   Context selector string.
	 * @param   object  $method    Method data.
	 * @param   array   $formData  Order form data.
	 * @param   array   $products  Order products data.
	 * @param   array   $currency  Order currency data.
	 *
	 * @throws  \Exception
	 *
	 * @since  1.0.0
	 */
	public function onRadicalMartGetOrderShipping(string $context, object $method, array $formData,
	                                              array  $products, array $currency): void
	{
		// Prepare data
		$data = (!empty($formData['shipping'])) ? $formData['shipping'] : [];
		foreach ((new Registry($method->params->get('fields_default', [])))->toArray() as $item)
		{
			if (!empty($item['value']) && empty($data[$item['field']]))
			{
				$data[$item['field']] = $item['value'];
			}
		}
		// Set calculate_price
		$calculate_price = false;
		$currentUserData = false;
		if ($context === 'com_radicalmart.checkout')
		{
			$calculate_price = true;
			// Получаем данные по-умолчанию пользователя
			$currentUserData = ECLCDEKHelper::getCurrentCustomerData();
		}
		elseif ($context === 'com_radicalmart.order' && isset($data['recalculate_price']))
		{
			$calculate_price = ((int) $data['recalculate_price'] === 1);
		}

		// Set price
		$methodPrice = (isset($method->prices[$currency['group']])) ? $method->prices[$currency['group']] : [];
		if ($calculate_price || empty($data['price']) || !isset($data['price']['base']))
		{
			$price = $methodPrice;

			if(is_array($currentUserData) && isset($currentUserData['shipping']['shipping_method_'.$data['id']??''])) {
				// для данного метода доставки есть данные пользователя по-умолчанию
				$customer_data = $currentUserData['shipping']['shipping_method_'.$data['id']];
				$data = ECLCDEKHelper::mergeCustomerFormData($data,$customer_data);
			}

			if (!empty($data['address']) || !empty($data['city']))
			{
				// Есть адрес или установлен город
				$this->addLog("onRadicalMartGetOrderShipping", "data['address']", $data['address']);
				try
				{
					$address = json_decode($data['address'], true);
					if(!isset($address['address']['city_code'])){
						$address['address']['city_code'] = $data['city'];
					}

					if(!isset($address['address']['region_code'])){
						$address['address']['region_code'] = $data['region'];
					}
				} catch (\Exception $e){
					$address = "";
					$this->addLog("onRadicalMartGetOrderShipping", 'error', $e->getMessage());
				}
				$this->addLog("onRadicalMartGetOrderShipping", "address", $address);

				if (isset($address['tariff']['delivery_sum']))
				{
					$price['base'] = $address['tariff']['delivery_sum'];
				}
				else
				{
					$items = new \stdClass();

					$to    = new Location(array(
						'address'      => is_array($address) ? $address['address'] : "",
						'code'         => $data['city'],
						'country_code' => $data['country']
					));
					foreach ($products as $key => $product)
					{
						$items->products[] = $product;
					}
					$shipping               = clone($method);
					$shipping->order        = new \stdClass();
					$shipping->order->price = $methodPrice;
					$calculate_params       = ECLCDEKHelper::buildCalculateParams($shipping, $items, $to);
					$this->addLog("onRadicalMartGetOrderShipping", 'calculate_params', $calculate_params);
					try
					{
						$new_price = CDEKClientHelper::calculate($calculate_params);
						$this->addLog("onRadicalMartGetOrderShipping", 'new_price', $new_price);
						if (is_array($new_price->tariff_codes))
						{
							$price['base'] = $new_price->tariff_codes[0]->delivery_sum;
							$new_price->tariff_codes[0]->checked = true;
						}

						$address['tariff'] = $new_price->tariff_codes[0];
						$data["address"] = json_encode($address);
					}
					catch (\Exception $e)
					{
						$this->addLog("onRadicalMartGetOrderShipping", 'error', $e->getMessage());
					}
				}

			}
		}
		else
		{
			$price = $data['price'];
		}
		if (!isset($price['base']))
		{
			$price['base'] = 0;
		}

		// Set price values
		$code                 = $currency['code'];
		$price['base']        = RadicalMartPriceHelper::clean($price['base'], $code);
		$price['base_string'] = (empty($price['base'])) ? Text::_('PLG_RADICALMART_SHIPPING_ECLCDEK_PRICE_FREE')
			: RadicalMartPriceHelper::toString($price['base'], $code);
		$price['base_seo']    = (empty($price['base'])) ? Text::_('PLG_RADICALMART_SHIPPING_ECLCDEK_PRICE_FREE')
			: RadicalMartPriceHelper::toString($price['base'], $code, 'seo');
		$price['base_number'] = RadicalMartPriceHelper::toString($price['base'], $code, false);

		// Set final price
		$price['final']        = $price['base'];
		$price['final_string'] = (empty($price['final'])) ? Text::_('PLG_RADICALMART_SHIPPING_ECLCDEK_PRICE_FREE')
			: RadicalMartPriceHelper::toString($price['final'], $code);
		$price['final_seo']    = (empty($price['final'])) ? Text::_('PLG_RADICALMART_SHIPPING_ECLCDEK_PRICE_FREE')
			: RadicalMartPriceHelper::toString($price['final'], $code, 'seo');
		$price['final_number'] = RadicalMartPriceHelper::toString($price['final'], $code, false);

		// Set order data
		$method->order                       = new \stdClass();
		$method->order->id                   = $method->id;
		$method->order->title                = $method->title;
		$method->order->code                 = $method->code;
		$method->order->description          = $method->description;
		$method->order->address_string       = $this->addressToString($data);
		$method->order->address              = $data['address'];
		$method->order->delivery_time_string = $this->deliveryTimeToString($data);
		$method->order->tariff               = $this->tariffToString($data);
		$method->order->price                = $price;

		// Set layout
		if ($context === 'com_radicalmart.checkout')
		{
			$method->layout = 'plugins.radicalmart_shipping.eclcdek.radicalmart.' . ($this->app->isClient('site') ? 'site' : 'admin') . '.checkout';
		}

		// Set notification
		$method->notification = $this->prepareMethodNotification($data);
	}


	/**
	 * Prepare loaded RadicalMart & RadicalMart Express form data.
	 *
	 * @param   string   $context   Context selector string.
	 * @param   array   &$data      Method saved  data.
	 * @param   object   $method    Order shipping method object.
	 * @param   array    $formData  Order form data.
	 * @param   array    $products  Order products data.
	 * @param   array    $currency  Order currency data.
	 * @param   bool     $isNew     Is new order.
	 *
	 * @since 1.0.0
	 */
	public function onLoadOrderMethodFormData(string $context, array &$data, object $method, array $formData,
	                                          array  $products, array $currency, bool $isNew)
	{
		// Set all order data to form data
		foreach ((new Registry($method->order))->toArray() as $key => $value)
		{
			$data[$key] = $value;
		}
//		// Очищаем адрес, если он пустой
//		// TODO Вернуться к необходимости
//
		$data['recalculate_price'] = 0;
		if(empty($data["address"]))
		{
			unset($data["address"]);
		}
		// Cleanup actions
		$data['recalculate_price'] = 0;
	}

	/**
	 * Prepare and clean RadicalMart & RadicalMart Express order save data.
	 *
	 * @param   string   $context   Context selector string.
	 * @param   array   &$data      Method saved  data.
	 * @param   object   $method    Order shipping method object.
	 * @param   array    $formData  Order form data.
	 * @param   array    $products  Order products data.
	 * @param   array    $currency  Order currency data.
	 * @param   bool     $isNew     Is new order.
	 *
	 * @since 1.0.0
	 */
	public function onPrepareOrderMethodSaveData(string $context, array &$data, object $method, array $formData,
	                                             array  $products, array $currency, bool $isNew)
	{
		// Cleanup data
		unset($data['address_string']);
		unset($data['delivery_time_string']);
		unset($data['tariff']);
		unset($data['recalculate_price']);
		unset($data['data']['address_string']);
		unset($data['data']['delivery_time_string']);
		unset($data['data']['tariff']);
		unset($data['data']['recalculate_price']);
	}


	/**
	 * Prepare RadicalMart & RadicalMart Express order shipping methods.
	 *
	 * @param   string  $context   Context selector string.
	 * @param   object  $method    Method data.
	 * @param   array   $formData  Order form data.
	 * @param   array   $products  Order products data.
	 * @param   array   $currency  Order currency data.
	 *
	 * @throws  \Exception
	 *
	 * @since  1.0.0
	 */
	public function onGetOrderShippingMethods(string $context, object $method, array $formData,
	                                          array  $products, array $currency)
	{
		// Set disabled
		$method->disabled = false;
	}


	/**
	 * Prepare RadicalMart & RadicalMart Express order form.
	 *
	 * @param   string             $context   Context selector string.
	 * @param   Form               $form      Order form object.
	 * @param   array              $formData  Form data array.
	 * @param   array|null|false   $products  Shipping method data.
	 * @param   object|null|false  $shipping  Shipping method data.
	 * @param   object|null|false  $payment   Payment method data.
	 * @param   array              $currency  Order currency data.
	 *
	 * @since 1.0.0
	 */
	public function onGetOrderForm(string $context, Form $form, array $formData, $products, $shipping, $payment, array $currency)
	{

		$formName = $form->getName();

		if (!in_array($formName, ['com_radicalmart.checkout', 'com_radicalmart.order', 'com_radicalmart.order_site',
			'com_radicalmart_express.checkout', 'com_radicalmart_express.order', 'com_radicalmart_express.order_site']))
		{
			return;
		}

		// Remove fields
		$defaults = [];
		foreach ((new Registry($shipping->params->get('fields_default', [])))->toArray() as $item)
		{
			if (!empty($item['value']))
			{
				$defaults[$item['field']] = $item['value'];
			}
		}
		$countries    = null;
		$country_code = null;
		$regions      = null;
		$region_code  = null;
		$address = "";
		$city_code =null;
		if(isset($formData['shipping']['address']) && $formData['shipping']['address'])
		{
			try
			{
				$address = json_decode($formData['shipping']['address'], true);
				$this->addLog("onGetOrderForm", 'address', $address);
			} catch (Exception $e) {
				$this->addLog("onGetOrderForm", 'error', $e->getMessage());
				$address = "";
			}
		} else if(property_exists($shipping->order,'address') && $shipping->order->address){
			$address = json_decode($shipping->order->address, true);
			$this->addLog("onGetOrderForm", 'from order address', $address);
		}

		$city_code = match (true){
			!empty($formData['shipping']['city']) => $formData['shipping']['city'],
			!empty($address['address']['city_code']) => $address['address']['city_code'],
			default => ""
		};
		$country_code = match (true){
			!empty($formData['shipping']['country']) => $formData['shipping']['country'],
			!empty($address['address']['country_code']) => $address['address']['country_code'],
			isset($defaults['country']) && !empty($countries[$defaults['country']]) => $countries[$defaults['country']]->code,
			default => "RU"
		};

		$region_code = match (true){
			!empty($formData['shipping']['region']) => $formData['shipping']['region'],
			!empty($address['address']['region_code']) => $address['address']['region_code'],
			isset($defaults['region']) && !empty($countries[$defaults['region']]) => $countries[$defaults['region']]->code,
			default => ""
		};
		if ($formName !== 'com_radicalmart.order_site' &&
			$formName !== 'com_radicalmart_express.order_site')
		{
			foreach (self::$defaultFieldsParams as $key => $default)
			{
				$display    = $shipping->params->get('field_' . $key, $default);
				$hasDefault = false;

				if ($key === 'country')
				{
					// Заполняем список стран
					/** @var ListField $fld_country */
					$fld_country = $form->getField('country', 'shipping');
					if (!is_array($countries))
					{
						$countries    = CDEKClientHelper::getCountries();
					}
					ECLCDEKHelper::addListFieldOptions($form, $fld_country, $countries, 'code', 'country', $country_code);

				}
				else if ($key === 'region')
				{
					// Заполняем список регионов
					try
					{
						if (!is_array($regions))
						{
							$filter = array();
							if ($country_code)
							{
								$filter['country_codes'] = $country_code;
							}
							$regions = CDEKClientHelper::getRegions($filter);
							$regions = $this->_buildResultArray($regions->items, 'region');
						}
						/** @var ListField $fld_region */
						$fld_region = $form->getField('region', 'shipping');
						ECLCDEKHelper::addListFieldOptions($form, $fld_region, $regions, 'region_code', 'region', $region_code ?? '');
					}
					catch (AuthException|RequestException|Exception $error)
					{
						$this->addLog("onGetOrderForm", 'error', $error);
					}
				}
				else if ($key === 'city')
				{
					// Заполняем список городов
					try
					{

						$filter = array();
						if ($country_code)
						{
							$filter['country_codes'] = $country_code;
						}
						if ($region_code)
						{
							$filter['region_code'] = $region_code;
						}
						$cities = CDEKClientHelper::getCities($filter);
						$cities = $this->_buildResultArray($cities->items, 'city');
						/** @var ListField $fld_city */
						$fld_city = $form->getField('city', 'shipping');
						ECLCDEKHelper::addListFieldOptions($form, $fld_city, $cities, 'code', 'city', $city_code);
					}
					catch (AuthException|RequestException|Exception $error)
					{
						$this->addLog("onGetOrderForm", 'error', $error);
					}
				}
				else
				{
					if (!empty($defaults[$key]))
					{
						$form->setFieldAttribute($key, 'default', $defaults[$key], 'shipping');
						$hasDefault = true;
					}
				}

				if ($formName === 'com_radicalmart.checkout' || $formName === 'com_radicalmart_express.checkout')
				{
					if ($display === 'hidden')
					{
						if ($hasDefault)
						{
							$form->setFieldAttribute($key, 'type', 'hidden', 'shipping');
						}
						else
						{
							$form->removeField($key, 'shipping');
						}

					}
					elseif ($display === 'required')
					{
						$form->setFieldAttribute($key, 'required', 'true', 'shipping');
					}
					else
					{
						$form->setFieldAttribute($key, 'required', 'false', 'shipping');
					}
				}
				elseif ($formName === 'com_radicalmart.order' || $formName === 'com_radicalmart_express.order')
				{
					if ($display === 'hidden')
					{
						if ($hasDefault)
						{
							$form->setFieldAttribute($key, 'readonly', 'true', 'shipping');
						}
						else
						{
							$form->removeField($key, 'shipping');
						}
					}
					else if ($shipping->params->get("delivery_options") === "office" && in_array($key, ['entrance', 'floor', 'apartment']))
					{
						// Убираем поля курьерской доставки
						$form->removeField($key, 'shipping');
					}
				}
			}
		}

		if ($formName === 'com_radicalmart.checkout' || $formName === 'com_radicalmart_express.checkout'){
			// Оформление заказа, грузим скрипты плагина
			/** @var WebAssetManager $assets */
			$wa = $this->app->getDocument()->getWebAssetManager();
			$wr = $wa->getRegistry();
			$wr->addRegistryFile('/media/plg_radicalmart_shipping_eclcdek/joomla.assets.json');

			$this->addLog("onGetOrderForm", 'formData', $formData);
			$shipping_price = $shipping->prices[$currency["group"]];
			$item                               = new \stdClass();
			$item->products                     = $products;
			$shipping->order->price['currency'] = $currency["code"];
			$to                                 = new Location(array(
				'address'      => is_array($address) ? $address['address'] : "",
				'code'         => $city_code,
				'country_code' => $country_code));

			if(is_array($address))
			{
				try
				{
					$tariff_list       = CDEKClientHelper::calculate(ECLCDEKHelper::buildCalculateParams($shipping, $item, $to));
					$address["tariff"] = $tariff_list->tariff_codes[0];
					$form->setValue("address", 'shipping', json_encode($address, JSON_UNESCAPED_UNICODE));
				} catch (Exception $e) {
					$this->addLog("onGetOrderForm", 'error', $e->getMessage());
					$address = "";
				}
			}
			$cp = ECLCDEKHelper::buildCalculateParamsJSON($shipping,$item,$to);
			$this->addLog("onGetOrderForm", 'cp', $cp);
			$js = '
			document.addEventListener("onRadicalMartCheckoutAfterUpdateDisplayData",function (){
				console.log(typeof window.ECLCDEKFrontOrder);
	            if(typeof window.ECLCDEKFrontOrder === "undefined") {
	                let _cp = '.$cp.'
	                _cp.shipping_base = '.json_encode($shipping_price).'
	                let _wp = '.ECLCDEKHelper::buildWidgetParams($shipping,$item).'
	        
	                const params = {
	                    common: {
	                        core: {
	                            debug: '.ECLCDEKHelper::isDebug().',
	                            ajaxLoader:"checkout_shipping_loading",
	                            disabled_class:"uk-disabled",
	                        },
	                        city_field_id:"jform_shipping_city",
	                        country_field_id:"jform_shipping_country",
	                        region_field_id:"jform_shipping_region",
	                        calculationParams: _cp,
	                        deliveryType:"'.$shipping->params->get('delivery_options', "").'",
			                task:"checkout",
			                client:"site",
			                result:"cdek-address-result",
			                widgetParams:_wp}
			        };
			        window.ECLCDEKFrontOrder = new ECLCDEKFrontOrder(params);	
			    }            		
			});';
			$wa->addInlineScript($js);

		}

		if ($formName === 'com_radicalmart.order_site' || $formName === 'com_radicalmart_express.order_site')
		{

			foreach (['address', 'comment'] as $key)
			{
				if ((empty($formData['shipping']) || empty($formData['shipping'][$key]) && empty($shipping->order->$key)))
				{
					$form->removeField($key, 'shipping');
				}
			}

			if (empty($formData['shipping']['price']['base']))
			{
				$form->removeGroup('shipping.price');
			}
		}
		if ($formName === 'com_radicalmart.order' || $formName === 'com_radicalmart_express.order')
		{

			/** @var WebAssetManager $assets */
			$wa = $this->app->getDocument()->getWebAssetManager();
			$wr = $wa->getRegistry();
			$wr->addRegistryFile('/media/plg_radicalmart_shipping_eclcdek/joomla.assets.json');
			$wa->useScript('eclcdek.widget');
			$wa->useScript('eclcdek.admin-order');
			$wa->useStyle('eclcdek.admin');
			if ($this->autoloadLanguage)
				$this->loadLanguage();
			Text::script("JSELECT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_COUNTRY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_TO_CITY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_ADDRESS");
			Text::script('PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_MESSAGE_TEXT');
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_OFFICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_DOOR");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_PRICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_TIME");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_OFFICE_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_DOOR_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_TARIFFS_TITLE");

			$this->addLog("onGetOrderForm", 'formData', $formData);
			$address = "";
			if(isset($formData['shipping']['address']) && $formData['shipping']['address'])
			{
				try
				{
					$address = json_decode($formData['shipping']['address'], true);
					$this->addLog("onGetOrderForm", 'address', $address);
				} catch (Exception $e) {
					$this->addLog("onGetOrderForm", 'error', $e);
					$address = "";
				}
			}

			$shipping_price = $shipping->prices[$currency["group"]];

			$item                               = new \stdClass();
			$item->products                     = $products;
			$shipping->order->price['currency'] = $currency["code"];
			$to                                 = new Location(array(
				'address'      => is_array($address) ? $address['address'] : "",
				'code'         => $formData['shipping']['city'],
				'country_code' => $formData['shipping']['country']));
			$cp                                 = ECLCDEKHelper::buildCalculateParamsJSON($shipping, $item, $to);


			$js = "document.addEventListener('DOMContentLoaded',function (){
            if(typeof window.ECLCDEKFrontOrder === 'undefined') {
                let _cp = " . $cp . ";
                _cp.shipping_base = " . json_encode($shipping_price) . ";
                let _wp = " . ECLCDEKHelper::buildWidgetParams($shipping, $item) . ";

                const params = {
                    common: {
                        core: {
                            debug: " . ECLCDEKHelper::isDebug() . ",
                            ajaxLoader:'',
                            disabled_class:'pe-none'
                        },
                        city_field_id:'jform_shipping_city',
                        country_field_id:'jform_shipping_country',
                        region_field_id:'jform_shipping_region',
                        calculationParams: _cp,
                        deliveryType:'" . $shipping->params->get('delivery_options', "") . "',
                        task:'order',
                        client:'admin',
                        result:'cdek-address-result',
                        widgetParams:_wp
                    }
                };
                window.ECLCDEKAdminOrder = new ECLCDEKAdminOrder(params);
            }});";
			$wa->addInlineScript($js);
		}
	}

	/**
	 * Prepare RadicalMart & RadicalMart Express order totals.
	 *
	 * @param   string             $context   Context selector string.
	 * @param   array              $total     Order total data.
	 * @param   array              $formData  Form data array.
	 * @param   array|null|false   $products  Shipping method data.
	 * @param   object|null|false  $shipping  Shipping method data.
	 * @param   object|null|false  $payment   Payment method data.
	 * @param   array              $currency  Order currency data.
	 *
	 * @throws \Exception
	 *
	 * @since 1.0.0
	 */
	public function onGetOrderTotal(string $context, array &$total, array $formData, $products, $shipping, $payment,
	                                array  $currency)
	{
		if (!empty($shipping->order->price['base']))
		{
			$total['base'] += $shipping->order->price['base'];
		}

		if (!empty($shipping->order->price['final']))
		{
			$total['final'] += $shipping->order->price['final'];
		}
	}

	/**
	 * Get RadicalMart & RadicalMart Express order customer update data.
	 *
	 * @param   string  $context   Context selector string.
	 * @param   object  $order     Order data.
	 * @param   object  $customer  Customer data method data.
	 *
	 * @return array|false Update customer data if success, False if not.
	 *
	 * @since 2.0.0
	 */
	public function onGetOrderCustomerUpdateData(string $context, object $order, object $customer)
	{
		$result = false;
		if (!empty($order->formData['shipping']))
		{
			$result = [];
			foreach (self::$defaultFieldsParams as $key => $value)
			{
				if ($key !== 'comment'
					&& $order->shipping->params->get('field_' . $key, $value) !== 'hidden'
					&& !empty($order->formData['shipping'][$key]))
				{
					$result[$key] = $order->formData['shipping'][$key];
				}
			}
		}

		return $result;
	}

	/**
	 * Get RadicalMart & RadicalMart Express checkout customer data.
	 *
	 * @param   string  $context       Context selector string.
	 * @param   object  $shipping      Shipping method object.
	 * @param   array   $customerData  Customer data method data.
	 *
	 * @return array|false Customer shipping data for merge.
	 *
	 * @since 2.0.0
	 */
	public function onGetCheckoutCustomerData(string $context, object $shipping, array $customerData)
	{
		if (empty($customerData))
		{
			return false;
		}

		$result = [];
		foreach (self::$defaultFieldsParams as $key => $value)
		{
			if ($key === 'address' && !empty($customerData[$key])
				||  $key !== 'comment'
				&& $shipping->params->get('field_' . $key, $value) !== 'hidden'
				&& !empty($customerData[$key]))
			{
				$result[$key] = $customerData[$key];
			}
		}
		return (!empty($result)) ? $result : false;
	}

	/**
	 * Prepare RadicalMart & RadicalMart Express customer and personal forms.
	 *
	 * @param   string  $context   Context selector string.
	 * @param   Form    $form      Custer shipping method form object.
	 * @param   mixed   $data      The data expected for the form.
	 * @param   object  $shipping  Shipping method data.
	 *
	 * @since 2.0.0
	 */
	public function onGetCustomerMethodForm(string $context, Form $form, $data, object $shipping)
	{
		$countries    = null;
		$country_code = null;
		$regions      = null;
		$region_code  = null;
		foreach (self::$defaultFieldsParams as $key => $default)
		{
			if ($shipping->params->get('field_' . $key, $default) === 'hidden')
			{
				$form->removeField($key);
			}

			if ($key === 'country')
			{
				// Заполняем список стран
				/** @var ListField $fld_country */
				$fld_country = $form->getField('country');
				if (!is_array($countries))
				{
					$countries    = CDEKClientHelper::getCountries();
					$country_code = match (true)
					{
						isset($data->shipping["country"]) => $data->shipping["country"],
						isset($defaults['country']) && isset($countries[$defaults['country']]) => $countries[$defaults['country']]->code,
						default => 'RU',
					};
				}
				ECLCDEKHelper::addListFieldOptions($form, $fld_country, $countries, 'code', 'country', $defaults['country'] ?? '');

			}
			else if ($key === 'region')
			{
				// Заполняем список регионов
				try
				{
					if (!is_array($regions))
					{
						$filter = array();
						if ($country_code)
						{
							$filter['country_codes'] = $country_code;
						}
						$regions = CDEKClientHelper::getRegions($filter);
						$regions = $this->_buildResultArray($regions->items, 'region');

						$region_code = match (true)
						{
							isset($data->shipping["region"]) => $data->shipping["shipping"]["region"],
							isset($defaults['region']) && isset($regions[$defaults['region']]) => $regions[$defaults['region']]->region_code,
							default => '',
						};
					}
					/** @var ListField $fld_region */
					$fld_region = $form->getField('region');
					ECLCDEKHelper::addListFieldOptions($form, $fld_region, $regions, 'region_code', 'region', $defaults['region'] ?? '');
				}
				catch (AuthException|RequestException|Exception $error)
				{
					$this->addLog("onGetCustomerMethodForm", 'error', $error);
				}
			}
			else if ($key === 'city')
			{
				// Заполняем список городов
				try
				{
					$filter = array();
					if ($country_code)
					{
						$filter['country_codes'] = $country_code;
					}
					if ($region_code)
					{
						$filter['region_code'] = $region_code;
					}
					$cities = CDEKClientHelper::getCities($filter);
					$cities = $this->_buildResultArray($cities->items, 'city');
					/** @var ListField $fld_city */
					$fld_city = $form->getField('city');
					ECLCDEKHelper::addListFieldOptions($form, $fld_city, $cities, 'code', 'city', $defaults['city'] ?? '');
				}
				catch (AuthException|RequestException|Exception $error)
				{
					$this->addLog("onGetCustomerMethodForm", 'error', $error);
				}
			}
			else if ($shipping->params->get('delivery_options') === 'office' && in_array($key, ['entrance', 'floor', 'apartment']))
			{
				$form->removeField($key);
			}
			else
			{
				if (!empty($defaults[$key]))
				{
					$form->setFieldAttribute($key, 'default', $defaults[$key]);
				}
			}
		}

		if ($context === "com_radicalmart.customer")
		{
			/** @var WebAssetManager $assets */
			$wa = $this->app->getDocument()->getWebAssetManager();
			$wr = $wa->getRegistry();
			$wr->addRegistryFile('/media/plg_radicalmart_shipping_eclcdek/joomla.assets.json');
			$wa->useScript('eclcdek.widget');
			$wa->useScript('eclcdek.admin-customer');
			$wa->useStyle('eclcdek.admin');
			if ($this->autoloadLanguage)
				$this->loadLanguage();
			Text::script("JSELECT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_COUNTRY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_TO_CITY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_ADDRESS");
			Text::script('PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_MESSAGE_TEXT');
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_OFFICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_DOOR");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_MESSAGE_READY_CHOOSE_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_MESSAGE_READY_CHOOSE_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_PRICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_TIME");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_OFFICE_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_DOOR_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_TARIFFS_TITLE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_LAYOUT_RESULT_OFFICE_TITLE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_LAYOUT_RESULT_DOOR_TITLE");
			$shipping_method = "shipping_method_" . $shipping->id;

			$js = "document.addEventListener('DOMContentLoaded',function (){
                let _wp = " . ECLCDEKHelper::buildWidgetParams($shipping, (object) null) . ";

                const params = {
                    common: {
                        core: {
                            debug: " . ECLCDEKHelper::isDebug() . ",
                            ajaxLoader:'',
                            disabled_class:'pe-none'
                        },
                        city_field_id:'jform_shipping_" . $shipping_method . "_city',
                        country_field_id:'jform_shipping_" . $shipping_method . "_country',
                        region_field_id:'jform_shipping_" . $shipping_method . "_region',
                        calculationParams: null,
                        deliveryType:'" . $shipping->params->get('delivery_options', "") . "',
                        task:'customer',
                        client:'admin',
                        result:'cdek-address-result',
                        widgetParams:_wp,
	                    parent_selector:{
	                        name:'id',
	                        value:'" . $shipping_method . "'
	                    }
                    },

                };
                
                function loadECLScript(el){
                    if(el.getAttribute('aria-controls') === '" . $shipping_method . "'){
                        if(typeof window.ECLCDEKAdminCustomer_" . $shipping_method . " === 'undefined' ){
                            window.ECLCDEKAdminCustomer_" . $shipping_method . " = new ECLCDEKAdminCustomer(params);
                        }
                    }        
                };
                
                let _joomla_tab = document.querySelector('joomla-tab#myTab');
                if(_joomla_tab){
                    let _currentTab = _joomla_tab.querySelector('button[aria-expanded=true]');
                    loadECLScript(_currentTab);
                    _joomla_tab.addEventListener('click',function(e){
                        loadECLScript(e.target);
                    },{ once: true });
                }
                
            });";
			$wa->addInlineScript($js);
		}
		else if ($context === "com_radicalmart.personal")
		{
			/** @var WebAssetManager $assets */
			$wa = $this->app->getDocument()->getWebAssetManager();
			$wr = $wa->getRegistry();
			$wr->addRegistryFile('/media/plg_radicalmart_shipping_eclcdek/joomla.assets.json');
			$wa->useScript('eclcdek.widget');
			$wa->useScript('eclcdek.front-personal');
			$wa->useStyle('eclcdek.front');
			if ($this->autoloadLanguage)
				$this->loadLanguage();
			Text::script("JSELECT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_COUNTRY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_TO_CITY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_ADDRESS");
			Text::script('PLG_RADICALMART_SHIPPING_ECLCDEK_ERROR_NOT_SET_MESSAGE_TEXT');
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_NEED_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_OFFICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_ERROR_NEED_DOOR");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_MESSAGE_READY_CHOOSE_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_MESSAGE_READY_CHOOSE_OFFICE_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_MESSAGE_READY_CHOOSE_DOOR_TEXT");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_ADDRESS");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_READY_TO_CHOOSE_TO_PVZ");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_PRICE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_TIME");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_OFFICE_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CHOOSE_DOOR_DELIVERY");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_TARIFFS_TITLE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_LAYOUT_RESULT_OFFICE_TITLE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_CUSTOMER_LAYOUT_RESULT_DOOR_TITLE");
			Text::script("PLG_RADICALMART_SHIPPING_ECLCDEK_SETTINGS_MESSAGE_NEED_ADDRESS");
			$shipping_method = "shipping_method_" . $shipping->id;
			$to              = new Location(array(
				'address'      => '',
				'code'         => $data->shipping['city'],
				'country_code' => $data->shipping['country']));


			$js = "document.addEventListener('DOMContentLoaded',function (){
                let _wp = " . ECLCDEKHelper::buildWidgetParams($shipping, (object) null) . ";

                const params = {
                    common: {
                        core: {
                            debug: " . ECLCDEKHelper::isDebug() . ",
                            ajaxLoader:'',
                            disabled_class:'uk-disabled'
                        },
                        city_field_id:'jform_shipping_" . $shipping_method . "_city',
                        country_field_id:'jform_shipping_" . $shipping_method . "_country',
                        region_field_id:'jform_shipping_" . $shipping_method . "_region',
                        calculationParams: null,
                        deliveryType:'" . $shipping->params->get('delivery_options', "") . "',
                        task:'personal',
                        client:'site',
                        result:'cdek-address-result',
                        widgetParams:_wp,
	                    parent_selector:{
	                        name:'id',
	                        value:'personal_" . $shipping_method . "'
	                    }
                    },

                };
                if(typeof window.ECLCDEKFrontPersonal_" . $shipping_method . " === 'undefined' ){
                    window.ECLCDEKFrontPersonal_" . $shipping_method . " = new ECLCDEKFrontPersonal(params);
                }                                
            });";
			$wa->addInlineScript($js);
		}

	}

	/**
	 * Prepare RadicalMart personal shipping method data.
	 *
	 * @param   string  $context  Context selector string.
	 * @param   object  $method   Method data.
	 *
	 * @throws  \Exception
	 *
	 * @since  2.0.0
	 */
	public function onGetPersonalShippingMethods(string $context, object $method)
	{
		$method->layout = (strpos($context, 'com_radicalmart_express.') !== false)
			? 'plugins.radicalmart_shipping.eclcdek.radicalmart_express.site.personal'
			: 'plugins.radicalmart_shipping.eclcdek.radicalmart.site.personal';
	}


	/**
	 * Method to prepare shipping notification information.
	 *
	 * @param   array  $data  Shipping form data.
	 *
	 * @return array
	 *
	 * @since 1.0.0
	 */
	protected function prepareMethodNotification(array $data): array
	{
		$result = [];
		if (empty($data))
		{
			return $result;
		}

		$address_string = $this->addressToString($data);

		if (!empty($address_string))
		{
			$result['PLG_RADICALMART_SHIPPING_ECLCDEK_CDEK_FIELD_ADDRESS'] = $address_string;
		}
		if (!empty($data['comment']))
		{
			$result['PLG_RADICALMART_SHIPPING_ECLCDEK_CDEK_FIELD_COMMENT'] = $data['comment'];
		}

		$delivery_time_string = $this->deliveryTimeToString($data);

		if (!empty($delivery_time_string))
		{
			$result['PLG_RADICALMART_SHIPPING_ECLCDEK_CDEK_FIELD_DELIVERY_TIME'] = $delivery_time_string;
		}

		$tariff = $this->tariffToString($data);

		if (!empty($tariff))
		{
			$result['PLG_RADICALMART_SHIPPING_ECLCDEK_CDEK_FIELD_TARIFF'] = $tariff;
		}

		return $result;
	}

	/**
	 * Обработка запросов AJAX
	 *
	 * @throws Exception
	 *
	 * @since 1.0.0
	 */
	#[NoReturn] public function onAjaxECLCDEK(AjaxEvent $event): void
	{
		$action = $this->app->input->getCmd('action', "");
		$data   = $this->app->input->get('request_data', []);
		Factory::getApplication()->getLanguage()->load('plg_radicalmart_shipping_eclcdek', JPATH_ADMINISTRATOR);
		$this->addLog("onAjaxECLCDEK", 'action ', $action);
		if (!$data)
		{
			$json   = file_get_contents('php://input');
			$source = json_decode($json, true);
			$inp    = new Input($source);
			$data   = $inp->get('request_data', [], 'ARRAY');
		}
		$this->addLog("onAjaxECLCDEK", 'data ', $data);
		switch ($action)
		{
			case "getCities":
				try
				{
					$filter = array();
					if ($data["country_codes"])
					{
						$filter["country_codes"] = $data["country_codes"];
					}
					if ($data["city"])
					{
						$filter["city"] = strtolower($data["city"]);
					}
					if ($data["region_code"])
					{
						$filter["region_code"] = $data["region_code"];
					}
					if (count($filter) == 0)
					{
						echo $this->_buildAjaxErrorResult(Text::_("PLG_RADICALMART_SHIPPING_ECLCDEK_REQUEST_CITIES_ERROR_WRONG_REQUEST"), $data);
						jexit();
					}
					$cities = CDEKClientHelper::getCities($filter);
					echo $this->_buildAjaxSuccessResult($this->_buildResultArray($cities->items, "city"));
				}
				catch (AuthException $exception)
				{
					//Авторизация не выполнена, не верные account и secure
					echo $this->_buildAjaxErrorResult($exception->getMessage(), array('error' => $exception));
				}
				break;
			case "getRegions":
				try
				{
					$filter = array();
					if ($data["country_codes"])
					{
						$filter["country_codes"] = $data["country_codes"];
					}
					if (count($filter) == 0)
					{
						echo $this->_buildAjaxErrorResult(Text::_("PLG_RADICALMART_SHIPPING_ECLCDEK_REQUEST_REGIONS_ERROR_WRONG_REQUEST"), $data);
						jexit();
					}

					$regions = CDEKClientHelper::getRegions($filter);
					echo $this->_buildAjaxSuccessResult($this->_buildResultArray($regions->items, "region"));
				}
				catch (AuthException $exception)
				{
					//Авторизация не выполнена, не верные account и secure
					echo $this->_buildAjaxErrorResult($exception->getMessage(), array('error' => $exception));
				}
				break;
			case "getResultFormatted":
				try
				{
					if ($this->autoloadLanguage)
						$this->loadLanguage();

					if (!empty($data['output_params']['result']['address']) || !empty($data['output_params']['result']['tariff']))
					{
						// Выводим адрес
						$cp     = $data['output_params']['calculation_params'];
						$tariff = $data['output_params']['result']['tariff'] ?? null;
						$this->addLog("onAjaxECLCDEK", 'tariff', $tariff);
						if (count($cp))
						{
							$this->reformatCalculateParams($cp);
							$this->addLog("onAjaxECLCDEK", 'cp', $cp);
							/** @var ECLTariffList $tariff_list */
							$tariff_list = CDEKClientHelper::calculate($cp);
							$this->addLog("onAjaxECLCDEK", 'tariff_list', $tariff_list);
						}
						else
						{
							$tariff_list = null;
						}
						// Передаем первый тариф из списка, как текущий
						if ($tariff_list instanceof ECLTariffList  && !empty($tariff_list->tariff_codes))
						{
							if (is_null($tariff))
							{
								$tariff                                = $tariff_list->tariff_codes[0];
								$tariff_list->tariff_codes[0]->checked = true;
							}
							else
							{
								foreach ($tariff_list->tariff_codes as &$item)
								{
									if ($item->tariff_code == $tariff['tariff_code'])
									{
										$item->checked = true;
										break;
									}
								}
							}
						}
						$result = [
							"output_params" => array(
								"result" => array(
									'address' => $data['output_params']['result']['address'],
									'tariff'  => $tariff)
							),
							"message"       => array(
								"formatted" => ECLCDEKHelper::getFormatedAddress($data['output_params']['result']['address'], $data['deliveryType'], $tariff_list, $data['client'], $data['task'])
							)
						];

					}
					else
					{
						// Выводим сообщение
						$result = [
							"message" => array(
								"formatted" => ECLCDEKHelper::getFormattedMessage($data['message']["type"], $data['message']["text"], $data['deliveryType'], $data['client'])
							)
						];
					}
					echo $this->_buildAjaxSuccessResult($result);
				}
				catch (Exception $exception)
				{
					//ошибка форматирования сообщения
					echo $this->_buildAjaxErrorResult($exception->getMessage(), array('error' => $exception));
				}
				break;
			default:
		}
		jexit();
	}

	/**
	 * Преобразует параметры расчета стоимости доставки из массива в объект.
	 * При обработке запроса AJAX
	 *
	 * @param   array  $cp  Массив параметров расчета цены
	 *
	 *
	 * @since 1.0.1
	 */
	private function reformatCalculateParams(&$cp): void
	{
		if (is_array($cp))
		{
			$cp["from"] = new Location($cp["from"]);
			$cp["to"]   = new Location($cp["to"]);


			$t             = new \stdClass();
			$t->door       = $cp["tariffs"]["door"];
			$t->office     = $cp["tariffs"]["office"];
			$t->pickup     = $cp["tariffs"]["pickup"];
			$cp["tariffs"] = $t;
			$g             = [];
			foreach ($cp["goods"] as $good)
			{
				$g[] = new Package($good);
			}
			$cp["goods"] = $g;

			$cp['shipping_base'] = (object) $cp['shipping_base'];
		}
	}

	/**
	 * Формирует массив, отсортированный по ключу
	 *
	 * @param   array   $result  Исходный массив элементов CdekSDK2\Dto\*
	 * @param   string  $key     Имя ключа по которому будет сформирован выходной массив и произведена сортировка
	 * @param   string  $order   Направление сортировки ASC и DESC
	 *
	 * @return array
	 *
	 * @since 1.0.0
	 */
	private function _buildResultArray(array $result, $key, $order = "ASC"): array
	{
		$out = [];
		foreach ($result as $v)
		{
			// Удаляем из результата не актуальные регионы
			if ($v instanceof Region && (str_contains($v->$key, '(удален)') /*|| is_null($v->kladr_region_code) && is_null($v->fias_region_guid)*/))
				continue;

			$out[$v->$key] = $v;
		}
		if ($order == "ASC")
		{
			ksort($out);
		}
		else
		{
			krsort($out);
		}

		return $out;
	}

	/**
	 * Формирует строку ответа успешного выполнения запроса AJAX
	 *
	 * @param   array  $data  Возвращаемые данные ответа
	 *
	 * @return string
	 *
	 * @since 1.0.1
	 */
	private function _buildAjaxSuccessResult(array $data): string
	{
		return json_encode(
			array(
				'success' => true,
				'message' => "",
				'data'    => $data
			),
			JSON_UNESCAPED_UNICODE
		);
	}

	/**
	 * Формирует строку ответа при ошибке выполнения запроса AJAX
	 *
	 * @param   string  $message  Сообщение об ошибке
	 * @param   mixed   $data     Данные запроса
	 *
	 * @return string
	 *
	 * @since 1.0.1
	 */
	private function _buildAjaxErrorResult(string $message, $data): string
	{
		return json_encode(
			array(
				'success' => false,
				'message' => $message,
				'data'    => $data
			),
			JSON_UNESCAPED_UNICODE
		);
	}

	/**
	 * Сохранение отладочной информации в лог
	 *
	 * @param   string  $source         Наименование метода источника записи
	 * @param   string  $variable_name  Наименование переменной
	 * @param   mixed   $data           Переменная для записи в лог
	 *
	 * @return void
	 *
	 * @since 1.0.0
	 */
	private function addLog(string $source, string $variable_name, $data): void
	{
		ECLCDEKHelper::addLog($source, $variable_name, $data);
	}

	/**
	 * Формирует строку адреса для вывода пользователю
	 *
	 * @param   array  $data  Данные содержащие адрес
	 *
	 * @return string
	 *
	 * @since 1.0.1
	 */
	protected function addressToString(array $data = []): string
	{
		$this->addLog("addressToString", "data", $data);
		$result = "";
		if (isset($data['address']))
		{
			try
			{
				$result       = [];
				$address_data = json_decode($data['address'], true);
				$address      = $address_data["address"];

				foreach (['entrance', 'floor', 'apartment'] as $key)
				{
					if (!empty($data[$key]))
					{
						$address[$key]= $data[$key];
					}
				}
				$this->addLog("addressToString", "address", $address);
				$client        = $this->app->isClient("admin") ? 'admin' : 'site';
				$delivery_type = isset($address["formatted"]) ? "door" : 'office';
				$result        = LayoutHelper::render('plugins.radicalmart_shipping.eclcdek.radicalmart.' . $client . '.order-results', array('address' => $address, 'deliveryType' => $delivery_type), JPATH_ROOT);
			}
			catch (\Exception $exception)
			{
				$this->addLog("addressToString", "exception", $exception);
			}
		}

		$this->addLog("addressToString", "result", $result);

		return $result;
	}

	/**
	 * Формирует строку со сроком доставки для вывода пользователю
	 *
	 * @param   array  $data  Данные, содержащие срок доставки
	 *
	 * @return string
	 *
	 * @since 1.0.1
	 */
	protected function deliveryTimeToString(array $data = []): string
	{
		$this->addLog("deliveryTimeToString", "data", $data);
		$result = "";
		if (isset($data['address']))
		{
			try
			{
				$address_data = json_decode($data['address'], true);
				$tariff       = $address_data["tariff"];
				$this->addLog("deliveryTimeToString", "tariff", $tariff);
				if (isset($tariff["calendar_max"]))
				{
					$result = Text::sprintf("PLG_RADICALMART_SHIPPING_ECLCDEK_LAYOUT_RESULT_DELIVERY_TIME", $tariff["calendar_max"]);
				}
			}
			catch (\Exception $exception)
			{
				$this->addLog("deliveryTimeToString", "exception", $exception);
			}
		}
		$this->addLog("deliveryTimeToString", "result", $result);

		return $result;

	}

	/**
	 * Формирует строку с наименованием тарифа
	 *
	 * @param   array  $data  Данные, содержащие тариф
	 *
	 * @return string
	 *
	 * @since 1.0.1
	 */
	protected function tariffToString(array $data = []): string
	{
		$this->addLog("tariffToString", "data", $data);
		$result = "";
		if (isset($data['address']))
		{
			try
			{
				$address_data = json_decode($data['address'], true);
				$tariff       = $address_data["tariff"];
				$this->addLog("tariffToString", "tariff", $tariff);
				if (isset($tariff["tariff_name"]))
				{
					$result = $tariff["tariff_name"];
				}
			}
			catch (\Exception $exception)
			{
				$this->addLog("tariffToString", "exception", $exception);
			}
		}
		$this->addLog("tariffToString", "result", $result);

		return $result;
	}
}

