<?php

namespace App\AutoProcessRules;


class ImportedDocIssue_Definition extends DefinitionAbstract
{

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

	/**
	 * List with filters for cache
	 * @var array
	 */
	protected $filtersCacheConfig = [
		'invoiceRespUser' => 	'responsibleUser',
		'docCurrencies' =>		'currency',
		'customers' =>			'customer',
		'corporates' =>			'corporate',
		'suppliers' =>			'supplier',
	];

	/**
	 * List with all available fields
	 * @var array
	 */
	protected $fieldsConfig = [
		'issueDocType',
		'idIssueUser',
		'idDocTemplate',
		'idDocSeries',
		'sendEmail',
		'emailRecipientPartner',
		'emailRecipientDocResp',
		'emailRecipientDocRemarkVar',
		'emailRecipientManual',
		'sendReadReceipt',
		'selfBcc',
	];

	/**
	 * List with fields for cached
	 * Value of array represents type of variable
	 * @var array
	 */
	protected $fieldsCacheConfig = [
		'invoiceIdIssueUser' =>		'issueUser',
		'idInvoiceTemplate' =>		'docTemplate',
		'idDocSeries' =>			'docSeries',
	];

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

		// check issueDocType
		if (!$this->fields['issueDocType'] or !\App\Config\IssueDocuments::getInstance()->exists($this->fields['issueDocType'])) {
			$msgs->addWarning('Issue doc type not selected or not valid.');
		} else {
			if (\App\Config\IssueDocuments::getInstance()->getDocCategory($this->fields['issueDocType'])!=$this->filters['docType']) {
				$msgs->addWarning('The issue doc type is not associated to the selected cashing/payment document.');
			}
			if (!\App\Config\IssueDocuments::getInstance()->isMainDocOnPivot($this->fields['issueDocType'])) { // this is only to control that a document is not automatically issued multiple times
				$msgs->addWarning('The issue doc type must be `main doc on pivot` to issue the imported document.');
			}
		}

		// check issue user
		if ($this->fields['idIssueUser']) {
			$userEnt = \Entity\User::select($this->fields['idIssueUser']);
			if (!$userEnt->recordExists() or $userEnt->deleted) {
				$msgs->addError('Invalid issue user id.');
			}
		}
		if ($this->fields['sendEmail'] and !$this->fields['idIssueUser']) {
			$msgs->addWarning('You must select the issue user if you want to send the email.');
		}

		// id invoice template
		if (!$this->fields['idDocTemplate']) {
			$msgs->addWarning('No doc template selected.');
		} else {
			$tpl = \Entity\DocumentTemplate::select($this->fields['idDocTemplate']);
			if (!$tpl->recordExists() or $tpl->deleted) {
				$msgs->addWarning('Invalid/deleted doc template.');
			} else {
				if ($tpl->docType!=$this->fields['issueDocType']) {
					$msgs->addWarning('The selected template is not associatd to the selected issue doc type.');
				}
			}
		}

		// id invoice series
		if ($this->fields['idDocSeries']) {
			$ser = \Entity\DocumentSeries::select($this->fields['idDocSeries']);
			if (!$ser->recordExists() or $ser->deleted) {
				$msgs->addWarning('Invalid/deleted invoice series.');
			} else {
				if (!in_array($this->fields['issueDocType'], $ser->documentTypes)) {
					$msgs->addWarning('The selected series is not associatd to the selected doc type.');
				}
			}
		}

		// check emails
		if ($this->fields['sendEmail'] and (!$this->fields['emailRecipientPartner'] and !$this->fields['emailRecipientDocResp'] and !strlen($this->fields['emailRecipientDocRemarkVar']) and !$this->fields['emailRecipientManual'])) {
			$msgs->addWarning('You must select at least one of the four types of recipients (client, invoice responsible, document remark, or manually inputted email address)');
		}

		// check manual addresses
		if ($this->fields['sendEmail'] and $this->fields['emailRecipientManual']) {
			// check emails
			$emails = array_map('trim', preg_split('/[\;\,]/', $this->fields['emailRecipientManual']));
			foreach($emails as $email) {
				if (!\Engine\Validator::set($email)->isEmail()) {
					$msgs->addWarning(sprintf('The address `%s` is not a valid email address.', $email));
				}
			}
		}

	}


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

		// check docCategory
		if (!in_array($this->filters['docCategory'], ['cashing', 'payment'])) {
			$msgs->addWarning('The doc category is not set/valid.');
		}

		// check doc type
		if (!$this->filters['docType']) {
			$msgs->addWarning('The doc type is not selected.');
		} else {
			if ($this->filters['docCategory']=='cashing' and !\App\Config\CashingDocuments::getInstance()->exists($this->filters['docType'])) {
				$msgs->addWarning('The cashing doc type is not valid.');
			}
			if ($this->filters['docCategory']=='payment' and !\App\Config\PaymentDocuments::getInstance()->exists($this->filters['docType'])) {
				$msgs->addWarning('The payment doc type is not valid.');
			}
		}

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

	}

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

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

		// FILTERS
		foreach ($this->filtersConfig as $filterName) {
			switch ($filterName) {

				case 'docCategory':
					$descrFilters[] = sprintf("doc category - %s", $filters['docCategory']);
				break;

				case 'docType':
					$descrFilters[] = sprintf("doc type - %s", $filters['docType']);
				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 'docDate': case 'docAddDate':
					if ($filters[$filterName] ){
						if ($filters[$filterName]->getReadableDescription()) {
							$descrFilters[] = $filterName.' - '.$filters[$filterName]->getReadableDescription();
						}
					}
				break;

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

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

			}
		}

		return  implode('; ',$descrFilters);

	}


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

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

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

		// FIELDS
		foreach ($this->fieldsConfig as $fieldName) {
			switch ($fieldName) {
				case 'issueDocType':
					if ($fields['issueDocType']) {
						$descrFields[] = sprintf("issue doc type - %s", \App\Config\IssueDocuments::getInstance()->getDocTypeName($fields['issueDocType']) );
					}
				break;

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

				case 'idDocTemplate':
					if ($fields['idDocTemplate']) {
						$descrFields[] = sprintf("doc template - %s", \Entity\DocumentTemplate::select($fields['idDocTemplate'])->name);
					}
				break;

				case 'idDocSeries':
					if ($fields['idDocSeries']) {
						$descrFields[] = sprintf("doc series - %s", \Entity\DocumentSeries::select($fields['idDocSeries'])->code);
					}
				break;

				case 'sendEmail': case 'selfBcc': case 'sendReadReceipt': case 'emailRecipientPartner': case 'emailRecipientDocResp':
					if ($fields[$fieldName]) {
						$descrFields[] = $fieldName.' - '.$_LANG['yes'];
					}
				break;

				case 'emailRecipientDocRemarkVar':
					if ($fields[$fieldName]) {
						$descrFields[] = 'recipient document remark var - '.$fields[$fieldName];
					}
				break;

				case 'emailRecipientManual':
					if ($fields['emailRecipientManual']) {
						$descrFields[] = sprintf("send to other addresses - %s", $fields['emailRecipientManual']);
					}
				break;

			}
		}

		return implode('; ',$descrFields);

	}

}
