<?php
	/**
	 * @version     1.0.3
	 * @package     Joomla 4
	 * @subpackage  Formea
	 * @author      Feseur Sdn Bhd
	 * @copyright   Copyright (C) 2010 - 2020 Feseur Sdn Bhd
	 * @license     GNU/GPL, see LICENSE.php
	 */

	// no direct access
	defined('_JEXEC') or die();

	use Joomla\CMS\Factory;
	use Joomla\CMS\Language\Text;
	use Joomla\CMS\WebAsset\WebAssetManager;
	use Joomla\Component\Formea\Site\Helper\FormeaGeneralHelper;
	use Joomla\Component\Formea\Site\Libraries\FormeaCore;
	use Joomla\Database\DatabaseDriver;

	class FormeaCalculations extends FormeaCore
	{
		private $calculationPath;
		private $core;


		public function __construct($config)
		{
			parent::__construct($config);
			$this->calculationPath = JPATH_ROOT . '/components/com_formea/plugins/core/Calculations/';
			$app                   = Factory::getApplication();
			/** @var WebAssetManager $wa */
			$wa       = $app->getDocument()->getWebAssetManager();
			$registry = $wa->getRegistry();
			$registry->addRegistryFile('components/com_formea/plugins/core/Calculations/joomla.asset.json');
		}

		public function drawPageElementAttribute($formId, $currentIdx, $totalPages)
		{
			$pageAttributes                    = [];
			$pageClass                         = ['content', 'multipage_' . $this->formUniqueString . '_' . $currentIdx];
			$pageAttributes['role']            = 'tabpanel';
			$pageAttributes['aria-labelledby'] = 'fm_pg_' . $this->formUniqueString . '_' . $currentIdx . '_trigger';

			return [
				'pageAttributes' => $pageAttributes,
				'pageClass'      => $pageClass,
			];
		}

		protected function getCore()
		{
			if (empty($this->core))
			{
				$core = FormeaGeneralHelper::getCoreExtension($this->id);
				if (!empty($core))
				{
					$params = $core->params;
					if ($this->styleId > 0)
					{
						$style = FormeaGeneralHelper::getExtensionStyle($this->styleId);
						if (!empty($style))
						{
							$params = $style->params;
						}
					}
					$core->params = new Joomla\Registry\Registry($params);
				}
				$this->core = $core;
			}

			return $this->core;
		}

		protected function generateVars($string)
		{
			$pattern = '/\[(.*?)\]/';
			$matches = [];
			preg_match_all($pattern, $string, $matches);
			$aliasArray      = $matches[1]; // Extracted words/characters
			$jsVarArray      = [];
			$totalAliasArray = count($aliasArray);
			for ($i = 0; $i < $totalAliasArray; $i++)
			{
				$alias        = $aliasArray[$i];
				$jsVarArray[] = [
					'var'   => str_replace('-', '_', $alias),
					'alias' => $alias,
					'inp'   => 'this.formEl.querySelector(\'[name="formea[' . $alias . ']"]\')'
				];
			}

			return $jsVarArray;
		}

		protected function _writeExpressionScript($vars, $resultFields, $params)
		{

			$totalResultFields = count($resultFields);


			$functionName  = 'exp' . \Feseur\Library\FsrHelper::generateRandomUniqueString();
			$expression    = $params->expression;
			$fieldIds      = $params->fieldIds;
			$setting       = $params->setting;
			$fieldIds      = explode(',', $fieldIds);
			$totalFieldIds = count($fieldIds);

			$initScript = 'init: function(){';
			$initScript .= "\r\n";

			$script     = 'var ' . $functionName . ' = {';
			$script     .= "\r\n";
			$script     .= 'formEl: null,';
			$script     .= "\r\n";
			$script     .= 'resultFields: [],';
			$script     .= "\r\n";
			$initScript .= 'this.formEl = document.getElementById(\'formea_form_' . $this->formUniqueString . '\');';
			$initScript .= "\r\n";
			$initScript .= 'this.resultFields = [';
			for ($j = 0; $j < $totalResultFields; $j++)
			{
				$initScript .= '{';
				$initScript .= 'type: 0,';
				$initScript .= 'alias: "' . $resultFields[$j]['alias'] . '",';
				$initScript .= 'el: ' . $resultFields[$j]['inp'];
				$initScript .= '}';
				if ($j !== ($totalResultFields - 1) || $totalFieldIds > 0)
				{
					$initScript .= ',';
				}
			}

			for ($k = 0; $k < $totalFieldIds; $k++)
			{
				$initScript .= '{';
				$initScript .= 'type: 1,';
				$initScript .= 'alias: "",';
				$initScript .= 'el: document.getElementById("' . $fieldIds[$k] . '")';
				$initScript .= '}';
				if ($j !== ($totalFieldIds - 1) || $totalFieldIds > 0)
				{
					$initScript .= ',';
				}
			}
			$initScript .= ']';
			$initScript .= "\r\n";

			$calcScript = 'calc: function(){';
			$calcScript .= "\r\n";

			$totalVars = count($vars);
			$setVars   = [];
			for ($i = 0; $i < $totalVars; $i++)
			{
				if (!in_array($vars[$i]['var'], $setVars))
				{
					$setVars[] = $vars[$i]['var'];

					$script .= $vars[$i]['var'] . ':null,';
					$script .= "\r\n";

					$initScript .= 'this.' . $vars[$i]['var'] . ' = ' . $vars[$i]['inp'] . ';';
					$initScript .= "\r\n";
					$initScript .= 'if(this.' . $vars[$i]['var'] . ' !== undefined && this.' . $vars[$i]['var'] . ' !== null){';
					$initScript .= "\r\n";
					$initScript .= 'this.' . $vars[$i]['var'] . '.addEventListener(\'change\',function(){';
					$initScript .= 'this.calc();';
					$initScript .= '}.bind(this));';
					$initScript .= "\r\n";

					$initScript .= "\r\n";
					$initScript .= 'this.' . $vars[$i]['var'] . '.addEventListener(\'keyup\',function(){';
					$initScript .= 'this.calc();';
					$initScript .= '}.bind(this));';
					$initScript .= "\r\n";

					$initScript .= '}';
					$initScript .= "\r\n";

					$calcScript .= 'let ' . $vars[$i]['var'] . 'Val = 0;';
					$calcScript .= 'if(this.' . $vars[$i]['var'] . ' !== undefined && this.' . $vars[$i]['var'] . ' !== null){';
					$calcScript .= "\r\n";
					$calcScript .= $vars[$i]['var'] . 'Val = parseFloat(this.' . $vars[$i]['var'] . '.value);';

					//$calcScript .='console.log(\''.$vars[$i]['var'] . 'Val\','.$vars[$i]['var'] . 'Val);';
					//$calcScript .='console.log(\'this.' . $vars[$i]['var'] .'\',this.'.$vars[$i]['var'] . ');';

					$calcScript .= "\r\n";
					$calcScript .= '}';
					$calcScript .= "\r\n";
				}

				$expression = str_replace('[' . $vars[$i]['alias'] . ']', ' ' . $vars[$i]['var'] . 'Val ', $expression);

			}
			$initScript .= "this.calc();";
			$initScript .= '},';
			$script     .= $initScript;
			$script     .= "\r\n";
			$script     .= $calcScript;
			$script     .= "\r\n";
			$script     .= 'let result = ' . $expression . ';';
			//$script .= 'console.log("result '.$expression.' ",result);';
			$script     .= "\r\n";
			// $script .="console.log('result',result);";
			$script .= "if(isNaN(result) ){result = 0;}";
			$script .= 'if(!isNaN(result) ){';
			$script .= 'result = parseFloat(result);';
			$script .= 'this.resultFields.forEach(function(rf){';
			$script .= 'if(rf.el !== undefined && rf.el !== null){';
			$script .= 'var _val = SiteFormeaCalculations.formattedNumber(result,' . $setting->decimal . ',"' . $setting->thousand . '","' . $setting->decimalSeparator . '");';
			$script .= 'if(SiteFormeaCalculations.canAcceptValueAttribute(rf.el)){';

			$script .='if(rf.el.value !== _val){';
			//$script .='console.log("rf.el",rf.el);';
			$script .='FormeaFormGeneral.triggerElementChange(0,"",0,0,0,"","");';
			$script .= 'rf.el.value = SiteFormeaCalculations.formattedNumber(result,' . $setting->decimal . ',"' . $setting->thousand . '","' . $setting->decimalSeparator . '");';
			$script .='}';

			$script .= '}else{';
			$script .='if(rf.el.innerHTML !== _val){';
			$script .='FormeaFormGeneral.triggerElementChange(0,"",0,0,0,"","");';
			$script .= 'rf.el.innerHTML = _val;';
			$script .='}';

			$script .= '}';
			$script .= '}';
			$script .= '}.bind(this));';
			$script .= '}';
			$script .= "\r\n";
			$script .= '},';
			$script .= "\r\n";
			$script .= '};';

			return [
				'functioName' => $functionName,
				'script'      => $script
			];
		}

		public function getGeneratedScript()
		{
			$script      = '';
			$expressions = $this->formParams->get('expressions.expressionLists');
			if (!empty($expressions))
			{

				$expressionLists      = json_decode($expressions);
				$totalExpressionLists = count($expressionLists);
				$functionNames        = [];

				for ($i = 0; $i < $totalExpressionLists; $i++)
				{
					$vars         = $this->generateVars($expressionLists[$i]->expression);
					$resultFields = $this->generateVars(implode(',', $expressionLists[$i]->field));


					$expressionFunc  = $this->_writeExpressionScript($vars, $resultFields, $expressionLists[$i]);
					$functionNames[] = $expressionFunc['functioName'];
					$script          .= $expressionFunc['script'];
				}

				$script .= ' document.addEventListener("DOMContentLoaded",function(){ ';
				foreach ($functionNames as $func)
				{
					$script .= $func . '.init();';
				}
				$script .= '});';

				$script .= ' document.addEventListener("FormeaElementChanged",function(){ ';
				$time = 50;
				$iterator = 0;
				foreach ($functionNames as $func)
				{
					$script .='setTimeout(function(){';
					$script .= $func . '.calc();';
					$script .='},'. $time  .');';
					$iterator++;
				}
				$script .= '});';
			}

			return $script;
		}

		public function getLoadableScript()
		{
			return [
				"site.formea-calculations.js"
			];
		}

		public function getLoadableStyle()
		{
			return [
			];
		}

		public function initFormEdit($config = [])
		{

			$app       = Factory::getApplication();
			$lang      = $app->getLanguage();
			$langTag   = $lang->getTag();
			$container = Factory::getContainer();
			/** @var DatabaseDriver $db */
			$db    = $container->get('DatabaseDriver');
			$query = $db->getQuery(true);

			if (\Joomla\CMS\Filesystem\Folder::exists(FORMEA_CORE_PATH . '/Calculations/language/' . $langTag))
			{
				$langStringIni = parse_ini_file(FORMEA_CORE_PATH . '/Calculations/language/' . $langTag . '/Calculations.ini');
				$lang->load('Calculations', FORMEA_CORE_PATH . '/Calculations', $langTag);
			}
			else
			{
				$langStringIni = parse_ini_file(FORMEA_CORE_PATH . '/Calculations/language/en-GB/Calculations.ini');
				$lang->load('Calculations', FORMEA_CORE_PATH . '/Calculations', 'en-GB');
			}

			$intro = Text::_('CALCULATIONS_FORMEA_FORM_EDIT_INTRO');

			$elements        = [];
			$expressionLists = [];
			if ($this->formId > 0)
			{
				$query->clear();
				$query->select(['a.id', 'a.title', 'a.element_id', 'a.type', 'b.value_type', 'c.alias']);
				$query->from($db->quoteName('#__formea_form_elements', 'a'))->innerJoin(
					$db->quoteName('#__formea_eltypes', 'b') . ' ON ' . $db->quoteName('a.type') . ' = ' .
					$db->quoteName('b.name')
				)->innerJoin(
					$db->quoteName('#__formea_elements', 'c') . ' ON ' . $db->quoteName('a.element_id') . ' = ' .
					$db->quoteName('c.id')
				);
				$query->where($db->quoteName('a.form_id') . ' = ' . $db->quote($this->formId));
				$query->order('a.id ASC');
				$db->setQuery($query);
				$elements = $db->loadObjectList();
			}

			$defaultAvailableFields    = ['text' => Text::_('JNONE'), 'val' => 0];
			$decimalOptions            = [
				['text' => '0', 'val' => 0],
				['text' => '1', 'val' => 1],
				['text' => '2', 'val' => 2],
				['text' => '3', 'val' => 3],
				['text' => '4', 'val' => 4],
			];
			$resultTypeOptions         = [
				['text' => Text::_('CALCULATIONS_FORM_FIELD'), 'val' => 0],
				['text' => Text::_('CALCULATIONS_HTML_ELEMENT_ID'), 'val' => 1],
				['text' => Text::_('CALCULATIONS_FORM_FIELD_AND_HTML_ELEMENT_ID'), 'val' => 3],
			];
			$defaultResultSetting      = [
				'resultType'       => 0,
				'decimal'          => 2,
				'thousand'         => ',',
				'decimalSeparator' => '.',
			];
			$allowedExpressionFields   = [0, 1, 2, 7];
			$allowedResultFields       = [0, 3, 4];
			$availableExpressionFields = [];
			$availableResultFields     = [];
			$totalElements             = count($elements);

			for ($i = 0; $i < $totalElements; $i++)
			{
				if (in_array($elements[$i]->value_type, $allowedExpressionFields))
				{
					$availableExpressionFields[] = [
						'text'       => '[' . $elements[$i]->alias . ']',
						'val'        => '[' . $elements[$i]->alias . ']',
						'value_type' => $elements[$i]->value_type,
						'selected'   => false,
					];
				}
				if (in_array($elements[$i]->value_type, $allowedResultFields))
				{
					$availableResultFields[] = [
						'text'       => '[' . $elements[$i]->alias . ']',
						'val'        => '[' . $elements[$i]->alias . ']',
						'value_type' => $elements[$i]->value_type,
						'selected'   => false,
					];
				}
			}

			if ($this->formId > 0)
			{
				//get expression
				$query->clear();

				$query->select('*');
				$query->from($db->quoteName('#__formea_form_cores'));
				$query->where($db->quoteName('form_id') . ' = ' . $db->quote($this->formId));
				$query->where($db->quoteName('corename') . ' = ' . $db->quote('Calculations'));
				$db->setQuery($query);
				$coreForm = $db->loadObject();
				if (!empty($coreForm))
				{
					$params     = new \Joomla\Registry\Registry($coreForm->params);
					$calcParams = $params->get('expressions');

					if (!empty($calcParams))
					{
						$expressions = $params->get('expressions.expressionLists');

						$expressions      = json_decode($expressions);
						$totalExpressions = count($expressions);
						for ($j = 0; $j < $totalExpressions; $j++)
						{
							$expressionLists[] = [
								'expression'            => $expressions[$j]->expression,
								'field'                 => $expressions[$j]->field,
								'fieldIds'              => $expressions[$j]->fieldIds,
								'isOpen'                => false,
								'isClosing'             => false,
								'availableResultFields' => $availableResultFields,
								'resultFieldOpen'       => false,
								'resultFieldClosing'    => false,
								'settingFieldClosing'   => false,
								'settingFieldOpen'      => false,
								'setting'               => $expressions[$j]->setting
							];
						}
					}
				}
			}


			$ret = [
				'langString'                => $langStringIni,
				'intro'                     => $intro,
				'expressions'               => $expressionLists,
				'allowedExpressionFields'   => $allowedExpressionFields,
				'allowedResultFields'       => $allowedResultFields,
				'defaultAvailableField'     => ['text' => Text::_('JNONE'), 'val' => 0],
				'availableResultFields'     => $availableResultFields,
				'availableExpressionFields' => $availableExpressionFields,
				'decimalOptions'            => $decimalOptions,
				'resultTypeOptions'         => $resultTypeOptions,
				'defaultResultSetting'      => $defaultResultSetting
			];

			return $ret;
		}

	}
