// 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,
// dropping namespaces and Prototype.js class system, as well as slightly refactored.
// All the computational code still remains untouched.

class Color {
    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 {
    constructor(position, color) {
        this.position = position;
        this.color = color;
    }

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

class Vector {
    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 {
    constructor(position, direction) {
        this.position = position;
        this.direction = direction;
    }

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

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

class Material {
    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 {
    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 {
    constructor(position, material) {
        this.position = position;
        this.material = material;
    }

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

class Sphere extends Shape {
    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 {
    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 {
    constructor() {
        this.isHit = false;
        this.hitCount = 0;
        this.shape = null;
        this.position = null;
        this.normal = null;
        this.color = IntersectionInfo.defaultColor;
        this.distance = null;
    }

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

IntersectionInfo.defaultColor = new Color(0, 0, 0);

class Camera {
    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 {
    constructor(color, ambience) {
        this.color = color;
        this.ambience = ambience;
    }

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

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

        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();
    }
}
