<?php
declare(strict_types = 1);

/**
 * Gestion des images.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class Image
{
	/**
	 * Extensions d'images autorisées.
	 *
	 * @param array
	 */
	const EXT_ARRAY = ['avif', 'gif', 'jfif', 'jpeg', 'jpg', 'png', 'webp'];



	/**
	 * Retourne les coordonnées d'une image qui seront
	 * utilisées pour la redimensionner et la retailler.
	 *
	 * @param int $img_width
	 *   Largeur de l'image.
	 * @param int $img_height
	 *   Hauteur de l'image.
	 * @param int $max_width
	 *   Largeur de l'image redimensionnée.
	 * @param int $max_height
	 *   Hauteur de l'image redimensionnée.
	 *
	 * @return array
	 */
	public static function getCroppedSource(int $img_width, int $img_height,
	int $max_width, int $max_height): array
	{
		$x = $y = 0;
		$w = $img_width;
		$h = $img_height;

		$ratio_w = $img_width / $max_width;
		$ratio_h = $img_height / $max_height;
		$ratio_m = $max_width > $max_height
			? $max_width / $max_height
			: $max_height / $max_width;

		if ($ratio_w < $ratio_h)
		{
			if ($max_width > $max_height)
			{
				$h = $img_width / $ratio_m;
			}
			else
			{
				$h = $img_width * $ratio_m;
			}
			$y = ($img_height - $h) / 2;
		}
		else
		{
			if ($max_width > $max_height)
			{
				$w = $img_height * $ratio_m;
			}
			else
			{
				$w = $img_height / $ratio_m;
			}
			$x = ($img_width - $w) / 2;
		}

		return
		[
			'x' => (int) round($x),
			'y' => (int) round($y),
			'w' => (int) round($w),
			'h' => (int) round($h)
		];
	}

	/**
	 * Retourne les dimensions d'une image redimensionnée
	 * en fonction de $max_width et $max_height.
	 *
	 * @param int $img_width
	 *   Largeur de l'image.
	 * @param int $img_height
	 *   Hauteur de l'image.
	 * @param int $max_width
	 *   Largeur max. de l'image redimensionnée.
	 * @param int $max_height
	 *   Hauteur max. de l'image redimensionnée.
	 * @param int $orientation
	 *   Orientation de l'image.
	 *
	 * @return array
	 */
	public static function getResizedSize(int $img_width, int $img_height,
	int $max_width, int $max_height, int $orientation = 1): array
	{
		$ratio_width = $img_width / $max_width;
		$ratio_height = $img_height / $max_height;

		if (($img_width > $max_width) && ($ratio_width >= $ratio_height))
		{
			$img_width = $max_width;
			$img_height = round($img_height / $ratio_width);
		}
		else if (($img_height > $max_height) && ($ratio_height >= $ratio_width))
		{
			$img_width = round($img_width / $ratio_height);
			$img_height = $max_height;
		}

		return in_array($orientation, [5, 6, 7, 8])
			? ['w' => (int) $img_height, 'h' => (int) $img_width]
			: ['w' => (int) $img_width, 'h' => (int) $img_height];
	}

	/**
	 * Récupère les dimensions et le type d'une image.
	 *
	 * @param string $file
	 *   Chemin du fichier.
	 *
	 * @return array
	 */
	public static function getTypeSize(string $file): array
	{
		if (($i = getimagesize($file)) === FALSE)
		{
			return [];
		}

		// Avant PHP 8.2.0, la fonction getimagesize() ne permettait pas de récupérer
		// les dimensions d'une image AVIF (les valeurs sont toujours à 0).
		// On passe donc par des fonctions GD pour récupérer les dimensions,
		// mais c'est beaucoup plus lent...
		if ((!$i[0] || !$i[1]) && $i[2] == IMAGETYPE_AVIF)
		{
			$gd_image = GD::createFrom($file);
			if (is_string($gd_image) || is_bool($gd_image))
			{
				return [];
			}
			$i[0] = imagesx($gd_image);
			$i[1] = imagesy($gd_image);
		}

		if (!$i[0] || !$i[1])
		{
			return [];
		}

		return
		[
			'width' => (int) $i[0],
			'height' => (int) $i[1],
			'filetype' => $i[2],
			'tags' => $i[3],
			'mime' => $i['mime']
		];
	}

	/**
	 * Envoi une image au navigateur.
	 *
	 * @param string $file
	 *   Chemin du fichier.
	 * @param bool $download
	 *   TRUE = télécharge l'image.
	 *   FALSE = affiche l'image.
	 *
	 * @return void
	 */
	public static function read(string $file, bool $download = FALSE): void
	{
		if (($i = getimagesize($file)) === FALSE)
		{
			die('Failed to read file.');
		}

		$content_type = $i['mime'];
		$content_disposition = $download ? 'attachment' : 'inline';
		$filename = basename($file);

		header("Content-Type: $content_type");
		header("Content-Disposition: $content_disposition; filename=\"$filename\"");
		if (!readfile($file))
		{
			header('Content-Type: text/html; charset=' . CONF_CHARSET);
			die('Failed to read file.');
		}
		die;
	}
}
?>