// ─────────────────────────────────────────────────────────────────────────────
// Odinote — tipografías del ordenador para notas y títulos
//
// Cada nota o título puede llevar `fuente`: el nombre de una tipografía
// instalada en el ordenador. Se pinta con la variable CSS --fuente-nodo (ver
// .note-inner, .note-edit y .bigtitle-edit en styles.css); sin ella, cada nodo
// usa la tipografía de siempre.
//
// La lista de las instaladas la da queryLocalFonts(), que solo existe en Chrome
// y Edge de escritorio (y en la app de escritorio) y pide permiso la primera
// vez. Donde no está, el nombre se puede escribir a mano: si esa tipografía
// está instalada, se usa igual.
// ─────────────────────────────────────────────────────────────────────────────

// Valor de font-family a partir del nombre guardado, o null si no hay. Se
// quitan los caracteres que podrían salirse del valor CSS.
function cssDeFuente(nombre) {
  const limpio = String(nombre || '').replace(/["\\;{}<>]/g, '').trim();
  return limpio ? '"' + limpio + '"' : null;
}
window.cssDeFuente = cssDeFuente;

// La variable para el style de un nodo (o de una muestra del panel). El nombre
// es dato del usuario: entra como variable, el resto lo decide la hoja.
function varsDeFuente(nombre) {
  const css = cssDeFuente(nombre);
  return css ? { '--fuente-nodo': css } : null;
}
window.varsDeFuente = varsDeFuente;

// La lista se pide una vez por sesión: leerla tarda y no cambia.
let familiasDelSistema = null;

function cargaFamiliasDelSistema() {
  if (familiasDelSistema) return Promise.resolve(familiasDelSistema);
  if (typeof window.queryLocalFonts !== 'function') return Promise.resolve(null);
  return window.queryLocalFonts().then(fuentes => {
    familiasDelSistema = [...new Set(fuentes.map(f => f.family))]
      .sort((a, b) => a.localeCompare(b));
    return familiasDelSistema;
  });
}

// Una fila del panel: el nombre con la letra de la interfaz, para que se lea
// siempre (hay tipografías de símbolos que lo convertirían en dibujos), y a la
// derecha una muestra con la tipografía de verdad.
function FilaFuente({ nombre, fuente, activa, onClick }) {
  return (
    <button
      className={`panel-fuente__item ${activa ? 'panel-fuente__item--activa' : ''}`}
      style={varsDeFuente(fuente)}
      onClick={onClick}
      title={nombre}
    >
      <span className="panel-fuente__nombre">{nombre}</span>
      <span className="panel-fuente__muestra" aria-hidden="true">Aa</span>
    </button>
  );
}

function PanelFuente({ valor, onCambio }) {
  const disponible = typeof window.queryLocalFonts === 'function';
  const [familias, setFamilias] = React.useState(familiasDelSistema);
  // inicio | cargando | lista | sinPermiso
  const [estado, setEstado] = React.useState(familiasDelSistema ? 'lista' : 'inicio');
  const [busca, setBusca] = React.useState('');

  const carga = () => {
    setEstado('cargando');
    cargaFamiliasDelSistema()
      .then(lista => { setFamilias(lista); setEstado(lista && lista.length ? 'lista' : 'sinPermiso'); })
      .catch(() => setEstado('sinPermiso'));
  };

  // Si el permiso ya se dio otro día, la lista sale sola, sin pedir un clic.
  React.useEffect(() => {
    if (familiasDelSistema || !disponible || !navigator.permissions) return;
    navigator.permissions.query({ name: 'local-fonts' })
      .then(p => { if (p.state === 'granted') carga(); })
      .catch(() => {});
  }, []);

  const escrita = busca.trim();
  const filtro = escrita.toLowerCase();
  const visibles = (familias || []).filter(f => !filtro || f.toLowerCase().includes(filtro)).slice(0, 300);
  const exacta = (familias || []).find(f => f.toLowerCase() === filtro);
  const elige = (nombre) => {
    onCambio(nombre);
    window.playAudioTone && window.playAudioTone('click');
  };

  return (
    <div className="ctx-popout panel-fuente">
      <div className="ctx-pop-section">
        <div className="ctx-pop-title">{window.t('Tipografía', 'Font')}</div>
        <input
          className="panel-fuente__busca"
          value={busca}
          onChange={(e) => setBusca(e.target.value)}
          onKeyDown={(e) => {
            e.stopPropagation();
            if (e.key === 'Enter' && escrita) elige(exacta || escrita);
          }}
          placeholder={window.t('Busca o escribe un nombre…', 'Search or type a name…')}
          spellCheck={false}
        />
        <div className="panel-fuente__lista">
          <FilaFuente activa={!valor} onClick={() => elige(null)} nombre={window.t('Por defecto', 'Default')}/>
          {escrita && !exacta && (
            <FilaFuente fuente={escrita} onClick={() => elige(escrita)} nombre={window.t('Usar', 'Use') + ' «' + escrita + '»'}/>
          )}
          {visibles.map(f => (
            <FilaFuente key={f} fuente={f} activa={valor === f} onClick={() => elige(f)} nombre={f}/>
          ))}
        </div>
        {disponible && estado === 'inicio' && (
          <button className="panel-fuente__cargar" onClick={carga}>
            <span className="material-symbols-rounded">font_download</span>
            {window.t('Ver las tipografías de mi ordenador', 'Show the fonts on my computer')}
          </button>
        )}
        {estado === 'cargando' && (
          <div className="panel-fuente__aviso">{window.t('Leyendo las tipografías…', 'Reading the fonts…')}</div>
        )}
        {estado === 'sinPermiso' && (
          <div className="panel-fuente__aviso">
            {window.t('No se pudo leer la lista. Permite el acceso a las fuentes en el candado de la barra de direcciones, o escribe el nombre arriba.',
              'Could not read the list. Allow font access from the padlock in the address bar, or type the name above.')}
          </div>
        )}
        {!disponible && (
          <div className="panel-fuente__aviso">
            {window.t('Este navegador no enseña la lista de tipografías: escribe arriba el nombre exacto de una instalada (en Chrome o Edge sí sale la lista).',
              'This browser cannot list your fonts: type the exact name of an installed one above (Chrome and Edge show the list).')}
          </div>
        )}
      </div>
    </div>
  );
}
window.PanelFuente = PanelFuente;
