/**
 * Point d'entrée. Le contenu est utilisable tout de suite ; l'animation de
 * l'ouverture (scène 3D ou séquence d'images) est chargée après l'affichage de
 * l'affiche, qui en est la première image.
 */
// Polices hébergées dans le projet (fontsource) : aucun appel à Google.
import '@fontsource/big-shoulders-display/700';
import '@fontsource/ibm-plex-sans/400';
import '@fontsource/ibm-plex-sans/500';
import '@fontsource/ibm-plex-sans/600';
import '@fontsource/ibm-plex-mono/400';
import './styles/marque.css';
import './styles/site.css';
import { initInterface } from './contenu/interface';
import { initAnimations } from './contenu/animations';
import { initTransitions } from './contenu/transitions';
import { initCalculateur } from './calculateur';

declare global {
  interface Window { __forjaSecours?: number }
}
// Le script en tête de page avait prévu un repli statique si ce module n'arrivait jamais : annulé.
clearTimeout(window.__forjaSecours);

initInterface();
initCalculateur();
initAnimations();
/**
 * Tout ce qui n'est pas nécessaire au premier affichage attend : la page chargée,
 * une image peinte (l'affiche est à l'écran), puis un moment de calme du processeur.
 * Safari n'a pas toujours requestIdleCallback : simple délai à la place.
 */
const auRepos = (f: () => void) =>
  'requestIdleCallback' in window ? requestIdleCallback(f, { timeout: 1500 }) : setTimeout(f, 200);
export const apresPremierRendu = (f: () => void) => {
  // Deux images après le chargement, l'affiche est peinte ; un court délai laisse ensuite
  // le navigateur finir ce premier affichage avant de télécharger le reste.
  const quandCharge = () => requestAnimationFrame(() => requestAnimationFrame(() => setTimeout(() => auRepos(f), 250)));
  if (document.readyState === 'complete') quandCharge();
  else addEventListener('load', quandCharge, { once: true });
};

// Les mouvements liés au défilement : rien à gagner avant que le visiteur ne défile.
apresPremierRendu(initTransitions);

/** Repli statique : l'affiche reste seule, la promesse suit dans le flux de la page. */
const replierStatique = () => {
  const racine = document.documentElement;
  racine.classList.remove('avec-3d', 'avec-sequence', 'animee');
  racine.classList.add('sans-3d');
};

/**
 * Le mode est décidé tôt par le script en tête de index.html :
 *   avec-3d        ordinateur : la scène 3D en direct, épinglée et liée au défilement ;
 *   avec-sequence  téléphone, tablette : la même scène en images pré-rendues, dessinées
 *                  au rythme du défilement dans l'ouverture épinglée (position: sticky) ;
 *   sans-3d        mouvement réduit, appareil faible, économie de données : affiche seule.
 */
const racine = document.documentElement.classList;
if (racine.contains('avec-3d')) {
  // L'épinglage de l'ouverture est posé tout de suite : un visiteur qui fait défiler
  // avant l'arrivée de la 3D voit déjà la section tenir, et la scène reprend au bon endroit.
  const ouverture = document.querySelector<HTMLElement>('#ouverture');
  const epingler = ouverture
    ? import('./defilement').then((m) => m.creerDefilement(ouverture))
    : Promise.resolve();
  const charger = () =>
    epingler.then(() =>
    import('./3d/index').then((m) => m.demarrerScene())).catch((erreur) => {
      console.warn('[Forja] Scène 3D indisponible, affiche conservée.', erreur);
      import('./defilement').then((m) => m.obtenirDefilement()?.detruire());
      replierStatique();
    });
  apresPremierRendu(charger);
} else if (racine.contains('avec-sequence')) {
  // Le suivi du défilement démarre tout de suite (l'ouverture est déjà épinglée par le CSS) ;
  // les images, elles, ne sont téléchargées qu'après le premier affichage.
  import('./sequence')
    .then((m) => { if (!m.lancerSequence(apresPremierRendu)) replierStatique(); })
    .catch((erreur) => {
      console.warn('[Forja] Séquence indisponible, affiche conservée.', erreur);
      replierStatique();
    });
}
