<?php
/**
 * Génération de l'affiche « Conseil Municipal ».
 */

defined( 'ABSPATH' ) || exit;

/**
 * Compose le visuel : fond + jour, date, heure et lieu.
 *
 * Les repères ci-dessous sont exprimés en pixels sur le fond fourni
 * (1254 × 1254). Ils sont filtrables si un autre visuel est utilisé.
 */
class Mairie_Affiche_Information_Conseil {

	/**
	 * Repères de composition.
	 *
	 * @return array
	 */
	public static function reperes() {
		$reperes = array(
			'jour'       => array(
				'cx'      => 806,
				'base'    => 633,
				'cap'     => 50,
				'largeur' => 700,
			),
			'date'       => array(
				'cx'      => 806,
				'base'    => 751,
				'cap'     => 87,
				'largeur' => 750,
			),
			'heure'      => array(
				'cx'      => 806,
				'base'    => 901,
				'cap'     => 90,
				'largeur' => 620,
				'ecart'   => 40,
			),
			'lieu'       => array(
				'cx'      => 760,
				'base'    => 1067,
				'cap'     => 62,
				'largeur' => 830,
			),
			'blanc'      => array( 255, 255, 255 ),
			'jaune'      => array( 246, 181, 25 ),
			'bleu'       => array( 1, 32, 81 ),
		);

		/**
		 * Ajuste les repères de composition de l'affiche Conseil Municipal.
		 *
		 * @param array $reperes Positions, tailles et couleurs.
		 */
		return apply_filters( 'mairie_affiche_information_conseil_reperes', $reperes );
	}

	/**
	 * Chemin de la police.
	 *
	 * @return string
	 */
	public static function police() {
		/**
		 * Police TrueType du visuel Conseil Municipal.
		 *
		 * @param string $chemin Chemin absolu du fichier .ttf.
		 */
		return apply_filters( 'mairie_affiche_information_conseil_police', MAIRIE_AFFICHE_INFORMATION_DIR . 'assets/fonts/Anton-Regular.ttf' );
	}

	/**
	 * Chemin du fond.
	 *
	 * @return string
	 */
	public static function fond() {
		$reglages = Mairie_Affiche_Information_Reglages::get();
		if ( ! empty( $reglages['conseil_fond_id'] ) ) {
			$chemin = get_attached_file( $reglages['conseil_fond_id'] );
			if ( $chemin && file_exists( $chemin ) ) {
				return $chemin;
			}
		}
		/**
		 * Fond par défaut du visuel Conseil Municipal.
		 *
		 * @param string $chemin Chemin absolu de l'image.
		 */
		return apply_filters( 'mairie_affiche_information_conseil_fond', MAIRIE_AFFICHE_INFORMATION_DIR . 'assets/fond_conseil.jpg' );
	}

	/**
	 * Nom du jour en majuscules, façon « JEUDI ».
	 *
	 * @param int $timestamp Horodatage.
	 * @return string
	 */
	public static function libelle_jour( $timestamp ) {
		return self::majuscules( wp_date( 'l', $timestamp ) );
	}

	/**
	 * Date en majuscules, façon « 30 JUILLET 2026 ».
	 *
	 * @param int $timestamp Horodatage.
	 * @return string
	 */
	public static function libelle_date( $timestamp ) {
		$texte = wp_date( 'j F Y', $timestamp );
		$texte = preg_replace( '/\b1 (?=\p{L})/u', '1ER ', $texte, 1 );
		return self::majuscules( $texte );
	}

	/**
	 * Heure façon « 20h00 » à partir d'une saisie HH:MM.
	 *
	 * @param string $saisie Heure au format HH:MM.
	 * @return string
	 */
	public static function libelle_heure( $saisie ) {
		if ( preg_match( '/^(\d{1,2})[:h.](\d{2})$/', trim( (string) $saisie ), $m ) ) {
			return sprintf( '%dh%02d', min( 23, (int) $m[1] ), min( 59, (int) $m[2] ) );
		}
		return '20h00';
	}

	/**
	 * Passage en majuscules, accents compris.
	 *
	 * @param string $texte Texte source.
	 * @return string
	 */
	public static function majuscules( $texte ) {
		return function_exists( 'mb_strtoupper' ) ? mb_strtoupper( $texte, 'UTF-8' ) : strtoupper( $texte );
	}

	/**
	 * Taille de police correspondant à une hauteur de capitale.
	 *
	 * @param int $cap Hauteur voulue pour un « H », en pixels.
	 * @return float
	 */
	private static function taille_pour_cap( $cap ) {
		$bbox = @imagettfbbox( 100, 0, self::police(), 'H' );
		if ( false === $bbox ) {
			return $cap;
		}
		$hauteur = abs( $bbox[7] - $bbox[1] );
		return $hauteur > 0 ? 100 * $cap / $hauteur : $cap;
	}

