/**
 * Generates textures for the Void Seep Depths biome.
 * Style: Obsidian black stone, neon violet corruption, glitchy visual effects.
 */
export class VoidSeepTextureGenerator {
  constructor(seed) {
    this.seed = seed;
  }

  /**
   * Generates a glossy, dark obsidian texture.
   * @param {number} size - Texture size (e.g., 64)
   * @returns {Object} { diffuse, normal, roughness, bump }
   */
  generateObsidian(size = 64) {
    const canvas = new OffscreenCanvas(size, size);
    const ctx = canvas.getContext("2d");

    // base: Very dark grey/black
    ctx.fillStyle = "#111111"; // Near black
    ctx.fillRect(0, 0, size, size);

    // Subtle noise for stone surface
    this.noisePass(ctx, size, 0.05, 0.1);

    // Glossy finish (handled by roughness map mostly) but let's add some faint veins
    ctx.strokeStyle = "#222222";
    ctx.lineWidth = 1;
    for (let i = 0; i < 5; i++) {
      ctx.beginPath();
      ctx.moveTo(Math.random() * size, Math.random() * size);
      ctx.lineTo(Math.random() * size, Math.random() * size);
      ctx.stroke();
    }

    const diffuse = canvas.transferToImageBitmap();

    // Normal Map (Smooth with minor imperfections)
    const normalCtx = new OffscreenCanvas(size, size).getContext("2d");
    normalCtx.fillStyle = "#8080ff"; // Flat normal
    normalCtx.fillRect(0, 0, size, size);
    // Add same veins as height bumps
    normalCtx.strokeStyle = "#8080ff"; // Slight variation needed for real normal map but this is a placeholder
    // For now, let's keep normal simple.

    // Roughness: Very low (0.1 - 0.3) for shiny obsidian, but with rougher patches
    const roughCtx = new OffscreenCanvas(size, size).getContext("2d");
    roughCtx.fillStyle = "#202020"; // Dark = Smooth/Shiny
    roughCtx.fillRect(0, 0, size, size);
    this.noisePass(roughCtx, size, 0.1, 0.2); // Add some dust/scratches

    return {
      diffuse,
      normal: normalCtx.canvas.transferToImageBitmap(),
      roughness: roughCtx.canvas.transferToImageBitmap(),
      bump: null, // Optional
    };
  }

  /**
   * Generates a pulsing neon violet corruption texture.
   * @param {number} size
   */
  generateCorruption(size = 64) {
    const canvas = new OffscreenCanvas(size, size);
    const ctx = canvas.getContext("2d");

    // Base: Dark Purple
    ctx.fillStyle = "#2a003b";
    ctx.fillRect(0, 0, size, size);

    // Neon Veins
    ctx.strokeStyle = "#aa00ff";
    ctx.lineWidth = 2;
    for (let i = 0; i < 8; i++) {
      ctx.beginPath();
      ctx.moveTo(Math.random() * size, Math.random() * size);
      ctx.bezierCurveTo(
        Math.random() * size,
        Math.random() * size,
        Math.random() * size,
        Math.random() * size,
        Math.random() * size,
        Math.random() * size
      );
      ctx.stroke();
    }

    // Glow patches
    for (let i = 0; i < 10; i++) {
      const x = Math.random() * size;
      const y = Math.random() * size;
      const r = Math.random() * 5 + 2;
      const grd = ctx.createRadialGradient(x, y, 0, x, y, r);
      grd.addColorStop(0, "#ff00ff");
      grd.addColorStop(1, "transparent");
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, size, size);
    }

    const diffuse = canvas.transferToImageBitmap();

    // Emissive Map (The neon parts glow)
    const emissiveCtx = new OffscreenCanvas(size, size).getContext("2d");
    emissiveCtx.fillStyle = "#000000";
    emissiveCtx.fillRect(0, 0, size, size);
    // Re-draw veins and glow for emissive
    emissiveCtx.strokeStyle = "#aa00ff";
    emissiveCtx.lineWidth = 2;
    // (Ideally we reuse the potential procedural noise or seed, but random here is fine for now as long as it looks "glowy")
    // Actually, to match, we should probably just use the diffuse as emissive but darkened?
    // Let's just make a generic noise emissive for now.
    emissiveCtx.fillStyle = "#440066";
    this.noisePass(emissiveCtx, size, 0.2, 0.8);

    return {
      diffuse,
      normal: (() => {
        const c = new OffscreenCanvas(size, size);
        const ctx = c.getContext("2d");
        ctx.fillStyle = "#8080ff";
        ctx.fillRect(0, 0, size, size);
        return c.transferToImageBitmap();
      })(),
      roughness: (() => {
        const c = new OffscreenCanvas(size, size);
        const ctx = c.getContext("2d");
        ctx.fillStyle = "#ff00ff"; // Fully rough? Or 0? Let's say mid rough.
        ctx.fillRect(0, 0, size, size);
        return c.transferToImageBitmap();
      })(),
      emissive: emissiveCtx.canvas.transferToImageBitmap(),
    };
  }

  noisePass(ctx, size, density, opacity) {
    const imageData = ctx.getImageData(0, 0, size, size);
    const data = imageData.data;
    for (let i = 0; i < data.length; i += 4) {
      if (Math.random() < density) {
        const val = Math.random() * 255;
        const alpha = opacity * 255;
        // Blend white noise
        data[i] = Math.min(255, data[i] + val * 0.1);
        data[i + 1] = Math.min(255, data[i + 1] + val * 0.1);
        data[i + 2] = Math.min(255, data[i + 2] + val * 0.1);
      }
    }
    ctx.putImageData(imageData, 0, 0);
  }
}
