<?php

namespace App\QcRules;

class Invoice_Filter_ServiceRemark extends FilterRemarkAbstract
{

	/**
	 * The service code for which the current filter applies to (if it is blank, the filter applies for all services).
	 * @var String
	 */
	public $serviceCode;


	/**
	 * Sets the remark var name, operation, value and also the service code
	 * @param String $serviceCode
	 * @param String $remarkVar
	 * @param String $operation
	 * @param Array $values
	 */
	public function __construct($operation=null, ?Array $values=null, $remarkVar=null, $serviceCode=null)
	{
		parent::__construct($operation, $values, $remarkVar);
		$this->serviceCode = $serviceCode;
	}


	/**
	 * (non-PHPdoc)
	 * @see \App\QcRules\FilterAbstract::checkInput()
	 */
	public function checkInput(\App\MessagesCollector $msgs)
	{

		// do the normal check
		$OK = parent::checkInput($msgs);

		// check the service code (if set)
		$serviceCodes = $this->serviceCode ? (array)$this->serviceCode : [] ; // allow compatibility with single value or list of service codes (the new default si array of service codes)
		foreach ($serviceCodes as $serviceCode) {
			if (!\App\Config\Services_Basic::getInstance()->checkService($serviceCode)) {
				$msgs->addWarning(sprintf('The service code `%s` is not valid', $serviceCode));
				$OK = false;
			}
		}

		return $OK;

	}


	/**
	 * (non-PHPdoc)
	 * @see \App\QcRules\FilterAbstract::checkFields()
	 */
	public function checkFields(\App\QcRules\FieldsAbstract $fields, $context='')
	{

		$serviceCodes = $this->serviceCode ? (array)$this->serviceCode : [] ; // allow compatibility with single value or list of service codes (the new default si array of service codes)

		// group invoice rows the service code
		$rmVals = [];
		$foundServices = false;
		foreach ($fields->rowsList as $row) {
			if (!$serviceCodes or in_array($row['serviceCode'], $serviceCodes)) { // filter by service code
				$foundServices = true;
				$rmVals[$row['processedRemarks'][$this->remarkVar]] = true;
			}
		}

		// if no services found - assume rule is ok; but for filters we must return false to stop the validations of the rule but for restrictions we must return true (to skip the condition).
		if (!$foundServices) {
			if ($context=='filter') {
				return false; // skip the rule altogether (does not apply)
			} elseif ($context=='restriction') {
				return true; // skip this condition (it is considered ok)
			} else {
				throw new \Exception("Invalid context `{$context}` - it must be either `filter` or `restriction`.");
			}
		}

		// if some services found - check their remark values
		$rmVals = array_keys($rmVals);
		if ( !$this->checkFields_multiValues($rmVals) ) {
			return false;
		}

		// also apply validators (if any)
		foreach ($rmVals as $rmVal) {
			// check standard validators
			$validators = [];
			if ($this->validatorType) {
				$validators['type'] = $this->validatorType;
			}
			if ($this->validatorLengthMin) {
				$validators['minLength'] = $this->validatorLengthMin;
			}
			if ($this->validatorLengthMax) {
				$validators['maxLength'] = $this->validatorLengthMax;
			}
			if ( $validators and \Engine\Validator::set($rmVal, $validators)->getProblems() ) {
				return false;
			}
		}

		return true;

	}


	/**
	 * (non-PHPdoc)
	 * @see \App\QcRules\FilterAbstract::createDescription()
	 */
	public function createDescription()
	{

		$description = parent::createDescription();

		if ($this->serviceCode) {
			// determine service name
			$serviceCodes = $this->serviceCode ? (array)$this->serviceCode : [] ; // allow compatibility with single value or list of service codes (the new default si array of service codes)
			$servicesNames = [];
			foreach ($serviceCodes as $serviceCode) {
				$servicesNames[] = \App\Config\Services_Basic::getInstance()->getServiceName($serviceCode);
			}
			$serviceName = implode(', ', $servicesNames);
			$_LANG = \App\Loader_Lang::getInstance()->getGlobal();
			$description .= ' - '.$_LANG['QcRules']['filterServiceRemarkDescriptionList'].' '.$serviceName;
		}

		return $description;

	}
}

