<?php

namespace App\AutoProcessRules;

class ImportedDocProcess_Definition extends DefinitionAbstract
{

	/**
	 * List with all available filters
	 * @var array
	 */
	protected $filtersConfig = [
		'docCategory', // cashing/payment
		'forcePartnerMatch',
		'docExternalSystems',
		'customers',
		'corporates',
		'corporateGroups',
		'suppliers',
		'docTypes',
		'docCurrencies',
		'docDate',
		'docAddDate',
		'docUpdateDate',
		'docRemarks',
	];

	/**
	 * List with filters for cache
	 * Value of array represents type of variable
	 * @var array
	 */
	protected $filtersCacheConfig = [
		'docCategory'				=> 'docCategory',
		'docExternalSystems'		=> 'docExternalSystems',
		'customers'					=> 'customer',
		'corporates'				=> 'corporate',
		'suppliers'					=> 'supplier',
		'docTypes' 					=> 'docTypes',
		'docCurrencies'				=> 'currency',
		'docRemarks'				=> 'remarks',
	];

	/**
	 * List with all available fields
	 * @var array
	 */
	protected $fieldsConfig = [
		'invoiceSuggestionsMode',
		'idUser',
		'remarks',
		'invoiceIssueStatus',
		'invoiceCurrency'
	];

	/**
	 * List with fields for cached
	 * Value of array represents type of variable
	 * @var array
	 */
	protected $fieldsCacheConfig = [
		'idUser'					=> 'responsibleUser',
	];

	/**
	 * (non-PHPdoc)
	 * @see \App\AutoProcessRules\DefinitionAbstract::checkFields()
	 */
	protected function checkFields(\App\MessagesCollector $msgs)
	{

		// check invoiceSuggestionsMode
		if (!$this->fields['invoiceSuggestionsMode']) {
			$msgs->addWarning('You did not set the invoice suggestions mode.');
		} else {
			if (!in_array($this->fields['invoiceSuggestionsMode'], ['documentInvoices', 'partnerInvoices', 'allInvoices'])) {
				$msgs->addWarning('Invalid invoice suggestions mode.');
			}
		}

		// check order responsible user
		if (!$this->fields['idUser']) {
			$msgs->addWarning('No document responsible selected.');
		} else {
			$userEnt = \Entity\User::select($this->fields['idUser']);
			if (!$userEnt->recordExists() or $userEnt->deleted) {
				$msgs->addWarning('Invalid document responsible user id.');
			}
		}

		// check invoiceIssueStatus
		if ($this->fields['invoiceIssueStatus'] and !in_array($this->fields['invoiceIssueStatus'], ['notIssued', 'issued'])) {
			$msgs->addWarning('Invalid invoice issue status.');
		}

		// check invoice currency
		if ($this->fields['invoiceCurrency']) {
			if (!\App\Config\Currencies::getInstance()->check($this->fields['invoiceCurrency']) and $this->fields['invoiceCurrency']!='docCurrency') {
				$msgs->addWarning('Invalid invoice currency set.');
			}
		}

	}

