use Test;
use lib 'lib';
use NativeCall;
use Noise::Simplex::Native;

# Bulk-fill must be bit-identical to per-sample for the same coords.
# It pays the NativeCall boundary once instead of w*h times, but the
# inner math is the same; the compiler inlines simplex_noise{2,3}d
# inside the fill loops at -O3.

plan 5;

my $simplex = Noise::Simplex::Native::Simplex.new(seed => 12345);
my &n2d = $simplex.create-noise2d;
my &n3d = $simplex.create-noise3d;

# --- 2D parity ---
{
	my Int $w  = 32;
	my Int $h  = 32;
	my Num $x0 = -1e0;
	my Num $dx = 0.125e0;
	my Num $y0 = -2e0;
	my Num $dy = 0.0625e0;

	my $bulk = $simplex.fill-noise2d-grid(:$x0, :$dx, :$w, :$y0, :$dy, :$h);
	is $bulk.elems, $w * $h, "2D bulk fill returns w*h elements";

	my $mismatches = 0;
	my $first-mismatch;
	for ^$h -> Int $j {
		for ^$w -> Int $i {
			my num64 $expect = n2d($x0 + $i * $dx, $y0 + $j * $dy);
			my num64 $got    = $bulk[$j * $w + $i];
			unless $expect == $got {
				$mismatches++;
				$first-mismatch //= "($i, $j) expect=$expect got=$got";
			}
		}
	}
	is $mismatches, 0,
	   "2D bulk fill bit-identical to per-sample over { $w * $h } samples"
	   ~ ($first-mismatch ?? " (first: $first-mismatch)" !! "");
}

# --- 3D parity ---
{
	my Int $w  = 16;
	my Int $h  = 16;
	my Int $d  = 4;
	my Num $x0 = -1e0;
	my Num $dx = 0.125e0;
	my Num $y0 = -1e0;
	my Num $dy = 0.0625e0;
	my Num $z0 = 0e0;
	my Num $dz = 0.25e0;

	my $bulk = $simplex.fill-noise3d-grid(
		:$x0, :$dx, :$w, :$y0, :$dy, :$h, :$z0, :$dz, :$d
	);
	is $bulk.elems, $w * $h * $d, "3D bulk fill returns w*h*d elements";

	my $mismatches = 0;
	my $first-mismatch;
	for ^$d -> Int $k {
		for ^$h -> Int $j {
			for ^$w -> Int $i {
				my num64 $expect = n3d(
					$x0 + $i * $dx,
					$y0 + $j * $dy,
					$z0 + $k * $dz,
				);
				my num64 $got = $bulk[($k * $h + $j) * $w + $i];
				unless $expect == $got {
					$mismatches++;
					$first-mismatch //= "($i,$j,$k) expect=$expect got=$got";
				}
			}
		}
	}
	is $mismatches, 0,
	   "3D bulk fill bit-identical to per-sample over { $w * $h * $d } samples"
	   ~ ($first-mismatch ?? " (first: $first-mismatch)" !! "");
}

# --- After dispose, bulk fill throws cleanly ---
$simplex.dispose;
throws-like {
	$simplex.fill-noise2d-grid(:x0(0e0), :dx(1e0), :w(4), :y0(0e0), :dy(1e0), :h(4));
}, Exception, message => /'after dispose'/,
   'fill-noise2d-grid after dispose throws cleanly';

done-testing;
