package pathtracing;

import basics.math.algebra.Ray;
import basics.math.algebra.Vector;
import geometry.scene.Hit;
import geometry.scene.Scene;
import optics.light.Color;
import optics.view.Camera;
import optics.view.PinholeCamera;
import pathtracing.pbr.Emissive;
import pathtracing.pbr.PhysicallyBasedMaterial;
import renderer.Renderer;

import java.util.Optional;

public class Pathtracer implements Renderer {

    private final Camera camera = new PinholeCamera(new Vector(0,0,-4), Vector.origin(), 90, 1e-3, 1e3);
    private final Scene scene = Scene.generatePathtracingExampleScene();

    private double traceShadow(Vector point, Vector direction, double distance) {
        Ray shadowRay = new Ray(point, direction, 1e-3, distance);

        Optional<Hit> result = scene.intersect(shadowRay);

        if (result.isEmpty()) {
            return 1.0;
        }

        return 0.0;
    }

    public Color traceDirect(Ray directRay, int depth) {
        if (depth == 4) {
            return Color.BLACK;
        }

        Optional<Hit> result = scene.intersect(directRay);

        if (result.isEmpty()) {
            // Background color
            return Color.BLACK;
        }

        Vector intersection = directRay.travel(result.get().getDistance());
        Vector normal = result.get().getMesh().normalAt(intersection, directRay.getDirection());

        var material = (PhysicallyBasedMaterial) result.get().getMesh().getMaterial();

        return material.surfaceColor(normal, directRay.getDirection(), intersection, this, depth + 1);
    }

    @Override
    public Color traceCameraRay(double u, double v) {
        var cameraRay = camera.generateViewRay(u, v);

        return traceDirect(cameraRay, 0);
    }

    @Override
    public Camera getCamera() {
        return camera;
    }
}
