<?php

namespace App\Spotlight\Source;

class CurrencyConvert extends \App\Spotlight\SourceAbstract
{
	/**
	 * The collected records to be suggested
	 * @var array
	 */
	private $records = [];

	/**
	 * Stores the common langs (components) used for this source.
	 * @var array
	 */
	private $langs = [];

	public function __construct()
	{

		$_LANG = \Engine\Loader_Lang::getInstance()->getGlobal();

		$this->langs = [
			'currConv'	=> ($_LANG['RemoteData']['Spotlight']['CurrencyConvert']['currConvert']?:'Currency convert'),
			'to'		=> ($_LANG['RemoteData']['Spotlight']['CurrencyConvert']['to']?:'to'),
			'at'		=> ($_LANG['RemoteData']['Spotlight']['CurrencyConvert']['at']?:'at'),
			'using'		=> ($_LANG['RemoteData']['Spotlight']['CurrencyConvert']['using']?:'using'),
		];

		parent::__construct();
	}


	/**
	 *
	 * {@inheritDoc}
	 * @see \App\Spotlight\SourceAbstract::determineRecords()
	 */
	protected function determineRecords($offset, $resultsPerPage):array
	{
		// TODO: sa folosesc switch in loc de if?

		// TODO: pune inapoi stealFocus

		$inputFormats = [
			[
				'regexp' => "/^{$this->langs['currConv']}.*$/i",
				'step' => 1,
				'suggestion' => "{$this->langs['currConv']} %s %s {$this->langs['to']} %s",
			],
			[
				'regexp' => "/^{$this->langs['currConv']}"
							."[\s]+(?P<fromValue>[0-9\.]+)"
							.".*$/i",
				'step' => 2,
				'suggestion' => "{$this->langs['currConv']} %s %s {$this->langs['to']} %s",
			],
			[
				'regexp' => "/^{$this->langs['currConv']}"
							."[\s]+(?P<fromValue>[0-9\.]+)"
							."[\s]*(?P<fromCurrency>[A-Z]{3})"
							.".*$/i",
				'step' => 3,
				'suggestion' => "{$this->langs['currConv']} %s %s {$this->langs['to']} %s",
			],
			[
				'regexp' => "/^{$this->langs['currConv']}"
							."[\s]+(?P<fromValue>[0-9\.]+)"
							."[\s]*(?P<fromCurrency>[A-Z]{3})"
							."([\s]*{$this->langs['to']}[\s]*)"
							."(?P<toCurrency>[A-Z]{3})"
							.".*$/i",
				'step' => 4,
				'suggestion' => "{$this->langs['currConv']} %s %s {$this->langs['to']} %s {$this->langs['at']} %s",
			],

			[
				'regexp' => "/^{$this->langs['currConv']}"
							."[\s]+(?P<fromValue>[0-9\.]+)"
							."[\s]*(?P<fromCurrency>[A-Z]{3})"
							."([\s]*{$this->langs['to']}[\s]*)"
							."(?P<toCurrency>[A-Z]{3})"
							."([\s]*{$this->langs['at']}[\s]*)"
							."(?P<date>[0-9\-]+)"
							.".*$/i",
				'step' => 10,
				'suggestion' => "{$this->langs['currConv']} %s %s {$this->langs['to']} %s {$this->langs['at']} %s {$this->langs['using']} %s",
			],

			[
				'regexp' => "/^{$this->langs['currConv']}"
							."[\s]+(?P<fromValue>[0-9\.]+)"
							."[\s]*(?P<fromCurrency>[A-Z]{3})"
							."([\s]*{$this->langs['to']}[\s]*)"
							."(?P<toCurrency>[A-Z]{3})"
							."([\s]*{$this->langs['using']}[\s]*)"
							."(?P<currencyType>.+)"
							.".*$/i",
				'step' => 20,
				'suggestion' => "{$this->langs['currConv']} %s %s {$this->langs['to']} %s {$this->langs['at']} %s {$this->langs['using']} %s",
			],
		];

		$matchedFormat = [	// default value, if nothing matches, this is the result
			'step' => 0,
			'suggestion' => $this->langs['currConv'],
		];

		// try to match the entered string to the internal list of possible formats
		foreach (array_reverse($inputFormats) as $inputFormat) {
			if ($xtr = $this->extractor->findAndStore($inputFormat['regexp'], $this->searchString)) {
				$matchedFormat = $inputFormat;
				$matchedFormat['xtr'] = $xtr->cleanup();
				break;
			}

		}

		// handle the matched case individually

		switch ($matchedFormat['step']) {
			case 0:		// not matched
				if ($this->matchesSearchString($matchedFormat['suggestion'])) {
					// return 'Currency convert' as an example
					$this->records[] = new \App\Spotlight\Record($matchedFormat['suggestion'].' ', 'CurrencyConvert', "spotlight_autocomplete.request(spotlight_autocomplete.getValue());", 5);
				}
			break;

			case 1:		// user entered 'Currency convert'
				// return a list with 'Currency convert 1 EUR to RON' as suggestions
				foreach (\App\Config\Currencies::getInstance()->getSimple() as $curr) {
					$date = 		TODAY_ISO;
					$fromValue = 	1.00;
					$fromCurrency = $curr;
					$toCurrency = 	\App\Config\Currencies::getInstance()->getDefaultCurrency();
					$toValue = 		\App\CurrencyExchange\Rates::getInstance($date)
						->convert($fromValue, $fromCurrency, $toCurrency);

					$label = sprintf($matchedFormat['suggestion'], $fromValue, $fromCurrency, $toCurrency);

					$this->records[] = $this->createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency);
				}
			break;

			case 2:		// user entered 'Currency convert 10'
				// return a list with 'Currency convert 10 EUR to RON' as suggestions
				foreach (\App\Config\Currencies::getInstance()->getSimple() as $curr) {
					$date = 		TODAY_ISO;
					$fromValue = 	(float)$matchedFormat['xtr']->fromValue;
					$fromCurrency = $curr;
					$toCurrency = 	\App\Config\Currencies::getInstance()->getDefaultCurrency();
					$toValue = 		\App\CurrencyExchange\Rates::getInstance($date)
						->convert($fromValue, $fromCurrency, $toCurrency);

					$label = sprintf($matchedFormat['suggestion'], $fromValue, $fromCurrency, $toCurrency);

					$this->records[] = $this->createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency);
				}
			break;