	/**
	 * (non-PHPdoc)
	 * @see \App\AutoProcessRules\DefinitionAbstract::checkFilters()
	 */
	protected function checkFilters(\App\MessagesCollector $msgs)
	{

		// check doc category
		if ($this->filters['docCategory']!='cashing' and $this->filters['docCategory']!='payment') {
			$msgs->addWarning('Invalid document category: '.$this->filters['docCategory']);
		}
		if ( ($this->filters['customers'] or $this->filters['corporates']) and $this->filters['docCategory']!='cashing' ) {
			$msgs->addWarning('You can set customers/corporates only for `cashing` doc category.');
		}
		if ( $this->filters['suppliers'] and $this->filters['docCategory']!='payment' ) {
			$msgs->addWarning('You can set suppliers only for `payment` doc category.');
		}

		// check doc types
		if ($this->filters['docTypes'] and !is_array($this->filters['docTypes'])) {
			$msgs->addError("The doc types must be set as a list.");
		} else {
			// check cashing docs
			if ($this->filters['docCategory']=='cashing') {
				foreach ($this->filters['docTypes'] as $docType) {
					if (!\App\Config\CashingDocuments::getInstance()->isActive($docType)) {
						$msgs->addWarning(sprintf('Invalid cashing doc type `%s`.', $docType));
					}
				}
			}
			// check payment docs
			if ($this->filters['docCategory']=='payment') {
				foreach ($this->filters['docTypes'] as $docType) {
					if (!\App\Config\PaymentDocuments::getInstance()->isActive($docType)) {
						$msgs->addWarning(sprintf('Invalid payment doc type `%s`.', $docType));
					}
				}
			}
		}

		// check external systems
		if ($this->filters['docExternalSystems']) {
			if (!is_array($this->filters['docExternalSystems']) ) {
				$msgs->addError('The external systems must be set as a list.');
			}
			else {
				foreach ($this->filters['docExternalSystems'] as $idSys) {
					$sysEnt = \Entity\ImportedDocumentsSystem::select($idSys);
					if (!$sysEnt->recordExists() or $sysEnt->deleted) {
						$msgs->addError(sprintf('Invalid doc external system id - %s.', $idSys));
					}
				}
			}
		}

		// check currencies
		if ($this->filters['docCurrencies']) {
			if (!is_array($this->filters['docCurrencies'])) {
				$msgs->addError('The doc currencies must be set as a list.');
			} else {
				foreach ($this->filters['docCurrencies'] as $curr) {
					if (!\App\Config\Currencies::getInstance()->check($curr)) {
						$msgs->addWarning(sprintf('Invalid doc currency: %s', $curr));
					}
				}
			}
		}

		// check doc date
		if ($this->filters['docDate']) {
			if ( !($this->filters['docDate'] instanceof \App\Utils\SmartDateInterval) ) {
				$msgs->addError('Invalid smart date interval for doc date.');
			} else {
				$msgsTemp = new \App\MessagesCollector();
				$this->filters['docDate']->check($msgsTemp);
				$msgs->appendMessages($msgsTemp, 'Doc date problem: %s');
			}
		}
		// check doc add date
		if ($this->filters['docAddDate']) {
			if ( !($this->filters['docAddDate'] instanceof \App\Utils\SmartDateInterval) ) {
				$msgs->addError('Invalid smart date interval for doc date.');
			} else {
				$msgsTemp = new \App\MessagesCollector();
				$this->filters['docAddDate']->check($msgsTemp);
				$msgs->appendMessages($msgsTemp, 'Doc add date problem: %s');
			}
		}

		// check doc last update date
		if ($this->filters['docUpdateDate']) {
			if ( !($this->filters['docUpdateDate'] instanceof \App\Utils\SmartDateInterval) ) {
				$msgs->addError('Invalid smart date interval for last update date.');
			} else {
				$msgsTemp = new \App\MessagesCollector();
				$this->filters['docUpdateDate']->check($msgsTemp);
				$msgs->appendMessages($msgsTemp, 'Doc last update date problem: %s');
			}
		}

		// check doc remark(s)
		if ($this->filters['docRemarks']) {
			if (!is_array($this->filters['docRemarks'])) {
				$msgs->addError('The doc remark(s) must be set as a list.');
			} else {
				foreach($this->filters['docRemarks'] as $idx=>$rmDet) {
					if (!in_array($rmDet['op'], ['anyValue', 'noValue', 'equal', 'notEqual'])) {
						$msgs->addError(sprintf('The operation for the doc remark #%s is not valid.', $idx+1));
					}
					if (!$rmDet['var']) {
						$msgs->addWarning(sprintf('The variable name for the doc remark #%s is not set.', $idx+1));
					}
					if (isset($rmDet['val']) and !is_array($rmDet['val'])) {
						$msgs->addError(sprintf('The variable value for the doc remark #%s is not valid.', $idx+1));
					}
					if ( ($rmDet['op']=='equal' or $rmDet['op']=='notEqual') and !$rmDet['val']) {
						$msgs->addWarning(sprintf('The variable value for the doc remark #%s is not set.', $idx+1));
					}
				}
			}
		}

	}


