const std = @import("std");

const info = std.log.info;

var prng = std.rand.DefaultPrng.init(0);
const rand = prng.random();

pub const Vec3 = struct {
    v: @Vector(3, f32),

    pub fn init(v0: f32, v1: f32, v2: f32) Vec3 {
        return Vec3{
            .v = .{ v0, v1, v2 },
        };
    }
    pub fn x(vec: Vec3) f32 {
        return vec.v[0];
    }
    pub fn y(vec: Vec3) f32 {
        return vec.v[1];
    }
    pub fn z(vec: Vec3) f32 {
        return vec.v[2];
    }
    pub fn length(vec: Vec3) f32 {
        return @sqrt(vec.length_squared());
    }
    pub fn length_squared(vec: Vec3) f32 {
        return vec.v[0] * vec.v[0] + vec.v[1] * vec.v[1] + vec.v[2] * vec.v[2];
    }
    pub fn add(lhs: Vec3, rhs: Vec3) Vec3 {
        return Vec3{ .v = lhs.v + rhs.v };
    }
    pub fn sub(lhs: Vec3, rhs: Vec3) Vec3 {
        return Vec3{ .v = lhs.v - rhs.v };
    }
    pub fn scale(vec: Vec3, t: f32) Vec3 {
        return Vec3{ .v = vec.v * @splat(3, t) };
    }
    pub fn unit(vec: Vec3) Vec3 {
        return vec.scale(1 / vec.length());
    }
    pub fn dot(u: Vec3, v: Vec3) f32 {
        const t = u.v * v.v;
        return t[0] + t[1] + t[2];
    }
    /// Return value in unit cube from -1, 1
    pub fn random() Vec3 {
        return Vec3.init(
            rand.float(f32) * 2 - 1,
            rand.float(f32) * 2 - 1,
            rand.float(f32) * 2 - 1,
        );
    }
};

pub fn random_in_unit_sphere() Vec3 {
    while (true) {
        const p = Vec3.random();
        if (p.length_squared() > 1) continue;
        return p;
    }
}
pub fn random_unit_vector() Vec3 {
    return random_in_unit_sphere().unit();
}

pub const Color = Vec3;
pub const Point3 = Vec3;
