<?php
namespace Entity;

class CashBookDocument extends \App\Entity\GeneralAbstract
{

	/**
	 * Indicate if the operations available for the current entity must be done inside a transaction or not.
	 * @var Boolean
	 */
	protected $saveInsideTransaction = true;

	protected $addAndUpdateDateTimeFormat = 'timestamp'; // TODO: to be eliminated after the table columns are renamed and replaced with datetime


	/**
	 * (non-PHPdoc)
	 * @see App\Entity.SelectAbstract::setTableName()
	 */
	protected function setTableName(): void
	{
		global $DBTCashBookDocuments;
		$this->tableName = $DBTCashBookDocuments;
	}

	/**
	 * Static instantiation of a blocking entity.
	 * @param Integer $idEntity
	 * @return CashBookDocument
	 */
	static public function block($idEntity) {
		return new self('block', $idEntity);
	}


	/**
	 * Static instantiation of an unblocking entity.
	 * @param Integer $idEntity
	 * @return CashBookDocument
	 */
	static public function unblock($idEntity) {
		return new self('unblock', $idEntity);
	}

	/**
	 * (non-PHPdoc)
	 * @see App\Entity.SelectAbstract::getAttribute()
	 */
	protected function getAttribute($var)
	{
		// check each possible values
		switch ($var) {

			// agency bank account
			case 'agencyBankAccount': {
				return \Entity\AgencyBankAccount::select($this->fields['idAgencyBankAccount'], $this->selectForUpdate);
			}

			// the name of the category (not cached as it is a lang var)
			case 'categoryName': {
				$_LANG = \App\Loader_Lang::getInstance()->getGlobal();
				return $_LANG['cashBook']['documentCategory'][$this->fields['category']];
			}

			// the type name of the document (not cached as it is a lang var)
			case 'typeName': {
				$_LANG = \App\Loader_Lang::getInstance()->getGlobal();
				return $_LANG['cashBook']['documentTypes'][$this->fields['category']][$this->fields['type']];
			}

			// extra info
			case 'extraInfo': {
				if (!is_array($this->fields['extraInfo'])) {
					if ($this->fields['extraInfo']) {
						$this->fields['extraInfo'] = unserialize($this->fields['extraInfo']);
					}
					else {
						$this->fields['extraInfo'] = [];
					}
				}
				return $this->fields['extraInfo'];
			}

			// gets an associative array of list of documents (indexed by their id) which containes all the documents generated on this pivot
			case 'documentsList': {
				if (!array_key_exists($var, $this->fields)) {
					$dlObj = new \App\Entity\Utils\PivotDocumentsList('cashBookDoc', $this->id);
					$this->fields[$var] = $dlObj->getDocumentsList($this->selectForUpdate);
				}
				return $this->fields[$var];
			}

			// user
			case 'user': {
				return \Entity\User::select($this->fields['idUser'], $this->selectForUpdate);
			}

			// office
			case 'office': {
				return \Entity\Office::select($this->fields['idOffice'], $this->selectForUpdate);
			}

			// issueUser
			case 'issueUser': {
				return \Entity\User::select($this->fields['idIssueUser'], $this->selectForUpdate);
			}

			// blockUser
			case 'blockUser': {
				return \Entity\User::select($this->fields['idBlockUser'], $this->selectForUpdate);
			}

			// addUser
			case 'addUser': {
				return \Entity\User::select($this->fields['idAddUser'], $this->selectForUpdate);
			}

			// updateUser
			case 'updateUser': {
				return \Entity\User::select($this->fields['idUpdateUser'], $this->selectForUpdate);
			}

			// the rest of the fields (most of them are just copied)
			default: {
				return parent::getAttribute($var);
			}
		}
	}

