<?php

namespace Entity;

class Validator_DocumentSeries extends \App\Entity\Utils\Extension_ValidateDefaultAbstract
{
	/**
	 * Check if user has access to section documents number
	 */
	protected function isAccessible_insert()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// check user access
		if (!\App\UserAccess\CurrentUserAccessFast::getInstance()->hasAccessToOption('Modules/Admin/DocumentSeries-insert')) {
			$currentMessages->addWarningCode('noAccessToOption');
		}

	}

	/**
	 * Check fields for inserting action
	 * @throws \Exception
	 */
	protected function check_insert()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

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

		// CHECK IF DOCUMENT TYPE IS VALID /////////////////////////////////////////////////////////

		// check if list with documents is not empty
		if (!$fields['documentTypes']) {
			$currentMessages->addWarningCode('insert_noDocumentTypes');
		}

		// search for duplicates
		if (count($fields['documentTypes']) != count(array_unique($fields['documentTypes']))) {
			$currentMessages->addWarningCode('duplicateDocumentTypes');
		}

		// validate document type
		if ($fields['documentTypes'] and !$currentMessages->hasErrorOrWarning()) {
			foreach ($fields['documentTypes'] as $documentType) {
				if (!\App\Config\IssueDocuments::getInstance()->isActive($documentType)) {
					$currentMessages->addWarningCode('invalidDocumentType', 'documentType');
				}
			}
		}

		// CHECK THAT START IS SMALLER THAN END ////////////////////////////////////////////////////
		if ($fields['start'] and $fields['end'] and $fields['start'] > $fields['end']) {
			$currentMessages->addWarningCode('startAfterEnd', 'end');
		}

		// CHECK ID OFFICE /////////////////////////////////////////////////////////////////////////
		if ($fields['idOffice']) {
			$officeEnt = \Entity\Office::select($fields['idOffice']);
			if (!$officeEnt->recordExists()) {
				$currentMessages->addErrorCode('idOfficeInvalid');
			}
			elseif ($officeEnt->deleted) {
				$currentMessages->addWarningCode('idOfficeDeleted');
			}
		}

		// CHECK VALIDITY PERIOD
		if (array_key_exists('validStartDate', $fields) and array_key_exists('validEndDate', $fields) and $fields['validStartDate'] and $fields['validEndDate'] and $fields['validStartDate'] > $fields['validEndDate']) {
			$currentMessages->addWarningCode('validStartDateAfterEnd');
		}

		// CHECK THE RESPONSIBLE ID
		if ($fields['idUser']) {
			$user = \Entity\User::select($fields['idUser']);
			if (!$user->recordExists()) {
				$currentMessages->addErrorCode('respUserIdInvalid');
			}
			elseif ($user->deleted) {
				$currentMessages->addWarningCode('respUserDeleted');
			}
		}

		// CHECK THE ALERT NUMBER ( ALERT OFFSET)
		if ($fields['alertNumber']) {
			if ($fields['alertNumber'] >= $fields['end']) {
				$currentMessages->addWarningCode('alertNumberAfterEnd', 'alertNumber');
			}
		}

		// CHECK FIELDS `validUsersList`, `validCurrenciesList`, `validTemplatesList` ///////K = ($this->checkAssociationWithField() and $OK);

	}

	/**
	 * Check fields `validUsersList`, `validCurrenciesList`, `validTemplatesList` and not to set allUsers, allCurrencies, allTemplates with them
	 * @throws \Exception
	 */
	private function checkAssociationWithField()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

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

		// CURRENCIES /////////////////////////////////////////////////////////////////////////////
		if ( (array_key_exists('allCurrencies', $fields) and !array_key_exists('validCurrenciesList', $fields)) or
			(!array_key_exists('allCurrencies', $fields) and array_key_exists('validCurrenciesList', $fields)) ) {
			throw new \Exception("Set either both or none fields allCurrencies and validCurrenciesList.");
		}

		if ($fields['allCurrencies'] and $fields['validCurrenciesList']) {
			$currentMessages->addWarningCode('simultaneousCurrencies');
		}

		if ($fields['validCurrenciesList']) {
			foreach ($fields['validCurrenciesList'] as $currencyCode) {
				if (!\App\Config\Currencies::getInstance()->check($currencyCode)) {
					$currentMessages->addWarningCode('invalidCurrency');
				}
			}
		}

		// USERS //////////////////////////////////////////////////////////////////////////////////
		if ( (array_key_exists('allUsers', $fields) and !array_key_exists('validUsersList', $fields)) or
			(!array_key_exists('allUsers', $fields) and array_key_exists('validUsersList', $fields)) ) {
			throw new \Exception("Set either both or none fields allUsers and validUsersList.");
		}

		if ($fields['allUsers'] and $fields['validUsersList']) {
			$currentMessages->addWarningCode('simultaneousUsers');
		}

		if ($fields['validUsersList']) {
			foreach ($fields['validUsersList'] as $idUser) {
				$userEnt = \Entity\User::select($idUser);
				if (!$userEnt->recordExists()) {
					$currentMessages->addErrorCode('invalidIdUser');
				}
				elseif ($userEnt->deleted) {
					$currentMessages->addWarningCode('userDeleted');
				}
			}
		}

		// TEMPLATES //////////////////////////////////////////////////////////////////////////////
		if ( (array_key_exists('allTemplates', $fields) and !array_key_exists('validTemplatesList', $fields)) or
			(!array_key_exists('allTemplates', $fields) and array_key_exists('validTemplatesList', $fields)) ) {
			throw new \Exception("Set either both or none fields allTemplates and validTemplatesList.");
		}

		if ($fields['allTemplates'] and $fields['validTemplatesList']) {
			$currentMessages->addWarningCode('simultaneousTemplates');
		}

		if ($fields['validTemplatesList']) {
			foreach ($fields['validTemplatesList'] as $idTemplate) {
				$documentTemplateEnt = \Entity\DocumentTemplate::select($idTemplate);
				if (!$documentTemplateEnt->recordExists()) {
					$currentMessages->addErrorCode('invalidTemplate');
				}
				elseif ($documentTemplateEnt->deleted) {
					$currentMessages->addWarningCode('templateDeleted');
				}
			}
		}
	}


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

		// check user access
		if (!\App\UserAccess\CurrentUserAccessFast::getInstance()->hasAccessToOption('Modules/Admin/DocumentSeries-update')) {
			$currentMessages->addWarningCode('noAccessToOption');
		}

	}


	/**
	 * Check if user can update a document series
	 */
	protected function isAvailable_update()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// current entity id
		$currentEntityId = $this->entity->getId();

		// object document series
		$documentSeriesEnt = \Entity\DocumentSeries::selectForUpdate($currentEntityId);

		// check if document series exists
		if (!$documentSeriesEnt->recordExists()) {
			$currentMessages->addErrorCode('update_idInvalid');
		}
		elseif ($documentSeriesEnt->deleted) {
			$currentMessages->addWarningCode('update_idDeleted');
		}
		elseif ($documentSeriesEnt->status == 'END') {
			$currentMessages->addWarningCode('update_seriesStatusBad');
		}
	}

	/**
	 * Check fields for action update
	 * @throws \Exception
	 */
	protected function check_update()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

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

		// current entity id
		$currentEntityId = $this->entity->getId();

		$OK = false;

		// GET SERIES DETAILS AND LOCK THE ROW /////////////////////////////////////////////////////
		$docSeriesDetails = \Entity\DocumentSeries::selectForUpdate($currentEntityId);
		$seriesCfg = $docSeriesDetails->getCFG();

		// get the old next number
		$nextNumber = $docSeriesDetails->nextNumber;

		// get the old end
		$endNumber = $docSeriesDetails->end;

		// CHECK THAT CURRENT NEXT NUMBER IS GREATER THAN THE OLD NEXT NUMBER //////////////////////
		if (array_key_exists('nextNumber', $fields)) {
			if ($fields['nextNumber'] <= $nextNumber) {
				$currentMessages->addWarningCode('update_nextNumberCannotGetSmaller', 'nextNumber');
				$OK = false;
			}
			else {
				$nextNumber = $fields['nextNumber'];
			}
 		}

 		// CHECK THAT END IS GREATER THAN THE NEW nextNumber + 1 ----------------------------------
		if (array_key_exists('end', $fields)) {
			$endNumber = $fields['end'];
		}

		if ($endNumber < $nextNumber) {
			$currentMessages->addWarningCode('update_nextNumberCantExceedEnd');
			$OK = false;
		}

		// FOR INCREASE ACTION CHECK IF FIELD `lastDate` and `increaseNextNumber` are both set or none of them
		if (array_key_exists('lastDate', $fields) and !array_key_exists('increaseNextNumber', $fields)){
			throw new \Exception('You must set both lastDate and increaseNextNumber.');
		}
		if (!array_key_exists('lastDate', $fields) and array_key_exists('increaseNextNumber', $fields)){
			throw new \Exception('You must set both lastDate and increaseNextNumber.');
		}

		// CHECK THAT FIELD `lastDate` IS DATE /////////////////////////////////////////////////////
		if (array_key_exists('lastDate', $fields) and !validDate($fields['lastDate'])) {
			$currentMessages->addWarningCode('lastDateInvalidType');
			$OK = false;
		}

		// CHECK THAT `lastDate` is bigger than old `lastDate`
		if ($seriesCfg['_special']['forceChronologicalUse'] and $fields['lastDate'] and $docSeriesDetails->lastDate and $fields['lastDate'] < $docSeriesDetails->lastDate) {
			$currentMessages->addWarningCode('lastDateWrongValue', '', \Engine\DateTime::isoToStd($docSeriesDetails->lastDate));
			$OK = false;
		}

		// CHECK VALID DATE ///////////////////////////////////////////////////////////////////////
		$validStartDate 	= $docSeriesDetails->validStartDate;
		if (array_key_exists('validStartDate', $fields)) {
			$validStartDate = $fields['validStartDate'];
		}

		$validEndDate 		= $docSeriesDetails->validEndDate;
		if (array_key_exists('validEndDate', $fields)) {
			$validEndDate	= $fields['validEndDate'];
		}

		// check validStartDate and ValidEndDate set both or none
		if ((array_key_exists('validStartDate', $fields) and !array_key_exists('validEndDate', $fields)) or (!array_key_exists('validStartDate', $fields) and array_key_exists('validEndDate', $fields))) {
			throw new \Exception('The start and the end date must be both set or none of them.');
		}

		// check validity period
		if (array_key_exists('validStartDate', $fields) and array_key_exists('validEndDate', $fields) and $fields['validStartDate'] and $fields['validEndDate'] and $fields['validStartDate'] > $fields['validEndDate']) {
			$currentMessages->addWarningCode('validStartDateAfterEnd');
			$OK=false;
		}

		// check the document date (lastDate)
		if ($fields['lastDate'] and ($fields['lastDate'] < $validStartDate or $fields['lastDate'] > $validEndDate)) {
			$currentMessages->addWarningCode('docLastDateNotValid');
			$OK=false;
		}

		// CHECK THE RESPONSIBLE ID
		if ($fields['idUser']) {
			$user = \Entity\User::select($fields['idUser']);
			if (!$user->recordExists()) {
				$currentMessages->addErrorCode('respUserIdInvalid');
				$OK=false;
			}
			elseif ($user->deleted) {
				$currentMessages->addWarningCode('respUserDeleted');
				$OK=false;
			}
		}

		// CHECK THE ALERT NUMBER ( ALERT OFFSET)
		if ($fields['alertNumber']) {
			if ($fields['alertNumber'] >= $endNumber) {
				$currentMessages->addWarningCode('alertNumberAfterEnd', 'alertNumber');
				$OK=false;
			}
		}


		// CHECK FIELDS `validUsersList`, `validCurrenciesList`, `validTemplatesList` /////////////
		$OK = ($this->checkAssociationWithField() and $OK);
	}


	/**
	 * Check if use has access to delete templateDocuments
	 */
	protected function isAccessible_delete()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// check user access
		if (!\App\UserAccess\CurrentUserAccessFast::getInstance()->hasAccessToOption('Modules/Admin/DocumentSeries-delete')) {
			$currentMessages->addWarningCode('noAccessToOption');
		}

	}


	/**
	 * Check if operation delete can be done
	 */
	protected function isAvailable_delete()
	{
		// current collected messages
		$currentMessages = $this->entity->getMessages();

		// current entity id
		$currentEntityId = $this->entity->getId();

		$documentSeries = \Entity\DocumentSeries::selectForUpdate($currentEntityId);

		// check if document series exists
		if (!$documentSeries->recordExists()) {
			$currentMessages->addErrorCode('delete_invalidId');
		}
		elseif ($documentSeries->deleted) {
			$currentMessages->addWarningCode('delete_seriesDeleted');
		}
		elseif ($documentSeries->status != 'END') {
			$currentMessages->addWarningCode('delete_statusNotEnd');
		}
	}

}