///|
/// Demo scenes for moon-ray.

/// Simple scene with three spheres on a ground plane.
pub fn three_spheres_scene() -> (HitableList, Camera) {
  let mut world = HitableList::new()

  // Ground plane
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: -100.5, z: -1.0 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.8, y: 0.8, z: 0.0 }),
  )))

  // Center - matte sphere (reddish)
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Lambertian({ x: 0.7, y: 0.3, z: 0.3 }),
  )))

  // Left - metal sphere (silver with some fuzz)
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -1.0, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Metal({ x: 0.8, y: 0.8, z: 0.8 }, 0.1),
  )))

  // Right - glass sphere
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 1.0, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Dielectric(1.5),
  )))

  let cam = Camera::default(aspect_ratio=16.0 / 9.0)
  (world, cam)
}

/// Cornell Box scene - classic test scene for global illumination
pub fn cornell_box_scene() -> (HitableList, Camera) {
  let mut world = HitableList::new()

  // Light source (ceiling)
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 2.0, z: 0.0 },
    radius=0.5,
    material=Material::Emissive({ x: 4.0, y: 4.0, z: 4.0 }),
  )))

  // Floor - white diffuse
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: -100.5, z: 0.0 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.8, y: 0.8, z: 0.8 }),
  )))

  // Left wall - red
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -100.5, y: 0.0, z: 0.0 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.8, y: 0.1, z: 0.1 }),
  )))

  // Right wall - green
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 100.5, y: 0.0, z: 0.0 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.1, y: 0.8, z: 0.1 }),
  )))

  // Back wall - white
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 0.0, z: -100.5 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.8, y: 0.8, z: 0.8 }),
  )))

  // Ceiling - white
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 100.5, z: 0.0 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.8, y: 0.8, z: 0.8 }),
  )))

  // Center sphere - white diffuse
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -0.3, y: -0.25, z: -0.3 },
    radius=0.25,
    material=Material::Lambertian({ x: 0.9, y: 0.9, z: 0.9 }),
  )))

  // Right sphere - metal
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.4, y: -0.35, z: 0.2 },
    radius=0.15,
    material=Material::Metal({ x: 0.9, y: 0.9, z: 0.9 }, 0.05),
  )))

  // Glass sphere
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: -0.35, z: 0.5 },
    radius=0.15,
    material=Material::Dielectric(1.5),
  )))

  let cam = Camera::new(
    lookfrom={ x: 0.0, y: 0.0, z: 2.0 },
    lookat={ x: 0.0, y: 0.0, z: 0.0 },
    vup={ x: 0.0, y: 1.0, z: 0.0 },
    vfov=60.0,
    aspect_ratio=1.0,
    aperture=0.0,
    focus_dist=2.0,
    time0=0.0,
    time1=0.0,
  )
  (world, cam)
}

/// Random spheres scene - similar to "Ray Tracing in One Weekend"
pub fn random_spheres_scene() -> (HitableList, Camera) {
  let mut world = HitableList::new()
  let mut rng = new_rng(123456789UL)

  // Ground
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: -1000.0, z: 0.0 },
    radius=1000.0,
    material=Material::Lambertian({ x: 0.5, y: 0.5, z: 0.5 }),
  )))

  // Random small spheres
  for a in -5..=5 {
    for b in -5..=5 {
      let (rand_mat, rng1) = rng.random_double()
      rng = rng1
      let center = {
        x: a.to_double() + 0.9 * rng.random_double().0,
        y: 0.2,
        z: b.to_double() + 0.9 * rng.random_double().0,
      }

      if (center - { x: 4.0, y: 0.2, z: 0.0 }).length() > 0.9 {
        if rand_mat < 0.6 {
          // Diffuse
          let (r1, rng2) = rng.random_double()
          let (r2, rng3) = rng2.random_double()
          let (r3, rng4) = rng3.random_double()
          rng = rng4
          let albedo = { x: r1 * r2, y: r2 * r3, z: r3 * r1 }
          world = world.add(Hitable::Sphere(Sphere::new(
            center=center,
            radius=0.2,
            material=Material::Lambertian(albedo),
          )))
        } else if rand_mat < 0.85 {
          // Metal
          let (r1, rng2) = rng.random_double_range(min=0.5, max=1.0)
          let (r2, rng3) = rng2.random_double_range(min=0.5, max=1.0)
          let (r3, rng4) = rng3.random_double_range(min=0.5, max=1.0)
          let (fuzz, rng5) = rng4.random_double_range(min=0.0, max=0.5)
          rng = rng5
          let albedo = { x: r1, y: r2, z: r3 }
          world = world.add(Hitable::Sphere(Sphere::new(
            center=center,
            radius=0.2,
            material=Material::Metal(albedo, fuzz),
          )))
        } else {
          // Glass
          world = world.add(Hitable::Sphere(Sphere::new(
            center=center,
            radius=0.2,
            material=Material::Dielectric(1.5),
          )))
        }
      }
    }
  }

  // Three large spheres
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 1.0, z: 0.0 },
    radius=1.0,
    material=Material::Dielectric(1.5),
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -4.0, y: 1.0, z: 0.0 },
    radius=1.0,
    material=Material::Lambertian({ x: 0.4, y: 0.2, z: 0.1 }),
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 4.0, y: 1.0, z: 0.0 },
    radius=1.0,
    material=Material::Metal({ x: 0.7, y: 0.6, z: 0.5 }, 0.0),
  )))

  let cam = Camera::new(
    lookfrom={ x: 13.0, y: 2.0, z: 3.0 },
    lookat={ x: 0.0, y: 0.0, z: 0.0 },
    vup={ x: 0.0, y: 1.0, z: 0.0 },
    vfov=20.0,
    aspect_ratio=16.0 / 9.0,
    aperture=0.1,
    focus_dist=10.0,
    time0=0.0,
    time1=0.0,
  )
  (world, cam)
}