	/**
	 * (non-PHPdoc)
	 * @see App\Entity.GeneralAbstract::setAttribute()
	 */
	protected function setAttribute($var, $value)
	{
		// check that operation is okay
		if ($this->operation!='insert' and $this->operation!='update') {
			throw new \Exception('You can use __set magic method only with insert/update operation in `'.__CLASS__.'` class.');
		}

		// check each possible field value
		switch ($var) {
			// simple fields
			case '_dontExport': case 'type': case 'date': case 'number': case 'value': case 'currency': case 'partner': case 'idAgencyBankAccount':
			case 'explanations': case 'comments': case 'idUser':  case 'idIssueUser': case 'issueTime': {
				$this->fields[$var]=$value;
				break;
			}

			// id office
			case 'idOffice': {
				// only works with 'insert' operation
				if ($this->operation=='update') {
					 throw new \Exception("You can only 'insert' the idOffice of the cashbook documents.");
				}
				// store value
				$this->fields[$var]=$value;
				break;
			}

			// category
			case 'category': {
				// only works with 'insert' operation
				if ($this->operation=='update'){
					throw new \Exception("You can only 'insert' the category of the cashbook documents.");
				}
				// if everything is okay - store the category in the object
				$this->fields[$var]=$value;
				break;
			}

			// extra info - updates only the set keys
			case 'extraInfo': {
				if (!is_array($value)) {
					throw new \Exception("The field `extraInfo` can only be set as an array for the `".__CLASS__."` entity.");
				}
				$this->fields[$var]=$value;
				break;
			}

			// the field is not valid
			default: {
				throw new \Exception("The field '$var' is not valid for the `".__CLASS__."` entity.");
			}
		}
	}

	/**
	 * (non-PHPdoc)
	 * @see App\Entity.GeneralAbstract::save_filterSaveData()
	 */
	protected function save_filterSaveData(Array $saveData)
	{
		unset($saveData['_dontExport']);

		// operation insert
		if ($this->operation == 'insert') {
			if ($saveData['value']) {
				if ($saveData['category'] == 'cashing') {
					$saveData['value'] = abs(round($saveData['value'], \App\Config\CurrencyDecimals::getCurrencyDecimals($saveData['currency'])));
				}
				else {
					$saveData['value'] = - abs(round($saveData['value'], \App\Config\CurrencyDecimals::getCurrencyDecimals($saveData['currency'])));
				}
			}

			// set extra info as a serialized array
			if ($saveData['extraInfo']) {
				$saveData['extraInfo'] = serialize($saveData['extraInfo']);
			}
			else {
				$saveData['extraInfo'] = '';
			}

			// set id office
			//$saveData['idOffice'] = \Entity\User::select($saveData['idUser'])->idOffice;
		}

		// operation update
		if ($this->operation == 'update') {
			// update the sign of document
			if ($saveData['value']) {
				if (\Entity\CashBookDocument::select($this->getId())->category == 'cashing') {
					$saveData['value'] = abs(round($saveData['value'], \App\Config\CurrencyDecimals::getCurrencyDecimals($saveData['currency'])));
				}
				else {
					$saveData['value'] = - abs(round($saveData['value'], \App\Config\CurrencyDecimals::getCurrencyDecimals($saveData['currency'])));
				}
			}

			// update extraInfo
			if ($saveData['extraInfo']) {
				$extraInfo = \Entity\CashBookDocument::select($this->getId())->extraInfo;
				foreach ($saveData['extraInfo'] as $key => $value) {
					if (is_null($value)) {
						unset ($extraInfo[$key]);
					}
					else {
						$extraInfo[$key] = $value;
					}
				}

				// store the new extra info
				if ($extraInfo) {
					$saveData['extraInfo'] = serialize($extraInfo);
				}
				else {
					$saveData['extraInfo'] = '';
				}
			}
		}

		// operation block
		if ($this->operation == 'block') {
			$saveData = [
				'idBlockUser' => CURRENT_ID_USER,
				'blockTime' => TIMESTAMP,
			];
		}

		// operation unblock
		if ($this->operation == 'unblock') {
			$saveData = [
				'idBlockUser' => 0,
				'blockTime' => 0,
			];
		}

		return $saveData;
	}


	protected function save_finishOperation()
	{
		parent::save_finishOperation();

		$cashbookDocument = self::select($this->id);

		// export doc xml
		if (!$this->fields['_dontExport']) {
			$operation = null;

			if ($this->operation == 'block') {
				$operation = 'confirm';
			}

			if ($this->operation == 'unblock') {
				$operation = 'unconfirm';
			}

			if ($this->operation == 'delete' and $cashbookDocument->issueTime) {
				$operation = 'void';
			}

			if ($operation) {
				try {
					$cashbookDocument = new \App\ExportData\ExportFile\CashBookDocument($this->getId(), $operation);
					$cashbookDocument->writeFile();
				}
				catch (\App\MessagesException $ex) {
					$this->messages->removeSuccess();
					\Log::getInstance()->critical(sprintf('The cashbook document XML was not generated. Error: %s', $ex->getMessagesCollector()->getMessageBulk()));
					$this->messages->addErrorCode('block_exportXmlFailed');
				}
			}
		}
	}
}