// The ray tracer code in this file is written by Adam Burmister.
// It is available in its original form from:
//
//   http://labs.flog.nz.co/raytracer/
//
// It has been modified slightly by Google to work as a standalone benchmark,
// but all the computational code remains untouched.

// For JetStream3, this code was rewritten using ES6 classes and public fields,
// dropping namespaces and Prototype.js class system, as well as slightly refactored.
// All the computational code still remains untouched.

class Color {
    red = 0;
    green = 0;
    blue = 0;

    constructor(red, green, blue) {
        this.red = red;
        this.green = green;
        this.blue = blue;
    }

    static add(c1, c2) {
        return new Color(c1.red + c2.red, c1.green + c2.green, c1.blue + c2.blue);
    }

    static addScalar(c1, s) {
        return new Color(c1.red + s, c1.green + s, c1.blue + s).limit();
    }

    static multiply(c1, c2) {
        return new Color(c1.red * c2.red, c1.green * c2.green, c1.blue * c2.blue);
    }

    static multiplyScalar(c1, f) {
        return new Color(c1.red * f, c1.green * f, c1.blue * f);
    }

    static blend(c1, c2, w) {
        return Color.add(
            Color.multiplyScalar(c1, 1 - w),
            Color.multiplyScalar(c2, w),
        );
    }

    limit() {
        this.red = this.red > 0 ? (this.red > 1 ? 1 : this.red) : 0;
        this.green = this.green > 0 ? (this.green > 1 ? 1 : this.green) : 0;
        this.blue = this.blue > 0 ? (this.blue > 1 ? 1 : this.blue) : 0;

        return this;
    }

    brightness() {
        const r = Math.floor(this.red * 255);
        const g = Math.floor(this.green * 255);
        const b = Math.floor(this.blue * 255);

        return (r * 77 + g * 150 + b * 29) >> 8;
    }

    toString() {
        const r = Math.floor(this.red * 255);
        const g = Math.floor(this.green * 255);
        const b = Math.floor(this.blue * 255);

        return `rgb(${r},${g},${b})`;
    }
}

class Light {
    static defaultColor = new Color(0, 0, 0);

    position = null;
    color = Light.defaultColor;

    constructor(position, color) {
        this.position = position;
        this.color = color;
    }

    toString() {
        return `Light [${this.position}]`;
    }
}

class Vector {
    x = 0;
    y = 0;
    z = 0;

    static add(v, w) {
        return new Vector(w.x + v.x, w.y + v.y, w.z + v.z);
    }

    static subtract(v, w) {
        return new Vector(v.x - w.x, v.y - w.y, v.z - w.z);
    }

    static multiplyScalar(v, w) {
        return new Vector(v.x * w, v.y * w, v.z * w);
    }

    constructor(x, y, z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    normalize() {
        const m = this.magnitude();

        return new Vector(this.x / m, this.y / m, this.z / m);
    }

    negateY() {
        this.y *= -1;
    }

    magnitude() {
        return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
    }

    cross(w) {
        return new Vector(
            -this.z * w.y + this.y * w.z,
            this.z * w.x - this.x * w.z,
            -this.y * w.x + this.x * w.y,
        );
    }

    dot(w) {
        return this.x * w.x + this.y * w.y + this.z * w.z;
    }

    toString() {
        return `Vector [${this.x},${this.y},${this.z}]`;
    }
}

class Ray {
    position = null;
    direction = null;

    constructor(position, direction) {
        this.position = position;
        this.direction = direction;
    }

    toString() {
        return `Ray [${this.position},${this.direction}]`;
    }
}

class Scene {
    camera = null;
    background = null;
    shapes = [];
    lights = [];

    constructor(camera, background, shapes, lights) {
        this.camera = camera;
        this.background = background;
        this.shapes = shapes;
        this.lights = lights;
    }
}

class Material {
    reflection = 0;
    transparency = 0;
    gloss = 0;
    hasTexture = false;

    constructor(reflection, transparency, gloss, hasTexture) {
        this.reflection = reflection;
        this.transparency = transparency;
        this.gloss = gloss;
        this.hasTexture = hasTexture;
    }

    getColor() {
        throw new Error("getColor() isn't implemented");
    }

    toString() {
        return `Material [gloss=${this.gloss}, transparency=${this.transparency}, hasTexture=${this.hasTexture}]`;
    }
}

class SolidMaterial extends Material {
    static defaultColor = new Color(0, 0, 0);

    color = SolidMaterial.defaultColor;

    constructor(color, reflection, transparency, gloss) {
        super(reflection, transparency, gloss, true);
        this.color = color;
    }

    getColor() {
        return this.color;
    }

    toString() {
        return `SolidMaterial [gloss=${this.gloss}, transparency=${this.transparency}, hasTexture=${this.hasTexture}]`;
    }
}

class ChessboardMaterial extends Material {
    static defaultColorEven = new Color(0, 0, 0);
    static defaultColorOdd = new Color(0, 0, 0);

    colorEven = ChessboardMaterial.defaultColorEven;
    colorOdd = ChessboardMaterial.defaultColorOdd;
    density = 1;