/// Material showcase scene - demonstrates all material types
pub fn material_showcase_scene() -> (HitableList, Camera) {
  let mut world = HitableList::new()

  // Ground
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: -100.5, z: -1.0 },
    radius=100.0,
    material=Material::Lambertian({ x: 0.5, y: 0.5, z: 0.5 }),
  )))

  // Row 1: Lambertian materials (different colors)
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -2.0, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Lambertian({ x: 0.9, y: 0.1, z: 0.1 }), // Red
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -0.7, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Lambertian({ x: 0.1, y: 0.9, z: 0.1 }), // Green
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.7, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Lambertian({ x: 0.1, y: 0.1, z: 0.9 }), // Blue
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 2.0, y: 0.0, z: -1.0 },
    radius=0.5,
    material=Material::Lambertian({ x: 0.9, y: 0.9, z: 0.1 }), // Yellow
  )))

  // Row 2: Metal materials (different fuzz values)
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -2.0, y: 0.0, z: -2.5 },
    radius=0.5,
    material=Material::Metal({ x: 0.9, y: 0.1, z: 0.1 }, 0.0), // Perfect mirror
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -0.7, y: 0.0, z: -2.5 },
    radius=0.5,
    material=Material::Metal({ x: 0.9, y: 0.9, z: 0.9 }, 0.1), // Slight fuzz
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.7, y: 0.0, z: -2.5 },
    radius=0.5,
    material=Material::Metal({ x: 0.9, y: 0.9, z: 0.9 }, 0.3), // Medium fuzz
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 2.0, y: 0.0, z: -2.5 },
    radius=0.5,
    material=Material::Metal({ x: 0.9, y: 0.9, z: 0.9 }, 0.5), // High fuzz
  )))

  // Row 3: Dielectric (glass) with different IOR
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: -1.5, y: 0.0, z: -4.0 },
    radius=0.5,
    material=Material::Dielectric(1.33), // Water-like
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 0.0, z: -4.0 },
    radius=0.5,
    material=Material::Dielectric(1.5), // Glass
  )))

  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 1.5, y: 0.0, z: -4.0 },
    radius=0.5,
    material=Material::Dielectric(2.42), // Diamond-like
  )))

  // Light source
  world = world.add(Hitable::Sphere(Sphere::new(
    center={ x: 0.0, y: 3.0, z: -2.0 },
    radius=0.5,
    material=Material::Emissive({ x: 5.0, y: 5.0, z: 5.0 }),
  )))

  let cam = Camera::new(
    lookfrom={ x: 0.0, y: 1.0, z: 4.0 },
    lookat={ x: 0.0, y: 0.0, z: -2.0 },
    vup={ x: 0.0, y: 1.0, z: 0.0 },
    vfov=45.0,
    aspect_ratio=16.0 / 9.0,
    aperture=0.0,
    focus_dist=4.0,
    time0=0.0,
    time1=0.0,
  )
  (world, cam)
}