<?php
declare(strict_types = 1);

/**
 * Modèle de description pour catégories et fichiers.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class Description
{
	/**
	 * Données de la catégorie ou du fichier.
	 *
	 * @var array
	 */
	private static $_data;

	/**
	 * Métadonnées du fichier.
	 *
	 * @var object
	 */
	private static $_metadata;



	/**
	 * Applique le modèle de description pour catégorie ou fichier.
	 *
	 * @param string $type
	 * @param array $data
	 * @param bool $specialchars
	 *
	 * @return string
	 */
	public static function model(string $type, array &$data, bool $specialchars = TRUE): string
	{
		self::$_data = &$data;
		self::$_metadata = NULL;

		$model = $type == 'cat'
			? Config::$params['categories_description_model_text']
			: Config::$params['items_description_model_text'];

		$regex = '`(\{(?:END)?IF\([^\)]+\)\})`i';
		$options = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
		$model = preg_split($regex, $model, -1, $options);

		self::_if($type, $model);
		$model = implode('', $model);

		$model = preg_replace_callback('`{([A-Z]{2,20})}`i',
			'Description::_' . $type . 'Var', $model);

		if ($type == 'item')
		{
			$model = preg_replace_callback('`{(EXIF|IPTC|XMP):([A-Z0-9]{2,20})}`i',
				'Description::_itemVarMeta', $model);
		}

		if ($specialchars)
		{
			HTML::specialchars($model);
		}

		return Template::formatText($model, FALSE);
	}



	/**
	 * Conditions pour les informations de catégories.
	 *
	 * @param string $var
	 *
	 * @return mixed
	 */
	private static function _catIf(string $var): bool
	{
		switch ($var)
		{
			case 'ID' :
			case 'URL' :
				return TRUE;

			case 'DESCRIPTION' :
				return !Utility::isEmpty((string) self::$_data['cat_desc']);

			case 'TITLE' :
				return !Utility::isEmpty((string) self::$_data['cat_name']);
		}

		return FALSE;
	}

	/**
	 * Informations de catégories.
	 *
	 * @param array $m
	 *
	 * @return mixed
	 */
	private static function _catVar(array $m)
	{
		switch ($m[1])
		{
			case 'DESCRIPTION' :
				return HTML::nl2br((string) self::$_data['cat_desc']);

			case 'ID' :
				return self::$_data['cat_id'];

			case 'TITLE' :
				return self::$_data['cat_name'];

			case 'URL' :
				return GALLERY_HOST . App::getURL(self::$_data['cat_type'] . '/'
					. self::$_data['cat_id'] . '-' . self::$_data['cat_url']);
		}

		return $m[0];
	}

	/**
	 * Gestion des conditions.
	 *
	 * @param string $type
	 * @param array $model
	 *
	 * @return void
	 */
	private static function _if(string $type, array &$model): void
	{
		$condition = [];
		foreach ($model as $key => &$str)
		{
			$regex = sprintf(
				'`\{((?:END)?IF)\((%s)\)\}`i',
				$condition ? key($condition) : '[^\)]+'
			);

			if (!preg_match($regex, $str, $m))
			{
				continue;
			}

			if (isset($condition[$m[2]]))
			{
				$condition[$m[2]][$m[1]]['count']++;

				if ($m[1] != 'IF'
				&& $condition[$m[2]]['IF']['count']
				== $condition[$m[2]]['ENDIF']['count'])
				{
					$method = $type == 'item'
						? (in_array(explode(':', $m[2])[0], ['EXIF', 'IPTC', 'XMP'])
							? '_itemVarMeta'
							: '_itemIf')
						: '_catIf';

					$if_key = $condition[$m[2]]['IF']['key'];
					if (self::{$method}($m[2]))
					{
						array_splice($model, $if_key, 1);
						array_splice($model, $key - 1, 1);
					}
					else
					{
						array_splice($model, $if_key, $key - $if_key + 1);
					}

					self::_if($type, $model);
					break;
				}
			}
			elseif ($m[1] == 'IF')
			{
				$condition[$m[2]] =
				[
					'IF' => ['count' => 1, 'key' => $key],
					'ENDIF' => ['count' => 0]
				];
			}
		}
	}

	/**
	 * Conditions pour les informations de fichiers.
	 *
	 * @param string $var
	 *
	 * @return bool
	 */
	private static function _itemIf(string $var): bool
	{
		switch ($var)
		{
			case 'DATEADDED' :
			case 'DATETIMEADDED' :
			case 'FILENAME' :
			case 'FILETYPE' :
			case 'ID' :
			case 'URL' :
			case 'USERNAME' :
				return TRUE;

			case 'DATECREATED' :
			case 'DATETIMECREATED' :
				return (bool) self::$_data['item_crtdt'];

			case 'DESCRIPTION' :
				return !Utility::isEmpty((string) self::$_data['item_desc']);

			case 'DURATION' :
				return (bool) self::$_data['item_duration'];

			case 'FILESIZE' :
				return (bool) self::$_data['item_filesize'];

			case 'HEIGHT' :
				return (bool) self::$_data['item_height'];

			case 'TITLE' :
				return !Utility::isEmpty((string) self::$_data['item_name']);

			case 'WIDTH' :
				return (bool) self::$_data['item_width'];
		}

		return FALSE;
	}

	/**
	 * Informations de fichiers.
	 *
	 * @param array $m
	 *
	 * @return mixed
	 */
	private static function _itemVar(array $m)
	{
		switch ($m[1])
		{
			case 'DATEADDED' :
			case 'DATEPUBLISHED' :
				return L10N::dt(__('%A %d %B %Y'), self::$_data['item_pubdt']);

			case 'DATETIMEADDED' :
			case 'DATETIMEPUBLISHED' :
				return L10N::dt(__('%A %d %B %Y à %H:%M:%S'), self::$_data['item_pubdt']);

			case 'DATECREATED' :
				return self::$_data['item_crtdt']
					? L10N::dt(__('%A %d %B %Y'), self::$_data['item_crtdt'], FALSE)
					: '';

			case 'DATETIMECREATED' :
				return self::$_data['item_crtdt']
					? L10N::dt(__('%A %d %B %Y à %H:%M:%S'), self::$_data['item_crtdt'], FALSE)
					: '';

			case 'DESCRIPTION' :
				return HTML::nl2br((string) self::$_data['item_desc']);

			case 'DURATION' :
				return self::$_data['item_duration']
					? App::formatDuration(self::$_data['item_duration'])
					: '00:00';

			case 'FILENAME' :
				return basename(self::$_data['item_path']);

			case 'FILESIZE' :
				return self::$_data['item_filesize']
					? L10N::formatFilesize(self::$_data['item_filesize'])
					: 0;

			case 'FILETYPE' :
				return Item::getTypeText(self::$_data['item_type']);

			case 'ID' :
				return self::$_data['item_id'];

			case 'HEIGHT' :
				return self::$_data['item_height'];

			case 'TITLE' :
				return self::$_data['item_name'];

			case 'URL' :
				return GALLERY_HOST . App::getURL('item/'
					. self::$_data['item_id'] . '-' . self::$_data['item_url']);

			case 'USERNAME' :
				return User::getNickname(
					self::$_data['user_login'], self::$_data['user_nickname']
				);

			case 'WIDTH' :
				return self::$_data['item_width'];
		}

		return $m[0];
	}

	/**
	 * Informations de fichiers (métadonnées).
	 *
	 * @param mixed $m
	 *
	 * @return mixed
	 */
	private static function _itemVarMeta($m)
	{
		if (!self::$_metadata)
		{
			self::$_metadata = new Metadata(CONF_ALBUMS_PATH . '/' . self::$_data['item_path']);
		}

		$m = explode(':', is_array($m) ? substr($m[0], 1, -1) : $m);

		if ($m[0] == 'EXIF')
		{
			$formated = self::$_metadata->getExifFormatedInfo($m[1],
				Config::$params['exif_params']);
		}

		if ($m[0] == 'IPTC')
		{
			$formated = self::$_metadata->getIptcFormatedInfo($m[1],
				Config::$params['iptc_params']);
		}

		if ($m[0] == 'XMP')
		{
			$formated = self::$_metadata->getXmpFormatedInfo($m[1],
				Config::$params['xmp_params']);
		}

		return $formated['value'] ?? NULL;
	}
}
?>