<?php

namespace Entity;

class Validator_AutoProcessRule extends \App\Entity\Utils\Extension_ValidateDefaultAbstract
{


	protected function check_insert()
	{
		// get current fields details
		$fields = $this->entity->getFields();

		// current collected messages
		$currMessages = $this->entity->getMessages();

		$ruleObj = $fields['object'];

		// check the object
		if ( !$ruleObj or !($ruleObj instanceof \App\AutoProcessRules\DefinitionAbstract) ) {
			$currMessages->addErrorCode('insert_noObject');
		} else {
			// check rule size (when serialized)
			$ruleObjSer = serialize($ruleObj);
			if (strlen($ruleObjSer)>65000) {
				$currMessages->addErrorCode('serializeLenTooLarge');
			}
			try {
				$ruleObj->check();
			} catch (\App\MessagesException $e) {
				$currMessages->addMessageCollector($e->getMessagesCollector());
			}
		}

		// check responsible users list
		if ($fields['responsibleUsers']) {
			foreach ($fields['responsibleUsers'] as $idUser) {
				// check user
				$user = \Entity\User::select($idUser);
				if (!$user->recordExists()) {
					$currMessages->addErrorCode('responsibleUserInvalidId');
				}
				elseif ($user->deleted) {
					$currMessages->addWarningCode('responsibleUserDeleted');
				}
			}
		}

		// check month days
		if (!$fields['monthDays']) {
			$currMessages->addWarningCode('noMonthDay', 'monthDays');
		}
		else {
			foreach($fields['monthDays'] as $day) {
				if ($day!='lastDom' and (!is_numeric($day) or $day<1 or $day>31)) {
					$currMessages->addWarningCode('invalidMonthDay', 'monthDays', $day);
				}
			}
		}
		// check week days
		if (!$fields['weekDays']) {
			$currMessages->addWarningCode('noWeekDay', 'weekDays');
		} else {
			foreach($fields['weekDays'] as $day) {
				if (!is_numeric($day) or $day<0 or $day>6) {
					$currMessages->addWarningCode('invalidWeekDay', 'weekDays', $day);
				}
			}
		}

		// check client type
		$ruleType = $ruleObj->getType();
		if ($ruleType=='ImportedDocProcess' or $ruleType=='CashPayDocIssue' or $ruleType=='ImportedDocIssue') {
			if (!in_array($fields['clientType'], ['corporate', 'customer', 'supplier']) ) {
				$currMessages->addWarningCode('invalidClientType', 'clientType');
			}
		} else {
			if (!in_array($fields['clientType'], ['corporate', 'customer']) ) {
				$currMessages->addWarningCode('invalidClientType', 'clientType');
			}
		}

	}


	protected function isAvailable_update()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// lock record (if it is the case)
		$apRule = AutoProcessRule::selectForUpdate($this->entity->getId());

