<?php
declare(strict_types = 1);

/**
 * Gestion des avatars.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class Avatar
{
	/**
	 * Poids maximum de l'image devant servir d'avatar (en octets).
	 *
	 * @var int
	 */
	const FILE_SIZE_MAX = 1048576;

	/**
	 * Dimensions maximum de l'image devant servir d'avatar,
	 * largeur et hauteur (en pixels).
	 *
	 * @var int
	 */
	const IMAGE_SIZE_MAX = 2000;

	/**
	 * Dimensions minimum de l'image devant servir d'avatar,
	 * largeur et hauteur (en pixels).
	 *
	 * @var int
	 */
	const IMAGE_SIZE_MIN = 50;

	/**
	 * Dimensions de l'avatar, largeur et hauteur (en pixels).
	 *
	 * @var int
	 */
	const IMAGE_SIZE = 300;

	/**
	 * Dimensions de la vignette de l'avatar, largeur et hauteur (en pixels).
	 *
	 * @var int
	 */
	const THUMB_SIZE = 100;



	/**
	 * Changement de l'avatar.
	 *
	 * @param int $user_id
	 *   Identifiant de l'utilisateur.
	 * @param string $source_filepath
	 *   Chemin absolu du fichier devant servir d'avatar.
	 *
	 * @return bool
	 */
	public static function change(int $user_id, string $source_filepath): bool
	{
		// Seul le super-administrateur peut modifier
		// l'avatar du super-administrateur.
		if (($user_id == 1 && Auth::$id != 1) || $user_id == 2)
		{
			return FALSE;
		}

		if (!$i = Image::getTypeSize($source_filepath))
		{
			return FALSE;
		}

		$avatar_copy = function(int $image_size, bool $thumb)
		use ($i, $source_filepath, $user_id): bool
		{
			// On redimensionne l'image si nécessaire.
			$file = self::getFilepath($user_id, $thumb);
			if ($i['width'] > $image_size || $i['height'] > $image_size)
			{
				$gd_image = GD::createFrom($source_filepath);
				$dst_size = Image::getResizedSize($i['width'], $i['height'],
					$image_size, $image_size);
				GD::resize($gd_image, 0, 0, $i['width'], $i['height'],
					0, 0, $dst_size['w'], $dst_size['h']);
				if (!GD::file($gd_image, $file, $i['filetype'], 100))
				{
					return FALSE;
				}
			}

			// Sinon on déplace directement l'image dans le répertoire des avatars.
			else if (!File::copy($source_filepath, $file))
			{
				return FALSE;
			}

			return TRUE;
		};
		if (!$avatar_copy(self::IMAGE_SIZE, FALSE))
		{
			return FALSE;
		}
		if (!$avatar_copy(self::THUMB_SIZE, TRUE))
		{
			return FALSE;
		}

		// On met à jour la base de données.
		if (!DB::execute('UPDATE {users} SET user_avatar = "1" WHERE user_id = ?', $user_id))
		{
			return FALSE;
		}

		// Log d'activité.
		if (App::$scriptName != 'admin')
		{
			App::logActivity('avatar_change');
		}

		return TRUE;
	}

	/**
	 * Vérifie un fichier devant servir d'avatar et retourne un code d'erreur.
	 *
	 * @param string $filepath
	 *   Chemin du fichier.
	 *
	 * @return array
	 *   Code et message d'erreur.
	 */
	public static function check(string $filepath): array
	{
		// Poids du fichier.
		if (filesize($filepath) > self::FILE_SIZE_MAX)
		{
			return
			[
				'code' => 1,
				'message' => sprintf(
						__('Le fichier ne doit pas dépasser %s.'),
						L10N::formatFilesize(self::FILE_SIZE_MAX)
					)
			];
		}

		$i = Image::getTypeSize($filepath);

		// Type de fichier.
		if (!$i || !in_array(Item::getTypeCode($filepath), Item::IMAGE_TYPES))
		{
			return
			[
				'code' => 2,
				'message' => __('Le fichier n\'est pas une image valide.')
			];
		}

		// Dimensions de l'image.
		if ($i['width'] < self::IMAGE_SIZE_MIN || $i['height'] < self::IMAGE_SIZE_MIN
		 || $i['width'] > self::IMAGE_SIZE_MAX || $i['height'] > self::IMAGE_SIZE_MAX)
		{
			return
			[
				'code' => 3,
				'message' => sprintf(
					__('L\'image doit faire entre %s et %s pixels de coté.'),
					Avatar::IMAGE_SIZE_MIN,
					Avatar::IMAGE_SIZE_MAX
				)
			];
		}

		return ['code' => 0];
	}

	/**
	 * Suppression de l'avatar d'un utilisateur.
	 *
	 * @param int $user_id
	 *   Identifiant de l'utilisateur.
	 *
	 * @return bool
	 */
	public static function delete(int $user_id): bool
	{
		// Seul le super-administrateur peut supprimer
		// l'avatar du super-administrateur.
		if (($user_id == 1 && Auth::$id != 1) || $user_id == 2)
		{
			return FALSE;
		}

		// Mise à jour de la base de données.
		if (!DB::execute('UPDATE {users} SET user_avatar = "0" WHERE user_id = ?', $user_id))
		{
			return FALSE;
		}

		// Suppression des fichiers.
		foreach ([FALSE, TRUE] as $thumb)
		{
			$filepath = self::getFilepath($user_id, $thumb);
			if (file_exists($filepath))
			{
				File::unlink($filepath);
			}
		}

		// Log d'activité.
		if (App::$scriptName != 'admin')
		{
			App::logActivity('avatar_delete');
		}

		return TRUE;
	}

	/**
	 * Retourne le nom de fichier de l'avatar.
	 *
	 * @param int $user_id
	 *   Identifiant de l'utilisateur.
	 * @param bool $thumb
	 *   Vignette de l'avatar ?
	 *
	 * @return string
	 */
	public static function getFilename(int $user_id, bool $thumb): string
	{
		return App::hashFilename("$user_id", $thumb ? ['_thumb'] : []) . '.jpg';
	}

	/**
	 * Retourne le chemin absolu de l'avatar sur le disque.
	 *
	 * @param int $user_id
	 *   Identifiant de l'utilisateur
	 * @param bool $thumb
	 *   Vignette de l'avatar ?
	 *
	 * @return string
	 */
	public static function getFilepath(int $user_id, bool $thumb = FALSE): string
	{
		return GALLERY_ROOT . '/images/avatars/' . self::getFilename($user_id, $thumb);
	}

	/**
	 * Retourne l'URL de l'avatar d'un utilisateur.
	 *
	 * @param int $user_id
	 *   Identifiant de l'utilisateur.
	 * @param bool $user_avatar
	 *   L'utilisateur a-t-il un avatar ?
	 * @param bool $thumb
	 *   Vignette de l'avatar ?
	 *
	 * @return string
	 */
	public static function getURL(int $user_id = 0,
	bool $user_avatar = FALSE, bool $thumb = TRUE): string
	{
		return CONF_GALLERY_PATH . '/images/avatars/' .
			($user_avatar ? self::getFilename($user_id, $thumb) : 'default.png');
	}
}
?>