/**
 * Tabela 22 — Cúpulas sobre paredes cilíndricas (NBR 6123:2023, sec. 6.2.4.2).
 *
 * Valores limites de Cpe para barlavento, topo, lateral; por f/d.
 *
 * Fonte: NBR 6123:2023, p. 41 (Tabela 22).
 * Última auditoria: 2026-07-07 — chaves e valores oficiais confirmados.
 *
 * Chaves: f/d. A norma fornece chaves literais '1/4', '1/2', '1', '1/6',
 * '1/10', '1/15', '1/20', '1/25', '1/30'. Para chaves intermediárias,
 * interpolamos linearmente em f (após clamp).
 */

import { linearInterp1D } from '../log-interp';

const FD = [1 / 30, 1 / 25, 1 / 20, 1 / 15, 1 / 10, 1 / 6, 1 / 4, 1 / 2, 1] as const;
const FD_KEYS = ['1/30', '1/25', '1/20', '1/15', '1/10', '1/6', '1/4', '1/2', '1'] as const;

type Row = { barlavento: number; topo: number; lateral: number };

const T22: Record<string, Row> = {
  '1/30': { barlavento: -1.5, topo: -1.5, lateral: -1.4 },
  '1/25': { barlavento: -1.4, topo: -0.4, lateral: -1.4 },
  '1/20': { barlavento: -1.4, topo: -0.4, lateral: -1.4 },
  '1/15': { barlavento: -1.4, topo: -0.5, lateral: -1.5 },
  '1/10': { barlavento: -1.2, topo: -0.6, lateral: -1.3 },
  '1/6':  { barlavento: -0.1, topo: -0.9, lateral: -0.4 },
  '1/4':  { barlavento:  0.9, topo: -1.5, lateral: -0.4 },
  '1/2':  { barlavento:  0.8, topo: -1.7, lateral: -0.4 },
  '1':    { barlavento:  0.5, topo: -1.7, lateral: -0.5 },
};

function lookup22(fd: number): Row {
  const fdClamped = Math.max(FD[0], Math.min(FD[FD.length - 1], fd));
  const xs = [...FD];
  const ys1 = FD_KEYS.map((k) => T22[k].barlavento);
  const ys2 = FD_KEYS.map((k) => T22[k].topo);
  const ys3 = FD_KEYS.map((k) => T22[k].lateral);
  return {
    barlavento: Number(linearInterp1D(xs, ys1, fdClamped).toFixed(2)),
    topo: Number(linearInterp1D(xs, ys2, fdClamped).toFixed(2)),
    lateral: Number(linearInterp1D(xs, ys3, fdClamped).toFixed(2)),
  };
}

export interface DomeOnCylinderCpe {
  cpeBarlavento: number;
  cpeTopo: number;
  cpeLateral: number;
}

export function getDomeOnCylinderCpeNBR6123(fOverD: number): DomeOnCylinderCpe {
  const v = lookup22(fOverD);
  return {
    cpeBarlavento: v.barlavento,
    cpeTopo: v.topo,
    cpeLateral: v.lateral,
  };
}
