<?php

namespace Entity;

// TODO: 'fieldsDetails', 'customFieldsDetails', 'templateContent' - la __set ar trebui sa se stocheze ca array (asa cum se trimit la apelul obiectului) si abia la save() sa faca "serialize"
// TODO: campurile ce contin array serializat ('fieldsDetails', 'customFieldsDetails', 'templateContent', etc) lucreaza si cu serialize() si cu htmlClean(serialize()) acum - ar trebui sa facem un script care sa updateze baza de date iar __get-ul sa lucreze numai cu htmlClean(serialize())

// TODO(extra): campurile i, m, etc sa fie scrise mai uman si la serializare sa se scrie cod si la deserialzare->uman
class DocumentTemplate 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


	/**
	 * Allowed attributes for standard/custom fields.
	 */
	protected $fieldTypes = [
		'i' => 'ignored',
		'o' => 'optional',
		'm' => 'mandatory',
		'r' => 'required',
		'd' => 'disabled',
	];

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

	/**
	 * (non-PHPdoc)
	 * @see App\Entity.SelectAbstract::getAttribute()
	 */
	protected function getAttribute($var)
	{
		switch ($var) {
			// unserialize fields
			case 'customFieldsDetails' : {
				if (!is_array($this->fields[$var])) {
					if ($this->fields[$var]) {
						$value = unserialize($this->fields[$var]);
						foreach ($value as $fields => $attr) {
							$value[$fields]['type'] = $this->fieldTypes[$attr['type']];
						}
						$this->fields[$var] = $value;
					}
					else {
						$this->fields[$var] = [];
					}
				}

				return $this->fields[$var];
			}

			case 'fieldsDetails' : {
				if (!is_array($this->fields[$var])) {
					if ($this->fields[$var]) {
						$value = unserialize($this->fields[$var]);
						// get fields type with long code (eg : mandatory)
						foreach ($value as $fields => $fieldsType) {
							$value[$fields] = $this->fieldTypes[$fieldsType];
						}
						$this->fields[$var] = $value;
					}
					else {
						$this->fields[$var] = [];
					}
				}

				return $this->fields[$var];
			}

		 	case 'templateContent' : {

		 		if (!is_array($this->fields[$var])) {
		 			if ($this->fields[$var]) {

		 				$templateContent = unserialize($this->fields[$var]);

		 				$templateContent['controls'] = array_map(function($c) { // TODO: in DTM some attributes are blank and PHP8 cannot make math operations with blank strings. This should be eliminated once we refactor DTM and we correctly store the template.
		 					foreach(['opacity', 'Wmm', 'Hmm', 'scaleX', 'scaleY'] as $attr) {
		 						if (isset($c['attributes'][$attr])) {
		 							$c['attributes'][$attr] = (float)$c['attributes'][$attr];
		 						}
		 					}
		 					return $c;
		 				}, (array)$templateContent['controls']);

		 				$this->fields[$var] = $templateContent;
		 			}
		 			else {
		 				$this->fields[$var] = [];
		 			}
		 		}

		 		return $this->fields[$var];
		 	}

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

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

			case 'validUsersList': {
				if (!array_key_exists($var, $this->fields)) {
					if ($this->fields['allUsers']) {
						$this->fields[$var] = [];
					}
					else {
						$db = \DB::getInstance();
						global $DBTDocumentsTemplatesUsers;
						$usersAccessListSQL="SELECT `idUser`
							FROM `{$DBTDocumentsTemplatesUsers}`
							WHERE `idTemplate`='{$this->id}'
						";

						$usersAccessList = $db->GetCol($usersAccessListSQL);
						if ($db->ErrorNo()) {
							throw new \DBException('Could not get the list of users associated to a document series.');
						}
						$this->fields[$var] = $usersAccessList;
					}
					return $this->fields[$var];
				}
			}

			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.');
		}

		switch ($var) {
			case 'name': case 'docType': case 'format': case 'fileName': case 'extension': case 'active': case 'allUsers':
				$this->fields[$var] = $value;
			break;

			case 'customFieldsDetails' : case 'fieldsDetails' :  case 'validUsersList' : case 'templateContent':{
				if (!is_array($value)) {
					throw new \Exception("Cannot update document templates for `".__CLASS__."` class if the '$var' parameter is not an array.");
				}

				$this->fields[$var] = $value;
				break;
			}

			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)
	{
		// serialize the fields details
		if (array_key_exists('fieldsDetails', $saveData)) {
			foreach ($saveData['fieldsDetails'] as $fields => $fieldsType) {
				if ($fieldsType == 'ignored') {
					unset($saveData['fieldsDetails'][$fields]);
				}
			}

			// save fields types with code (eg 'mandatory' -> 'm')
			foreach ($saveData['fieldsDetails'] as $fields => $fieldsType) {
				$saveData['fieldsDetails'][$fields] = array_search($fieldsType, $this->fieldTypes);
			}

			if ($saveData['fieldsDetails']) {
				$saveData['fieldsDetails'] = serialize($saveData['fieldsDetails']);
			}
			else {
				$saveData['fieldsDetails'] = '';
			}

		}

		// serialize the custom fields details
		if (array_key_exists('customFieldsDetails', $saveData)) {
			foreach ($saveData['customFieldsDetails'] as $fields => $attr) {
				if ($attr['type'] == 'ignored') {
					unset($saveData['customFieldsDetails'][$fields]);
				}
			}

			foreach ($saveData['customFieldsDetails'] as $fields => $attr) {
				$saveData['customFieldsDetails'][$fields]['type'] = array_search($attr['type'], $this->fieldTypes);
			}

			if ($saveData['customFieldsDetails']) {
				$saveData['customFieldsDetails'] = serialize($saveData['customFieldsDetails']);
			}
			else {
				$saveData['customFieldsDetails'] = '';
			}

		}


		// serialize the template content
		if (array_key_exists('templateContent', $saveData)) {
			if ($saveData['templateContent']) {
				$saveData['templateContent'] = serialize($saveData['templateContent']);
			}
			else {
				$saveData['templateContent'] = '';
			}
		}


		// unset list with users ids
		unset($saveData['validUsersList']);

		return $saveData;

	}

	/**
	 * (non-PHPdoc)
	 * @see App\Entity.GeneralAbstract::save_postProcess()
	 */
	protected function save_postProcess(Array $saveData)
	{
		if (array_key_exists('validUsersList', $this->fields)) {

			// remove prev access rights
			global $DBTDocumentsTemplatesUsers;
			$this->save_executeSql_delete($DBTDocumentsTemplatesUsers, 'idTemplate', $this->id);

			$insertedFields = [];

			foreach ($this->fields['validUsersList'] as $idUser) {
				$insertedFields['idTemplate'] = $this->id;
				$insertedFields['idUser'] = $idUser;
				$this->save_executeSql_insert($DBTDocumentsTemplatesUsers, $insertedFields);
			}
		}
	}
}