	/**
	 *
	 * {@inheritDoc}
	 * @see \App\AutoProcessRules\DefinitionAbstract::getDescriptionFilters()
	 */
	public function getDescriptionFilters()
	{

		// lang
		$_LANG = \App\Loader_Lang::getInstance()->getAll();

		// filters
		$filters = $this->getFilters();
		$descrFilters = [];

		// FILTERS
		foreach ($this->filtersConfig as $filterName) {
			switch ($filterName) {
				case 'docCategory':
					if ($filters['docCategory']) {
						$descrFilters[] =  sprintf("doc category - %s", $filters['docCategory']);
					}
				break;

				case 'forcePartnerMatch':
					$descrFilters[] = sprintf("force partner match - %s", ($filters['forcePartnerMatch']?$_LANG['yes']:$_LANG['no']));
				break;

				case 'docExternalSystems':
					if ($filters['docExternalSystems']) {
						$extSystems = [];
						foreach ($filters['docExternalSystems'] as $idSys) {
							$extSystems[] = \Entity\ImportedDocumentsSystem::select($idSys)->name;
						}
						$descrFilters[] = sprintf("doc external systems - %s", implode(', ', $extSystems));
					}
				break;

				case 'docTypes':
					if ($filters['docTypes']) {
						$descrFilters[] =  sprintf("doc types - %s", implode(', ', $filters['docTypes']));
					}
				break;

				case 'docCurrencies':
					if ($filters['docCurrencies']) {
						$descrFilters[] =  sprintf("doc currencies - %s", implode(', ', $filters['docCurrencies']));
					}
				break;

				case 'docDate': case 'docAddDate': case 'docUpdateDate':
					if ($filters[$filterName] ){
						if ($filters[$filterName]->getReadableDescription()) {
							if ($filterName=='docDate') {
								$descrFilters[] = sprintf("doc date - %s", $filters[$filterName]->getReadableDescription());
							} elseif ($filterName=='docAddDate') {
								$descrFilters[] = sprintf("doc add date - %s", $filters[$filterName]->getReadableDescription());
							} elseif ($filterName=='docUpdateDate') {
								$descrFilters[] = sprintf("doc last update date - %s", $filters[$filterName]->getReadableDescription());
							}
						}
					}
				break;

				case 'docRemarks':
					if ($filters['docRemarks']) {
						foreach ($filters['docRemarks'] as $value) {
							if ($value['op'] == 'equal') {
								$remark = sprintf('%s equal with %s', $value['var'], implode(', ', $value['val']));
							}
							elseif ($value['op'] == 'notEqual') {
								$remark = sprintf('%s not equal with %s', $value['var'], implode(', ', $value['val']));
							}
							else {
								$remark = sprintf('%s %s', $value['var'], $value['op']);
							}
							$descrFilters[] = sprintf('doc remarks -  %s', $remark);
						}
					}
				break;

				default: {
					$this->populateDescriptionCommonFilters($descrFilters, $filterName);
				}

			}

		}

		return implode('; ',$descrFilters);

	}



	/**
	 *
	 * {@inheritDoc}
	 * @see \App\AutoProcessRules\DefinitionAbstract::getDescriptionFields()
	 */
	public function getDescriptionFields()
	{

		// fields
		$fields = $this->getFields();
		$descrFields = [];

		// FIELDS
		foreach ($this->fieldsConfig as $fieldName) {
			switch ($fieldName) {
				case 'invoiceSuggestionsMode':
					if ($fields['invoiceSuggestionsMode']) {
						$descrFields[] = sprintf("invoice suggestions mode - %s", $fields['invoiceSuggestionsMode']);
					}
				break;

				case 'invoiceIssueStatus':
					if ($fields['invoiceIssueStatus']) {
						$descrFields[] = sprintf("invoice issue status - %s", $fields['invoiceIssueStatus']);
					}
				break;

				case 'invoiceCurrency':
					if ($fields['invoiceCurrency']) {
						$descrFields[] = sprintf("invoice currency - %s", $fields['invoiceCurrency']);
					}
				break;

				case 'idUser':
					if ($fields['idUser']) {
						$descrFields[] = sprintf("user - %s", \Entity\User::select($fields['idUser'])->name);
					}
				break;

				case 'remarks':
					if ($fields['remarks']) {
						$descrFields[] = sprintf("remarks - %s", $fields['remarks']);
					}
				break;

			}
		}

		return implode('; ',$descrFields);

	}

}