    constructor(colorEven, colorOdd, reflection, transparency, gloss, density) {
        super(reflection, transparency, gloss, true);
        this.colorEven = colorEven;
        this.colorOdd = colorOdd;
        this.density = density;
    }

    wrapUp(t) {
        t %= 2;
        if (t < -1) t += 2;
        if (t >= 1) t -= 2;
        return t;
    }

    getColor(u, v) {
        const t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
        return t < 0 ? this.colorEven : this.colorOdd;
    }

    toString() {
        return `ChessMaterial [gloss=${this.gloss}, transparency=${this.transparency}, hasTexture=${this.hasTexture}]`;
    }
}

class Shape {
    position = null;
    material = null;

    constructor(position, material) {
        this.position = position;
        this.material = material;
    }

    intersect(ray) {
        throw new Error("intersect() isn't implemented");
    }
}

class Sphere extends Shape {
    radius = 0;

    constructor(position, material, radius) {
        super(position, material);
        this.radius = radius;
    }

    intersect(ray) {
        const info = new IntersectionInfo();
        info.shape = this;

        const dst = Vector.subtract(ray.position, this.position);

        const B = dst.dot(ray.direction);
        const C = dst.dot(dst) - (this.radius * this.radius);
        const D = (B * B) - C;

        if (D > 0) { // intersection!
            info.isHit = true;
            info.distance = (-B) - Math.sqrt(D);
            info.position = Vector.add(ray.position, Vector.multiplyScalar(ray.direction, info.distance));
            info.normal = Vector.subtract(info.position, this.position).normalize();
            info.color = this.material.getColor(0, 0);
        } else {
            info.isHit = false;
        }

        return info;
    }

    toString() {
        return `Sphere [position=${this.position}, radius=${this.radius}]`;
    }
}

class Plane extends Shape {
    d = 0;

    constructor(position, material, d) {
        super(position, material);
        this.d = d;
    }

    intersect(ray) {
        const info = new IntersectionInfo();
        info.shape = this;

        const Vd = this.position.dot(ray.direction);
        if (Vd === 0) return info; // no intersection

        const t = -(this.position.dot(ray.position) + this.d) / Vd;
        if (t <= 0) return info;

        info.isHit = true;
        info.position = Vector.add(ray.position, Vector.multiplyScalar(ray.direction, t));
        info.normal = this.position;
        info.distance = t;

        if (this.material.hasTexture) {
            const vU = new Vector(this.position.y, this.position.z, -this.position.x);
            const vV = vU.cross(this.position);
            const u = info.position.dot(vU);
            const v = info.position.dot(vV);
            info.color = this.material.getColor(u, v);
        } else {
            info.color = this.material.getColor(0, 0);
        }

        return info;
    }

    toString() {
        return `Plane [${this.position}, d=${this.d}]`;
    }
}

class IntersectionInfo {
    static defaultColor = new Color(0, 0, 0);

    isHit = false;
    hitCount = 0;
    shape = null;
    position = null;
    normal = null;
    color = IntersectionInfo.defaultColor;
    distance = null;

    toString() {
        return `Intersection [${this.position}]`;
    }
}

class Camera {
    position = null;
    lookAt = null;
    up = null;
    equator = null;
    screen = null;

    constructor(position, lookAt, up) {
        this.position = position;
        this.lookAt = lookAt;
        this.up = up;
        this.equator = this.lookAt.normalize().cross(this.up);
        this.screen = Vector.add(this.position, this.lookAt);
    }

    getRay(vx, vy) {
        const pos = Vector.subtract(
            this.screen,
            Vector.subtract(
                Vector.multiplyScalar(this.equator, vx),
                Vector.multiplyScalar(this.up, vy),
            ),
        );

        pos.negateY();

        const dir = Vector.subtract(pos, this.position);
        return new Ray(pos, dir.normalize());
    }

    toString() {
        return `Camera [${this.position}]`;
    }
}

class Background {
    static defaultColor = new Color(0, 0, 0);

    color = Background.defaultColor;
    ambience = 0;

    constructor(color, ambience) {
        this.color = color;
        this.ambience = ambience;
    }

    toString() {
        return `Background [${this.color}]`;
    }
}

class Engine {
    // Variable used to hold a number that can be used to verify that
    // the scene was ray traced correctly.
    checkNumber = 0;
    options = {};

    constructor(options) {
        this.options = {
            canvasHeight: 100,
            canvasWidth: 100,
            pixelWidth: 2,
            pixelHeight: 2,
            renderDiffuse: false,
            renderShadows: false,
            renderHighlights: false,
            renderReflections: false,
            rayDepth: 2,
            ...options,
        };

        this.options.canvasHeight /= this.options.pixelHeight;
        this.options.canvasWidth /= this.options.pixelWidth;
    }

    renderScene(scene) {
        for (let x = 0; x < this.options.canvasWidth; x++) {
            for (let y = 0; y < this.options.canvasHeight; y++) {
                const xp = x * 1 / this.options.canvasWidth * 2 - 1;
                const yp = y * 1 / this.options.canvasHeight * 2 - 1;

                const ray = scene.camera.getRay(xp, yp);
                const color = this.getPixelColor(ray, scene);

                this.setPixel(x, y, color);
            }
        }

        if (this.checkNumber !== 2321)
            throw new Error("Scene rendered incorrectly");
    }

