<?php
/**
 * Génération de l'affiche.
 */

defined( 'ABSPATH' ) || exit;

/**
 * Compose le visuel : fond + date dessinée en TrueType.
 */
class Mairie_Affiche_Information_Generateur {

	/**
	 * GD est-il exploitable (avec FreeType) ?
	 *
	 * @return bool
	 */
	public static function gd_disponible() {
		return function_exists( 'imagettftext' ) && function_exists( 'imagecreatefrompng' );
	}

	/**
	 * Chemin de la police.
	 *
	 * @return string
	 */
	public static function police() {
		/**
		 * Permet de substituer une autre police TrueType.
		 *
		 * @param string $chemin Chemin absolu du fichier .ttf.
		 */
		return apply_filters( 'mairie_affiche_information_police', MAIRIE_AFFICHE_INFORMATION_DIR . 'assets/fonts/FjallaOne.ttf' );
	}

	/**
	 * Chemin du fond : pièce jointe choisie dans les réglages, sinon fond fourni.
	 *
	 * @return string
	 */
	public static function fond() {
		$reglages = Mairie_Affiche_Information_Reglages::get();
		if ( $reglages['fond_id'] ) {
			$chemin = get_attached_file( $reglages['fond_id'] );
			if ( $chemin && file_exists( $chemin ) ) {
				return $chemin;
			}
		}
		return apply_filters( 'mairie_affiche_information_fond', MAIRIE_AFFICHE_INFORMATION_DIR . 'assets/fond_mairie.jpg' );
	}

	/**
	 * Libellé français de la date, façon « Mercredi 5 août 2026 ».
	 *
	 * @param int $timestamp Horodatage UTC.
	 * @return string
	 */
	public static function libelle_date( $timestamp ) {
		$texte = wp_date( 'l j F Y', $timestamp );

		// 1er au lieu de 1.
		$texte = preg_replace( '/\b1 (?=\p{L})/u', '1er ', $texte, 1 );

		// Majuscule initiale (WordPress renvoie le jour en minuscule en français).
		if ( function_exists( 'mb_substr' ) ) {
			$texte = mb_strtoupper( mb_substr( $texte, 0, 1, 'UTF-8' ), 'UTF-8' ) . mb_substr( $texte, 1, null, 'UTF-8' );
		} else {
			$texte = ucfirst( $texte );
		}

		return $texte;
	}

	/**
	 * Largeur d'une chaîne et décalage gauche, pour une taille donnée.
	 *
	 * @param float  $taille Taille de police.
	 * @param string $texte  Texte mesuré.
	 * @return array{0:int,1:int}|false
	 */
	private static function mesurer( $taille, $texte ) {
		$bbox = @imagettfbbox( $taille, 0, self::police(), $texte );
		if ( false === $bbox ) {
			return false;
		}
		$gauche = min( $bbox[0], $bbox[6] );
		$droite = max( $bbox[2], $bbox[4] );
		return array( $droite - $gauche, $gauche );
	}

	/**
	 * Taille de police faisant tenir le texte dans la largeur voulue.
	 *
	 * @param string $texte   Texte à ajuster.
	 * @param float  $largeur Largeur cible en pixels.
	 * @return float
	 */
	private static function taille_ajustee( $texte, $largeur ) {
		$taille = 100.0;
		for ( $i = 0; $i < 8; $i++ ) {
			$mesure = self::mesurer( $taille, $texte );
			if ( ! $mesure || $mesure[0] <= 0 ) {
				break;
			}
			$taille *= $largeur / $mesure[0];
		}
		return $taille;
	}

