import { ButtonEffect } from "../effect-base.js";

/**
 * Starfield background effect
 * Twinkling stars with optional shooting stars
 */
export class StarfieldEffect extends ButtonEffect {
  constructor() {
    super({
      id: "bg-starfield",
      name: "Starfield",
      type: "background-animation",
      category: "Background Animations",
      renderOrder: 10,
    });

    this.stars = [];
    this.initialized = false;
  }

  defineControls() {
    return [
      {
        id: "animate-starfield",
        type: "checkbox",
        label: "Starfield Effect",
        defaultValue: false,
      },
      {
        id: "star-density",
        type: "range",
        label: "Star Density",
        defaultValue: 30,
        min: 10,
        max: 80,
        step: 5,
        showWhen: "animate-starfield",
        description: "Number of stars",
      },
      {
        id: "star-twinkle-speed",
        type: "range",
        label: "Twinkle Speed",
        defaultValue: 1,
        min: 1,
        max: 3,
        step: 0.1,
        showWhen: "animate-starfield",
        description: "Speed of twinkling",
      },
      {
        id: "star-shooting-enabled",
        type: "checkbox",
        label: "Shooting Stars",
        defaultValue: true,
        showWhen: "animate-starfield",
        description: "Enable shooting stars",
      },
      {
        id: "star-color",
        type: "color",
        label: "Star Color",
        defaultValue: "#ffffff",
        showWhen: "animate-starfield",
        description: "Color of stars",
      },
    ];
  }

  isEnabled(controlValues) {
    return controlValues["animate-starfield"] === true;
  }

  apply(context, controlValues, animState, renderData) {
    if (!animState) return;

    const density = controlValues["star-density"] || 30;
    const twinkleSpeed = controlValues["star-twinkle-speed"] || 1;
    const shootingEnabled = controlValues["star-shooting-enabled"] !== false;
    const starColor = controlValues["star-color"] || "#ffffff";

    // Initialize stars with deterministic positions (seed-based)
    if (!this.initialized || this.stars.length !== density) {
      this.stars = [];
      for (let i = 0; i < density; i++) {
        // Use density as part of the seed so pattern changes with density
        // Use multiple large prime seeds for better distribution
        const densitySeed = density * 97531; // Density affects all stars
        const seed1 = (i * 2654435761) + densitySeed;
        const seed2 = (i * 2246822519) + 3141592653 + densitySeed;
        const seed3 = (i * 3266489917) + 1618033988 + densitySeed;
        const seed4 = (i * 374761393) + 2718281828 + densitySeed;
        const seed5 = (i * 1103515245) + 12345 + densitySeed;

        // Hash-like function for better pseudo-random distribution
        const hash = (s) => {
          const x = Math.sin(s * 0.0001) * 10000;
          return x - Math.floor(x);
        };

        this.stars.push({
          x: hash(seed1) * renderData.width,
          y: hash(seed2) * renderData.height,
          size: 0.5 + hash(seed3) * 1.5,
          twinkleOffset: hash(seed4) * Math.PI * 2,
          twinkleSpeed: 0.5 + hash(seed5) * 1.5,
        });
      }
      this.initialized = true;
    }

    // Draw twinkling stars
    this.stars.forEach((star) => {
      const twinkle =
        Math.sin(
          animState.getPhase(twinkleSpeed * star.twinkleSpeed) +
            star.twinkleOffset,
        ) *
          0.5 +
        0.5;
      const opacity = 0.3 + twinkle * 0.7;

      context.fillStyle = starColor;
      context.globalAlpha = opacity;
      context.beginPath();
      context.arc(star.x, star.y, star.size, 0, Math.PI * 2);
      context.fill();
      context.globalAlpha = 1.0;
    });

    // Shooting stars - deterministic based on frame number
    if (shootingEnabled) {
      // Define shooting star spawn schedule (deterministic)
      const shootingStarSpawns = [
        { startFrame: 5, seed: 12345 },
        { startFrame: 18, seed: 67890 },
        { startFrame: 31, seed: 24680 },
      ];

      shootingStarSpawns.forEach((spawn) => {
        const framesSinceSpawn = animState.frame - spawn.startFrame;
        const duration = 25; // Frames the shooting star is visible

        if (framesSinceSpawn >= 0 && framesSinceSpawn < duration) {
          // Calculate deterministic properties from seed
          const hash = (s) => {
            const x = Math.sin(s * 0.0001) * 10000;
            return x - Math.floor(x);
          };

          const startX = hash(spawn.seed * 1) * renderData.width;
          const startY = -10;
          const vx = (hash(spawn.seed * 2) - 0.5) * 2;
          const vy = 3 + hash(spawn.seed * 3) * 2;

          // Calculate position based on frames elapsed
          const x = startX + vx * framesSinceSpawn;
          const y = startY + vy * framesSinceSpawn;
          const life = 1.0 - framesSinceSpawn / duration;

          if (life > 0) {
            // Draw shooting star trail
            const gradient = context.createLinearGradient(
              x,
              y,
              x - vx * 5,
              y - vy * 5,
            );
            gradient.addColorStop(0, `rgba(255, 255, 255, ${life * 0.8})`);
            gradient.addColorStop(1, "rgba(255, 255, 255, 0)");

            context.strokeStyle = gradient;
            context.lineWidth = 2;
            context.beginPath();
            context.moveTo(x, y);
            context.lineTo(x - vx * 5, y - vy * 5);
            context.stroke();
          }
        }
      });
    }
  }
}

export function register(generator) {
  generator.registerEffect(new StarfieldEffect());
}
