<?php

/**
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
 * @copyright Metaways Infosystems GmbH, 2011
 * @copyright Aimeos (aimeos.org), 2015-2025
 * @package Base
 * @subpackage Common
 */


namespace Aimeos\Base\Criteria\Attribute;


/**
 * Default search attribute class.
 *
 * Instances of this class define input fields that can be searched for, how they
 * should be validated and what type is used by a manager internally when
 * storing data in the database
 *
 * @package Base
 * @subpackage Common
 */
class Standard implements \Aimeos\Base\Criteria\Attribute\Iface
{
	/* Custom value */
	public $value;

	private array $values;


	/**
	 * Initializes the search attribute object.
	 *
	 * @param array $params Parameter to be set on initialisation
	 *		[code] string
	 *		[default] mixed (optional)
	 *		[internalcode] string (optional)
	 *		[internaltype] string (optional)
	 *		[internaldeps] array (optional)
	 *		[function] Closure (optional)
	 *		[label] string
	 *		[public] boolean (optional)
	 *		[required] booblean (optional)
	 *		[type] string
	 */
	public function __construct( array $params = [] )
	{
		if( !isset( $params['code'] ) ) {
			throw new \Aimeos\Base\Exception( sprintf( 'Required parameter "%1$s" is missing', 'code' ) );
		}

		$this->values = $params;
	}


	/**
	 * Returns the value of the attribute.
	 *
	 * @param string $name Name of the attribute
	 * @return mixed|null Value of the attribute or NULL if not available
	 */
	public function __get( string $name )
	{
		return $this->values[$name] ?? null;
	}


	/**
	 * Tests if the property name is available.
	 *
	 * @param string $name Name of the attribute
	 * @return bool TRUE if the property is available, FALSE if not
	 */
	public function __isset( string $name ) : bool
	{
		return isset( $this->values[$name] );
	}


	/**
	 * Returns the type of the attribute.
	 *
	 * Can be used in the frontend to create a speacial form for this type
	 *
	 * @return string Available types are "string", "integer", "float", "boolean", "date", "time", "datetime"
	 */
	public function getType() : string
	{
		return $this->values['type'] ?? 'string';
	}


	/**
	 * Returns the type internally used by the manager.
	 *
	 * @return int|string Type used by the manager
	 * @deprecated 2024.01
	 */
	public function getInternalType()
	{
		return $this->values['internaltype'] ?? $this->getType();
	}


	/**
	 * Returns the public code for the search attribute.
	 *
	 * @return string Public code of the search attribute
	 */
	public function getCode() : string
	{
		return $this->values['code'];
	}


	/**
	 * Returns the internal code for the search attribute.
	 *
	 * @return array|string Internal code of the search attribute
	 */
	public function getInternalCode()
	{
		return $this->values['internalcode'] ?? $this->getCode();
	}


	/**
	 * Returns the list of internal dependency strings for the search attribute.
	 *
	 * @return array List of internal dependency strings
	 */
	public function getInternalDeps() : array
	{
		return (array) ( $this->values['internaldeps'] ?? [] );
	}


	/**
	 * Returns the helper function if available
	 *
	 * @return \Closure|null Helper function
	 */
	public function getFunction() : ?\Closure
	{
		return $this->values['function'] ?? null;
	}


	/**
	 * Returns the human readable label for the search attribute.
	 *
	 * @return string Name of the search attribute
	 */
	public function getLabel() : string
	{
		return $this->values['label'] ?? $this->getCode();
	}


	/**
	 * Returns the default value of the search attribute.
	 *
	 * @return mixed Default value of the search attribute
	 */
	public function getDefault()
	{
		return $this->values['default'] ?? null;
	}


	/**
	 * Returns true if the attribute should be publically available.
	 *
	 * @return bool True if the attribute is public, false if not
	 */
	public function isPublic() : bool
	{
		return (bool) ( $this->values['public'] ?? true );
	}


	/**
	 * Returns true if the attribute is required.
	 *
	 * @return bool True if the attribute is required, false if not
	 */
	public function isRequired() : bool
	{
		return (bool) ( $this->values['required'] ?? true );
	}


	/**
	 * Returns the attribute properties as key/value pairs.
	 *
	 * @param bool $private TRUE to return private attributes too, FALSE for public only
	 * @return array Associative list of attribute key/value pairs
	 */
	public function toArray( bool $private = false ) : array
	{
		$list = [
			'code' => $this->getCode(),
			'type' => $this->getType(),
			'label' => $this->getLabel(),
			'public' => $this->isPublic(),
			'default' => $this->getDefault(),
			'required' => $this->isRequired(),
			'value' => $this->value
		];

		if( $private )
		{
			$list['internalcode'] = $this->getInternalCode();
			$list['internaldeps'] = $this->getInternalDeps();
			$list['internaltype'] = $this->getInternalType();
		}

		return $list;
	}
}