	/**
	 * Construit l'image.
	 *
	 * @param string $texte Texte de la date.
	 * @return resource|GdImage|WP_Error
	 */
	public static function composer( $texte ) {
		if ( ! self::gd_disponible() ) {
			return new WP_Error( 'mairie_affiche_information_gd', __( "The GD extension (with FreeType) is not available on this server.", 'mairie-affiche-information' ) );
		}

		$fond = self::fond();
		if ( ! file_exists( $fond ) ) {
			return new WP_Error( 'mairie_affiche_information_fond', __( 'Background image not found.', 'mairie-affiche-information' ) );
		}

		$type = wp_check_filetype( $fond );
		if ( 'image/png' === $type['type'] ) {
			$img = @imagecreatefrompng( $fond );
		} elseif ( in_array( $type['type'], array( 'image/jpeg', 'image/jpg' ), true ) ) {
			$img = @imagecreatefromjpeg( $fond );
		} else {
			return new WP_Error( 'mairie_affiche_information_fond_type', __( 'The background must be a PNG or JPEG image.', 'mairie-affiche-information' ) );
		}

		if ( ! $img ) {
			return new WP_Error( 'mairie_affiche_information_fond_lecture', __( "The background image could not be opened.", 'mairie-affiche-information' ) );
		}

		$reglages = Mairie_Affiche_Information_Reglages::get();
		imagealphablending( $img, true );

		// Taille de référence : celle d'une date « type », pour garder une
		// allure constante d'une affiche à l'autre ; on ne réduit que si besoin.
		$taille_ref = self::taille_ajustee( 'Mercredi 5 août 2026', $reglages['largeur_max'] );
		$taille     = min( $taille_ref, self::taille_ajustee( $texte, $reglages['largeur_max'] ) );

		$mesure = self::mesurer( $taille, $texte );
		if ( ! $mesure ) {
			imagedestroy( $img );
			return new WP_Error( 'mairie_affiche_information_police', __( 'Font not found, or GD built without FreeType.', 'mairie-affiche-information' ) );
		}

		list( $largeur, $decalage ) = $mesure;

		$x = (int) round( $reglages['centre_x'] - $largeur / 2 - $decalage );
		$y = (int) $reglages['ligne_base'];

		// Ombre portée douce, en trois passes translucides.
		foreach ( array( array( 6, 7, 105 ), array( 4, 5, 95 ), array( 2, 3, 85 ) ) as $passe ) {
			$ombre = imagecolorallocatealpha( $img, 60, 0, 0, $passe[2] );
			imagettftext( $img, $taille, 0, $x + $passe[0], $y + $passe[1], $ombre, self::police(), $texte );
		}

		list( $r, $v, $b ) = Mairie_Affiche_Information_Reglages::hex_vers_rvb( $reglages['couleur'] );
		$couleur           = imagecolorallocate( $img, $r, $v, $b );
		imagettftext( $img, $taille, 0, $x, $y, $couleur, self::police(), $texte );

		return $img;
	}

	/**
	 * Rend l'image sous forme binaire.
	 *
	 * @param string $texte  Texte de la date.
	 * @param string $format jpg ou png.
	 * @return string|WP_Error
	 */
	public static function rendu( $texte, $format = 'jpg' ) {
		$img = self::composer( $texte );
		if ( is_wp_error( $img ) ) {
			return $img;
		}

		$reglages = Mairie_Affiche_Information_Reglages::get();

		ob_start();
		if ( 'png' === $format ) {
			imagepng( $img, null, 6 );
		} else {
			imagejpeg( $img, null, (int) $reglages['qualite'] );
		}
		$binaire = ob_get_clean();
		imagedestroy( $img );

		return $binaire;
	}

	/**
	 * Nom de fichier normalisé : Mairie_Affiche_Information_05-08-2026.jpg
	 *
	 * @param int    $timestamp Horodatage.
	 * @param string $format    jpg ou png.
	 * @return string
	 */
	public static function nom_fichier( $timestamp, $format = 'jpg' ) {
		return 'Mairie_Affiche_Information_' . wp_date( 'd-m-Y', $timestamp ) . '.' . ( 'png' === $format ? 'png' : 'jpg' );
	}
}
