/**
 * Genere un masque PNG a bords arrondis (blanc opaque au centre, transparent
 * autour) pour arrondir les coins d'une source dans OBS.
 *
 * Usage :
 *   node tools/generer-masque-camera.js [largeur] [hauteur] [rayon] [fichier]
 *   node tools/generer-masque-camera.js 1920 1080 90
 *
 * Dans OBS : clic droit sur la source > Filtres > + > "Masque/mélange d'image",
 * Type = "Masque alpha (canal alpha)", et choisir ce fichier.
 */
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');

// --- Table CRC32 (necessaire au format PNG) ---
const TABLE_CRC = (() => {
  const t = new Int32Array(256);
  for (let n = 0; n < 256; n++) {
    let c = n;
    for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
    t[n] = c;
  }
  return t;
})();

function crc32(buf) {
  let c = -1;
  for (let i = 0; i < buf.length; i++) c = TABLE_CRC[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
  return (c ^ -1) >>> 0;
}

function chunk(type, data) {
  const len = Buffer.alloc(4);
  len.writeUInt32BE(data.length, 0);
  const corps = Buffer.concat([Buffer.from(type, 'ascii'), data]);
  const crc = Buffer.alloc(4);
  crc.writeUInt32BE(crc32(corps), 0);
  return Buffer.concat([len, corps, crc]);
}

/**
 * Couverture d'un pixel par le rectangle arrondi (0 = dehors, 1 = dedans).
 * La transition sur ~1 pixel donne des bords lisses (anticrenelage).
 */
function couverture(x, y, w, h, r) {
  const dx = Math.max(Math.abs(x - w / 2) - (w / 2 - r), 0);
  const dy = Math.max(Math.abs(y - h / 2) - (h / 2 - r), 0);
  const distance = Math.sqrt(dx * dx + dy * dy) - r;
  return Math.min(1, Math.max(0, 0.5 - distance));
}

function genererMasque(largeur, hauteur, rayon) {
  // 1 octet de filtre par ligne + 4 octets RGBA par pixel
  const brut = Buffer.alloc(hauteur * (1 + largeur * 4));
  let p = 0;
  for (let y = 0; y < hauteur; y++) {
    brut[p++] = 0; // filtre "None"
    for (let x = 0; x < largeur; x++) {
      const a = Math.round(couverture(x + 0.5, y + 0.5, largeur, hauteur, rayon) * 255);
      brut[p++] = 255; // R
      brut[p++] = 255; // V
      brut[p++] = 255; // B
      brut[p++] = a;   // alpha : c'est lui que lit OBS
    }
  }

  const ihdr = Buffer.alloc(13);
  ihdr.writeUInt32BE(largeur, 0);
  ihdr.writeUInt32BE(hauteur, 4);
  ihdr[8] = 8;  // 8 bits par canal
  ihdr[9] = 6;  // RGBA
  ihdr[10] = 0; // compression standard
  ihdr[11] = 0; // filtrage standard
  ihdr[12] = 0; // pas d'entrelacement

  return Buffer.concat([
    Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
    chunk('IHDR', ihdr),
    chunk('IDAT', zlib.deflateSync(brut, { level: 9 })),
    chunk('IEND', Buffer.alloc(0))
  ]);
}

const largeur = parseInt(process.argv[2], 10) || 1920;
const hauteur = parseInt(process.argv[3], 10) || 1080;
const rayon = parseInt(process.argv[4], 10) || Math.round(Math.min(largeur, hauteur) * 0.08);
const sortie = process.argv[5] ||
  path.join(__dirname, '..', 'public', 'overlay', 'media', 'images',
    `masque-camera-${largeur}x${hauteur}-r${rayon}.png`);

fs.mkdirSync(path.dirname(sortie), { recursive: true });
fs.writeFileSync(sortie, genererMasque(largeur, hauteur, rayon));
console.log(`Masque genere : ${sortie}`);
console.log(`  ${largeur} x ${hauteur}, rayon ${rayon} px`);
