/**
 * SeededRandom.js
 * A deterministic pseudo-random number generator using Mulberry32.
 * Essential for reproducible procedural generation.
 */
export class SeededRandom {
  constructor(seed) {
    // Hash the string seed to a number if necessary
    if (typeof seed === "string") {
      this.state = this.hashString(seed);
    } else {
      this.state = seed || Math.floor(Math.random() * 2147483647);
    }
  }

  hashString(str) {
    let hash = 1779033703 ^ str.length;
    for (let i = 0; i < str.length; i++) {
      hash = Math.imul(hash ^ str.charCodeAt(i), 3432918353);
      hash = (hash << 13) | (hash >>> 19);
    }

    // Perform the final mixing immediately and return the result
    hash = Math.imul(hash ^ (hash >>> 16), 2246822507);
    hash = Math.imul(hash ^ (hash >>> 13), 3266489909);
    return hash >>> 0;
  }

  // Mulberry32 Algorithm
  next() {
    let t = (this.state += 0x6d2b79f5);
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  }

  // Returns float between [min, max)
  range(min, max) {
    return min + this.next() * (max - min);
  }

  // Returns integer between [min, max] (inclusive)
  rangeInt(min, max) {
    return Math.floor(this.range(min, max + 1));
  }

  // Returns true/false based on probability (0.0 - 1.0)
  chance(probability) {
    return this.next() < probability;
  }
}