		if (!$apRule->recordExists()) {
			$currentMessages->addWarningCode('update_invalidId');
		}
		elseif ($apRule->deleted) {
			$currentMessages->addWarningCode('update_deleted');
		}
	}


	protected function check_update()
	{

		// get current fields details
		$fields	= $this->entity->getFields();

		// current collected messages
		$currMessages = $this->entity->getMessages();

		// check the object
		$ruleObj = $fields['object'];
		if ($ruleObj) {
			// check the type of object
			if (!($ruleObj instanceof \App\AutoProcessRules\DefinitionAbstract)) {
				$currMessages->addErrorCode('insert_noObject');
			}
			// check rule size (when serialized)
			$ruleObjSer = serialize($ruleObj);
			if (strlen($ruleObjSer)>65000) {
				$currMessages->addErrorCode('serializeLenTooLarge');
			}
			// check the rule
			try {
				$ruleObj->check();
			} catch (\App\MessagesException $e) {
				$currMessages->addMessageCollector($e->getMessagesCollector());
			}
		}

		// check responsible users list
		if ($fields['responsibleUsers']) {
			foreach ($fields['responsibleUsers'] as $idUser) {
				// check user
				$user = \Entity\User::select($idUser);
				if (!$user->recordExists()) {
					$currMessages->addErrorCode('responsibleUserInvalidId');
				}
				elseif ($user->deleted) {
					$currMessages->addWarningCode('responsibleUserDeleted');
				}
			}
		}

		// check month days
		if (array_key_exists('monthDays', $fields)) {
			if (!$fields['monthDays']) {
				$currMessages->addWarningCode('noMonthDay', 'monthDays');
			} else {
				foreach($fields['monthDays'] as $day) {
					if ($day!='lastDom' and (!is_numeric($day) or $day<1 or $day>31)) {
						$currMessages->addWarningCode('invalidMonthDay', 'monthDays', $day);
					}
				}
			}
		}

		// check week days
		if (array_key_exists('weekDays', $fields)) {
			if (!$fields['weekDays']) {
				$currMessages->addWarningCode('noWeekDay', 'weekDays');
			} else {
				foreach($fields['weekDays'] as $day) {
					if (!is_numeric($day) or $day<0 or $day>6) {
						$currMessages->addWarningCode('invalidWeekDay', 'weekDays', $day);
					}
				}
			}
		}

		// check client type
		if ($ruleObj and array_key_exists('clientType', $fields)) {
			$ruleType = $ruleObj->getType();
			if ($ruleType=='ImportedDocProcess' or $ruleType=='CashPayDocIssue' or $ruleType=='ImportedDocIssue') {
				if (!in_array($fields['clientType'], ['corporate', 'customer', 'supplier']) ) {
					$currMessages->addWarningCode('invalidClientType', 'clientType');
				}
			} else {
				if (!in_array($fields['clientType'], ['corporate', 'customer']) ) {
					$currMessages->addWarningCode('invalidClientType', 'clientType');
				}
			}
		}
	}


	protected function isAvailable_delete()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// check if task category is not already deleted
		$apRule = AutoProcessRule::selectForUpdate($this->entity->getId());

		if (!$apRule->recordExists()) {
			$currentMessages->addWarningCode('delete_invalidId');
		}
		elseif ($apRule->deleted) {
			$currentMessages->addWarningCode('delete_deleted');
		}

	}


	protected function isAvailable_execute()
	{

		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// check if task category is not already deleted
		$apRule = AutoProcessRule::selectForUpdate($this->entity->getId());

		if (!$apRule->recordExists()) {
			$currentMessages->addWarningCode('execute_invalidId');
		} elseif ($apRule->deleted) {
			$currentMessages->addWarningCode('execute_deleted');
		} elseif (!$apRule->active) {
			$currentMessages->addWarningCode('execute_inactive');
		}

		// check week days and month days
		$weekday = \Engine\DateTime::create()->format('w');
		if (!in_array($weekday, $apRule->weekDays)) {
			$currentMessages->addWarningCode('execute_wrongWeekDay');
		}
		// check if this is the last day of the month
		if (TODAY_DAY==date('t')) {
			$isLastDom = true;
		} else {
			$isLastDom = false;
		}
		if ( !in_array(TODAY_DAY, $apRule->monthDays) and (!$isLastDom or !in_array('lastDom', $apRule->monthDays)) ) {
			$currentMessages->addWarningCode('execute_wrongMonthDay');
		}
		// check startTime and endTime
		$time = \Engine\DateTime::create()->format('H:i:s');
		if ($apRule->startTime and $apRule->startTime>$time) {
			$currentMessages->addWarningCode('execute_wrongStartTime', '', $apRule->startTime);
		}
		if ($apRule->endTime and $apRule->endTime<$time) {
			$currentMessages->addWarningCode('execute_wrongEndTime', '', $apRule->endTime);
		}

		// check max executions count
		if ($apRule->maxDailyExecutionsCount) {
			$dt = $apRule->lastExecutionDateTime;
			if (!$dt->isEmpty() and $dt->isValid() and $dt->formatDateIso()==TODAY_ISO) {
				if ($apRule->currentDayExecutionsCount>=$apRule->maxDailyExecutionsCount) {
					$currentMessages->addWarningCode('execute_maxExecCount');
				}
			}
		}

	}


	protected function check_execute()
	{

		$fields = $this->entity->getFields();

		if (!$fields['ruleLogs']) {
			throw new \Exception('No rule logs object set for rule execution.');
		}

	}

}