    getPixelColor(ray, scene) {
        const info = this.testIntersection(ray, scene, null);
        if (info.isHit)
            return this.rayTrace(info, ray, scene, 0);
        return scene.background.color;
    }

    setPixel(x, y, color) {
        if (x === y)
            this.checkNumber += color.brightness();
    }

    testIntersection(ray, scene, exclude) {
        let hitCount = 0;
        let best = new IntersectionInfo();
        best.distance = 2000;

        for (let i = 0; i < scene.shapes.length; i++) {
            const shape = scene.shapes[i];
            if (shape !== exclude) {
                const info = shape.intersect(ray);
                if (info.isHit && info.distance >= 0 && info.distance < best.distance) {
                    best = info;
                    hitCount++;
                }
            }
        }

        best.hitCount = hitCount;
        return best;
    }

    getReflectionRay(P, N, V) {
        const c1 = -N.dot(V);
        const R1 = Vector.add(Vector.multiplyScalar(N, 2 * c1), V);
        return new Ray(P, R1);
    }

    rayTrace(info, ray, scene, depth) {
        // Calc ambient
        let color = Color.multiplyScalar(info.color, scene.background.ambience);
        const shininess = 10 ** (info.shape.material.gloss + 1);

        for (let i = 0; i < scene.lights.length; i++) {
            const light = scene.lights[i];

            // Calc diffuse lighting
            const v = Vector.subtract(light.position, info.position).normalize();

            if (this.options.renderDiffuse) {
                const L = v.dot(info.normal);
                if (L > 0) {
                    color = Color.add(
                        color,
                        Color.multiply(
                            info.color,
                            Color.multiplyScalar(light.color, L),
                        ),
                    );
                }
            }

            // The greater the depth the more accurate the colours, but
            // this is exponentially (!) expensive
            if (depth <= this.options.rayDepth) {
                // calculate reflection ray
                if (this.options.renderReflections && info.shape.material.reflection > 0) {
                    const reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
                    const refl = this.testIntersection(reflectionRay, scene, info.shape);

                    if (refl.isHit && refl.distance > 0) {
                        refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
                    } else {
                        refl.color = scene.background.color;
                    }

                    color = Color.blend(
                        color,
                        refl.color,
                        info.shape.material.reflection,
                    );
                }
            }

            // Render shadows and highlights
            let shadowInfo = new IntersectionInfo();

            if (this.options.renderShadows) {
                const shadowRay = new Ray(info.position, v);

                shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
                if (shadowInfo.isHit && shadowInfo.shape !== info.shape) {
                    const vA = Color.multiplyScalar(color, 0.5);
                    const dB = 0.5 * (shadowInfo.shape.material.transparency ** 0.5);
                    color = Color.addScalar(vA, dB);
                }
            }

            // Phong specular highlights
            if (this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0) {
                const Lv = Vector.subtract(info.shape.position, light.position).normalize();
                const E = Vector.subtract(scene.camera.position, info.shape.position).normalize();
                const H = Vector.subtract(E, Lv).normalize();

                const glossWeight = Math.max(info.normal.dot(H), 0) ** shininess;
                color = Color.add(Color.multiplyScalar(light.color, glossWeight), color);
            }
        }

        return color.limit();
    }
}

function renderScene() {
    const camera = new Camera(
        new Vector(0, 0, -15),
        new Vector(-0.2, 0, 5),
        new Vector(0, 1, 0),
    );
    const background = new Background(new Color(0.5, 0.5, 0.5), 0.4);

    const shapes = [
        new Sphere(
            new Vector(-1.5, 1.5, 2),
            new SolidMaterial(new Color(0, 0.5, 0.5), 0.3, 0, 2),
            1.5,
        ),
        new Sphere(
            new Vector(1, 0.25, 1),
            new SolidMaterial(new Color(0.9, 0.9, 0.9), 0.1, 0, 1.5),
            0.5,
        ),
        new Plane(
            new Vector(0.1, 0.9, -0.5).normalize(),
            new ChessboardMaterial(
                new Color(1, 1, 1),
                new Color(0, 0, 0),
                0.2, 0, 1, 0.7,
            ),
            1.2,
        ),
    ];

    const lights = [
        new Light(
            new Vector(5, 10, -1),
            new Color(0.8, 0.8, 0.8),
        ),
        new Light(
            new Vector(-3, 5, -15),
            new Color(0.8, 0.8, 0.8),
        ),
    ];

    const scene = new Scene(camera, background, shapes, lights);

    const raytracer = new Engine({
        canvasWidth: 100,
        canvasHeight: 100,
        pixelWidth: 5,
        pixelHeight: 5,
        renderDiffuse: true,
        renderHighlights: true,
        renderShadows: true,
        renderReflections: true,
        rayDepth: 2,
    });

    raytracer.renderScene(scene);
}

class Benchmark {
    runIteration() {
        for (let i = 0; i < 15; ++i)
            renderScene();
    }
}
