namespace MaBibli.Shared.Isbn;
///
/// Reconnaît qu'un terme de recherche est un code et non des mots, et donne les formes
/// sous lesquelles le chercher dans le catalogue.
///
///
///
/// Le geste visé : scanner un livre qu'on tient en main pour retrouver sa fiche. La douchette
/// « tape » l'EAN-13 dans le champ de recherche, la caméra le pose de la même façon — mais la
/// recherche du catalogue ne portait que sur le titre et les auteurs, donc ne rendait rien.
///
///
/// ⚠️ Les deux formes d'ISBN sont indispensables, ici comme partout ailleurs dans le
/// projet : un livre paru avant 2007 porte un ISBN-10 en base, alors qu'un code-barres se lit
/// toujours en 13. Ne chercher qu'une forme ferait répondre « vous ne l'avez pas » à propos d'un
/// livre posé sur l'étagère.
///
///
/// ⚠️ Le seuil de huit chiffres n'est pas décoratif. Sans lui, chercher « 1984 » — un
/// titre — remonterait tous les livres dont l'ISBN contient ces quatre chiffres, c'est-à-dire du
/// bruit à la place d'une réponse. Aucun titre ne s'écrit avec huit chiffres d'affilée.
///
///
public static class RechercheIsbn
{
/// En deçà, un terme numérique est un titre bien plus probablement qu'un code.
private const int ChiffresMinimum = 8;
///
/// Les formes à confronter à Livre.Isbn, ou null si le terme n'est pas un code.
///
///
/// Un terme n'est un code que s'il ne contient rien d'autre que des chiffres, la
/// ponctuation d'un ISBN (tirets, espaces, points) et l'éventuel X final : « Zola 1984 »
/// reste une recherche de mots.
///
public static IReadOnlyList? Formes(string? recherche)
{
if (string.IsNullOrWhiteSpace(recherche) || !QueDuCode(recherche))
{
return null;
}
var chiffres = IsbnUtils.Normaliser(recherche);
if (chiffres is null || chiffres.Length < ChiffresMinimum)
{
return null;
}
// La conversion 13 → 10 ne vaut que pour un ISBN-13 complet et valide ; sur un fragment,
// elle n'a pas de sens et on s'en passe — la forme longue suffit alors.
return IsbnUtils.TryConvertirEnIsbn10(chiffres, out var court) && court is not null
? [chiffres, court]
: [chiffres];
}
/// Vrai si le terme est un ISBN complet et valide — donc s'il désigne UNE édition.
///
/// C'est ce qui autorise le catalogue à ouvrir directement la fiche quand un seul livre
/// correspond : sur un fragment, le même résultat unique serait un hasard de frappe.
///
public static bool EstCodeComplet(string? recherche) =>
QueDuCode(recherche) && IsbnUtils.EstValide(IsbnUtils.Normaliser(recherche));
private static bool QueDuCode(string? recherche)
{
if (string.IsNullOrWhiteSpace(recherche))
{
return false;
}
foreach (var c in recherche)
{
if (!char.IsDigit(c) && c is not ('-' or ' ' or '.' or 'x' or 'X'))
{
return false;
}
}
return true;
}
}