	/**
	 * Écrit un texte centré sur une ligne de base, réduit s'il déborde.
	 *
	 * @param resource|GdImage $img     Image.
	 * @param string           $texte   Texte.
	 * @param array            $repere  Repère (cx, base, cap, largeur).
	 * @param int              $couleur Couleur allouée.
	 * @return int Largeur occupée.
	 */
	private static function ecrire( $img, $texte, $repere, $couleur ) {
		$taille = self::taille_pour_cap( $repere['cap'] );
		$bbox   = @imagettfbbox( $taille, 0, self::police(), $texte );
		if ( false === $bbox ) {
			return 0;
		}

		$largeur = max( $bbox[2], $bbox[4] ) - min( $bbox[0], $bbox[6] );
		if ( $largeur > $repere['largeur'] && $largeur > 0 ) {
			$taille  = $taille * $repere['largeur'] / $largeur;
			$bbox    = imagettfbbox( $taille, 0, self::police(), $texte );
			$largeur = max( $bbox[2], $bbox[4] ) - min( $bbox[0], $bbox[6] );
		}

		$x = (int) round( $repere['cx'] - $largeur / 2 - min( $bbox[0], $bbox[6] ) );
		imagettftext( $img, $taille, 0, $x, (int) $repere['base'], $couleur, self::police(), $texte );

		return (int) $largeur;
	}

	/**
	 * Construit l'image.
	 *
	 * @param int    $timestamp Date du conseil.
	 * @param string $heure     Heure au format HH:MM.
	 * @param string $lieu      Lieu (imprimé en majuscules).
	 * @return resource|GdImage|WP_Error
	 */
	public static function composer( $timestamp, $heure, $lieu ) {
		if ( ! Mairie_Affiche_Information_Generateur::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' ) );
		}

		imagealphablending( $img, true );

		$r     = self::reperes();
		$blanc = imagecolorallocate( $img, $r['blanc'][0], $r['blanc'][1], $r['blanc'][2] );
		$jaune = imagecolorallocate( $img, $r['jaune'][0], $r['jaune'][1], $r['jaune'][2] );
		$bleu  = imagecolorallocate( $img, $r['bleu'][0], $r['bleu'][1], $r['bleu'][2] );

		self::ecrire( $img, self::libelle_jour( $timestamp ), $r['jour'], $blanc );
		self::ecrire( $img, self::libelle_date( $timestamp ), $r['date'], $blanc );
		self::ecrire( $img, self::majuscules( $lieu ), $r['lieu'], $bleu );

		// Heure : pictogramme et texte centrés ensemble.
		$texte_heure = self::libelle_heure( $heure );
		$taille      = self::taille_pour_cap( $r['heure']['cap'] );
		$bbox        = imagettfbbox( $taille, 0, self::police(), $texte_heure );
		$largeur     = max( $bbox[2], $bbox[4] ) - min( $bbox[0], $bbox[6] );

		$picto  = @imagecreatefrompng( MAIRIE_AFFICHE_INFORMATION_DIR . 'assets/horloge.png' );
		$lp     = $picto ? imagesx( $picto ) : 0;
		$hp     = $picto ? imagesy( $picto ) : 0;
		$total  = $largeur + ( $picto ? $lp + $r['heure']['ecart'] : 0 );
		$x      = (int) round( $r['heure']['cx'] - $total / 2 );

		if ( $picto ) {
			imagealphablending( $picto, true );
			imagesavealpha( $picto, true );
			imagecopy( $img, $picto, $x, (int) $r['heure']['base'] - 43 - (int) ( $hp / 2 ), 0, 0, $lp, $hp );
			imagedestroy( $picto );
			$x += $lp + $r['heure']['ecart'];
		}

		imagettftext( $img, $taille, 0, (int) round( $x - min( $bbox[0], $bbox[6] ) ), (int) $r['heure']['base'], $jaune, self::police(), $texte_heure );

		return $img;
	}

	/**
	 * Rend l'image sous forme binaire.
	 *
	 * @param int    $timestamp Date du conseil.
	 * @param string $heure     Heure HH:MM.
	 * @param string $lieu      Lieu.
	 * @param string $format    jpg ou png.
	 * @return string|WP_Error
	 */
	public static function rendu( $timestamp, $heure, $lieu, $format = 'jpg' ) {
		$img = self::composer( $timestamp, $heure, $lieu );
		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é : Conseil_Municipal_30-07-2026.jpg
	 *
	 * @param int    $timestamp Horodatage.
	 * @param string $format    jpg ou png.
	 * @return string
	 */
	public static function nom_fichier( $timestamp, $format = 'jpg' ) {
		return 'Conseil_Municipal_' . wp_date( 'd-m-Y', $timestamp ) . '.' . ( 'png' === $format ? 'png' : 'jpg' );
	}
}
