/**
 * Tabela 6 — Coeficientes de pressão e de forma, externos, para
 * paredes de edificações de planta retangular (NBR 6123:2023, sec. 6.1.1).
 *
 * Fonte: NBR 6123:2023, p. 20 (Tabela 6).
 *
 * Zonas diferentes para α=0° e α=90°:
 *  - α = 0° (vento ⊥ largura b): A1/B1, A2/B2, C, D
 *  - α = 90° (vento ⊥ comprimento a): A, B, C1/D1, C2/D2
 *
 * A dimensão 'a' é sempre a maior, 'b' a menor, portanto a/b >= 1.
 */

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

type HbClass = 'low' | 'mid' | 'high';

function getHbClass(hOverB: number): HbClass {
  if (hOverB <= 0.5) return 'low';
  if (hOverB <= 1.5) return 'mid';
  return 'high';
}

// 1.5 means 1 <= a/b <= 1.5, 2.0 means 2 <= a/b <= 4

const WALL_CPE_A0: Record<HbClass, Record<number, readonly number[]>> = {
  // [A1B1, A2B2, C, D]
  low: {
    1.5: [-0.8, -0.5, +0.7, -0.4],
    2.0: [-0.8, -0.4, +0.7, -0.3],
  },
  mid: {
    1.5: [-0.9, -0.5, +0.7, -0.5],
    2.0: [-0.9, -0.4, +0.7, -0.3],
  },
  high: {
    1.5: [-1.0, -0.6, +0.8, -0.6],
    2.0: [-1.0, -0.5, +0.8, -0.3],
  },
};

const WALL_CPE_A90: Record<HbClass, Record<number, readonly number[]>> = {
  // [A, B, C1D1, C2D2]
  low: {
    1.5: [+0.7, -0.4, -0.8, -0.4],
    2.0: [+0.7, -0.5, -0.9, -0.5],
  },
  mid: {
    1.5: [+0.7, -0.5, -0.9, -0.5],
    2.0: [+0.7, -0.6, -0.9, -0.5],
  },
  high: {
    1.5: [+0.8, -0.6, -1.0, -0.6],
    2.0: [+0.8, -0.6, -1.0, -0.6],
  },
};

export interface WallCoefficientsAlpha0 {
  A1B1: number;
  A2B2: number;
  C: number;
  D: number;
}

export interface WallCoefficientsAlpha90 {
  A: number;
  B: number;
  C1D1: number;
  C2D2: number;
}

export interface WallCoefficients {
  alpha0: WallCoefficientsAlpha0;
  alpha90: WallCoefficientsAlpha90;
}

function interpRow(hbClass: HbClass, aOverB: number, table: typeof WALL_CPE_A0): readonly number[] {
  const t = table[hbClass];
  if (aOverB <= 1.5) return t[1.5];
  if (aOverB >= 2.0) return t[2.0];
  
  // Linear interpolation for a/b between 1.5 and 2.0
  const row15 = t[1.5];
  const row20 = t[2.0];
  return row15.map((val15, idx) => {
    const val20 = row20[idx];
    return Number(linearInterp1D([1.5, 2.0], [val15, val20], aOverB).toFixed(2));
  });
}

export function getWallCpeNBR6123(a: number, b: number, h: number): WallCoefficients {
  if (b <= 0 || a <= 0) {
    return {
      alpha0: { A1B1: 0, A2B2: 0, C: 0, D: 0 },
      alpha90: { A: 0, B: 0, C1D1: 0, C2D2: 0 },
    };
  }
  
  // A dimensão 'a' deve ser sempre a maior de acordo com a norma Tabela 6
  const aNorm = Math.max(a, b);
  const bNorm = Math.min(a, b);
  
  const aOverB = aNorm / bNorm;
  const hOverB = h / bNorm;
  const hbClass = getHbClass(hOverB);

  const row0 = interpRow(hbClass, aOverB, WALL_CPE_A0);
  const row90 = interpRow(hbClass, aOverB, WALL_CPE_A90);

  return {
    alpha0: { A1B1: row0[0], A2B2: row0[1], C: row0[2], D: row0[3] },
    alpha90: { A: row90[0], B: row90[1], C1D1: row90[2], C2D2: row90[3] },
  };
}

export function getWallCpeZone(
  a: number,
  b: number,
  h: number,
  zone: 'A1B1' | 'A2B2' | 'C' | 'D' | 'A' | 'B' | 'C1D1' | 'C2D2',
  windAngle: 0 | 90 = 0,
): number {
  const all = getWallCpeNBR6123(a, b, h);
  if (windAngle === 0) {
    return all.alpha0[zone as keyof WallCoefficientsAlpha0] ?? 0;
  }
  return all.alpha90[zone as keyof WallCoefficientsAlpha90] ?? 0;
}
