package eu.jonahbauer.raytracing.render.material;

import eu.jonahbauer.raytracing.math.Ray;
import eu.jonahbauer.raytracing.math.Vec3;
import eu.jonahbauer.raytracing.render.texture.Texture;
import eu.jonahbauer.raytracing.scene.HitResult;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;
import java.util.Optional;
import java.util.random.RandomGenerator;

public record MetallicMaterial(@NotNull Texture texture, double fuzz) implements Material {

    public MetallicMaterial(@NotNull Texture texture) {
        this(texture, 0);
    }

    public MetallicMaterial {
        Objects.requireNonNull(texture, "texture");
        if (fuzz < 0 || !Double.isFinite(fuzz)) throw new IllegalArgumentException("fuzz must be non-negative");
    }

    @Override
    public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
        var newDirection = Vec3.reflect(ray.direction(), hit.normal());
        if (fuzz > 0) {
            newDirection = newDirection.unit().plus(Vec3.random(random, true).times(fuzz));
        }
        var attenuation = texture.get(hit);
        return Optional.of(new ScatterResult(new Ray(hit.position(), newDirection), attenuation));
    }
}
