// Asset generator: icon PNGs (16/48/128) + alert.wav notification sound.
// Uses only Node built-ins (zlib) — no dependencies.
//   node tools/generate-assets.js
const fs = require("fs");
const path = require("path");
const zlib = require("zlib");

const ASSETS = path.join(__dirname, "..", "assets");
fs.mkdirSync(ASSETS, { recursive: true });

// ---- PNG helpers ----
const CRC_TABLE = (() => {
  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 = ~0;
  for (let i = 0; i < buf.length; i++) c = CRC_TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
  return ~c >>> 0;
}
function chunk(type, data) {
  const len = Buffer.alloc(4);
  len.writeUInt32BE(data.length, 0);
  const typeBuf = Buffer.from(type, "ascii");
  const crc = Buffer.alloc(4);
  crc.writeUInt32BE(crc32(Buffer.concat([typeBuf, data])), 0);
  return Buffer.concat([len, typeBuf, data, crc]);
}
function makePNG(size, draw) {
  const px = Buffer.alloc(size * size * 4, 0); // RGBA, transparent start
  const set = (x, y, r, g, b, a = 255) => {
    if (x < 0 || y < 0 || x >= size || y >= size) return;
    const i = (y * size + x) * 4;
    px[i] = r; px[i + 1] = g; px[i + 2] = b; px[i + 3] = a;
  };
  draw(set, size);
  // filter byte 0 per row
  const raw = Buffer.alloc(size * (size * 4 + 1));
  for (let y = 0; y < size; y++) {
    raw[y * (size * 4 + 1)] = 0;
    px.copy(raw, y * (size * 4 + 1) + 1, y * size * 4, (y + 1) * size * 4);
  }
  const ihdr = Buffer.alloc(13);
  ihdr.writeUInt32BE(size, 0);
  ihdr.writeUInt32BE(size, 4);
  ihdr[8] = 8;  // bit depth
  ihdr[9] = 6;  // RGBA
  const sig = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
  return Buffer.concat([
    sig,
    chunk("IHDR", ihdr),
    chunk("IDAT", zlib.deflateSync(raw, { level: 9 })),
    chunk("IEND", Buffer.alloc(0)),
  ]);
}

// Purple rounded-square background + a gold "ping" dot in the center.
function drawIcon(set, size) {
  const r = size * 0.22;            // corner radius
  const cx = size / 2, cy = size / 2;
  const inRoundRect = (x, y) => {
    const dx = Math.max(r - x, x - (size - 1 - r), 0);
    const dy = Math.max(r - y, y - (size - 1 - r), 0);
    return dx * dx + dy * dy <= r * r;
  };
  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      if (!inRoundRect(x, y)) continue;
      // slight vertical gradient
      const t = y / size;
      const R = Math.round(124 - 30 * t);
      const G = Math.round(58 - 20 * t);
      const B = Math.round(237 - 40 * t);
      set(x, y, R, G, B, 255);
    }
  }
  // gold circle
  const dotR = size * 0.26;
  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      const d = Math.hypot(x - cx, y - cy);
      if (d <= dotR) set(x, y, 255, 209, 102, 255);
      else if (d <= dotR + 1) set(x, y, 255, 209, 102, 120); // anti-alias edge
    }
  }
}

for (const size of [16, 48, 128]) {
  fs.writeFileSync(path.join(ASSETS, `icon${size}.png`), makePNG(size, drawIcon));
}

// ---- WAV notification sound (short two-tone "ding") ----
function makeWav(tones, sampleRate = 44100) {
  const samples = [];
  for (const { freq, dur } of tones) {
    const n = Math.floor(sampleRate * dur);
    for (let i = 0; i < n; i++) {
      const t = i / sampleRate;
      // fast attack, exponential decay envelope
      const env = Math.min(1, t / 0.005) * Math.exp(-t * 7);
      samples.push(Math.sin(2 * Math.PI * freq * t) * env * 0.6);
    }
  }
  const buf = Buffer.alloc(44 + samples.length * 2);
  buf.write("RIFF", 0);
  buf.writeUInt32LE(36 + samples.length * 2, 4);
  buf.write("WAVE", 8);
  buf.write("fmt ", 12);
  buf.writeUInt32LE(16, 16);
  buf.writeUInt16LE(1, 20);            // PCM
  buf.writeUInt16LE(1, 22);            // mono
  buf.writeUInt32LE(sampleRate, 24);
  buf.writeUInt32LE(sampleRate * 2, 28);
  buf.writeUInt16LE(2, 32);
  buf.writeUInt16LE(16, 34);
  buf.write("data", 36);
  buf.writeUInt32LE(samples.length * 2, 40);
  for (let i = 0; i < samples.length; i++) {
    let s = Math.max(-1, Math.min(1, samples[i]));
    buf.writeInt16LE(Math.round(s * 32767), 44 + i * 2);
  }
  return buf;
}
fs.writeFileSync(
  path.join(ASSETS, "alert.wav"),
  makeWav([{ freq: 880, dur: 0.14 }, { freq: 1318.5, dur: 0.22 }])
);

console.log("Assets generated:", fs.readdirSync(ASSETS).join(", "));