			case 3:		// user entered 'Currency convert 10 EUR'
				// return a list of 'Currency convert 10 EUR to RON' as a selectable example
				foreach (\App\Config\Currencies::getInstance()->getSimple() as $curr) {
					$date = 		TODAY_ISO;
					$fromValue = 	(float)$matchedFormat['xtr']->fromValue;
					$fromCurrency = strtoupper($matchedFormat['xtr']->fromCurrency);
					$toCurrency = 	$curr;
					$toValue = 		\App\CurrencyExchange\Rates::getInstance($date)
						->convert($fromValue, $fromCurrency, $toCurrency);

					$label = sprintf($matchedFormat['suggestion'], $fromValue, $fromCurrency, $toCurrency, \Engine\DateTime::createFromIsoDate($date)->formatDateStd());

					$this->records[] = $this->createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency);
				}
			break;

			case 4:		// user entered 'Currency convert 10 EUR to USD'
				// do the conversion at different dates
				$dates = [
					'today',
					'-1 days',
					'-2 days',
					'-3 days',
					'-1 weeks',
					'-2 weeks',
					'-1 months',
					'-2 months',
					'-3 months',
				];
				foreach ($dates as $date) {
					$date = 		\Engine\DateTime::create($date)->formatDateIso();
					$fromValue = 	(float)$matchedFormat['xtr']->fromValue;
					$fromCurrency = strtoupper($matchedFormat['xtr']->fromCurrency);
					$toCurrency = 	strtoupper($matchedFormat['xtr']->toCurrency);
					$toValue = 		\App\CurrencyExchange\Rates::getInstance($date)
						->convert($fromValue, $fromCurrency, $toCurrency);

					$label = sprintf($matchedFormat['suggestion'], $fromValue, $fromCurrency, $toCurrency, \Engine\DateTime::createFromIsoDate($date)->formatDateStd());

					$this->records[] = $this->createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency);
				}
			break;

			case 10:		// user entered 'Currency convert 10 EUR to USD'
				// do the conversion at different dates
				$dateObj = 		\Engine\DateTime::createFromFormatsArr([\dateHelper::appShortDateFormat(), MYSQL_FORMAT, 'd', 'd-m', 'd m', 'm d',], $matchedFormat['xtr']->date);

				$date = null;
				if ($dateObj->isValid() && !$dateObj->isEmpty()) {
					$date = $dateObj->formatDateIso();
				}
				else {
					$this->records[] = new \App\Spotlight\Record('Invalid date', 'CurrencyConvert', "spotlight_autocomplete.request(spotlight_autocomplete.getValue());", 0, ['color-important', ]);
					break;
				}

				foreach (\App\Config\CurrencyTypes::getInstance()->getAll() as $currencyType) {
					$fromValue = 	(float)$matchedFormat['xtr']->fromValue;
					$fromCurrency = strtoupper($matchedFormat['xtr']->fromCurrency);
					$toCurrency = 	strtoupper($matchedFormat['xtr']->toCurrency);
					$toValue = 		\App\CurrencyExchange\Rates::getInstance($date, $currencyType['code'])
						->convert($fromValue, $fromCurrency, $toCurrency);

					$label = sprintf($matchedFormat['suggestion'], $fromValue, $fromCurrency, $toCurrency, \Engine\DateTime::createFromIsoDate($date)->formatDateStd(), $currencyType['name']);

					$this->records[] = $this->createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency);
				}
			break;

			case 20:		// user entered 'Currency convert 10 EUR to USD'
				// do the conversion at different dates
				$dates = [
					'today',
					'-1 days',
					'-2 days',
					'-3 days',
					'-1 weeks',
					'-2 weeks',
					'-1 months',
					'-2 months',
					'-3 months',
				];

				$currencyType = [];
				foreach (\App\Config\CurrencyTypes::getInstance()->getAll() as $ct) {
					if ($ct['name'] == $matchedFormat['xtr']->currencyType) {
						$currencyType = $ct;
						break;
					}

					if ($ct['code'] == \App\Config\CurrencyTypes::getInstance()->getDefaultCurrencyType()) {
						$currencyType = $ct; // do not break after this one. It's simply loading the default value, and should be overwritten if a match is done
					}
				}

				foreach ($dates as $date) {
					$date = 		\Engine\DateTime::create($date)->formatDateIso();
					$fromValue = 	(float)$matchedFormat['xtr']->fromValue;
					$fromCurrency = strtoupper($matchedFormat['xtr']->fromCurrency);
					$toCurrency = 	strtoupper($matchedFormat['xtr']->toCurrency);
					$toValue = 		\App\CurrencyExchange\Rates::getInstance($date, $currencyType['code'])
						->convert($fromValue, $fromCurrency, $toCurrency);

					$label = sprintf($matchedFormat['suggestion'], $fromValue, $fromCurrency, $toCurrency, \Engine\DateTime::createFromIsoDate($date)->formatDateStd(), $currencyType['name']);

					$this->records[] = $this->createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency);
				}
			break;

			default:
				throw new \Exception("Step {$matchedFormat['step']} is not handled");
		}

		// when using "steal focus" we need to manually sort & count & paginate the results
		// TODO: pagination data isn't visible in here. How should I handle this?
		$this->lastSearchTotalCount = count($this->records);

		return $this->records;
	}

	protected function createRecord($label, $fromValue, $fromCurrency, $toValue, $toCurrency)
	{

		$toCurrDecimals = \App\Config\CurrencyDecimals::getCurrencyDecimals($toCurrency);

		return new \App\Spotlight\Record(
			$label,
			number_format($toValue, $toCurrDecimals),
			sprintf("if(window.prompt('%s =', '%s')){ spotlight_autocomplete.setValue({value:'%s' }); }", $label, round($toValue, $toCurrDecimals), round($toValue, $toCurrDecimals)),
			5
		);
	}

	public function shouldStealFocus()
	{
		return mb_stripos($this->searchString, $this->langs['currConv'])===0;
	}
}
