const std = @import("std");

// pub fn eye(D: comptime_int, T: type) [D][D]T {
//     var out: [D][D]T = undefined;
//     @memset(out, 0);
//     for (0..D) |d| out[d] = 1;
//     return out;
// }

// pub fn eye(D: comptime_int, T: type) [D][D]T {
//     var out = std.mem.zeroes([D][D]T);
//     for (0..D) |d| out[d][d] = 1;
//     return out;
// }

// pub fn _matmul_result(A: type, B: type) type {
//     const a = @typeInfo(A);
//     // const s = a.Pointer.size;
//     // a.Pointer.size.
//     const b = @typeInfo(B);
// }
// pub fn matmul(A: anytype, B: anytype)

/// r := ab
pub fn matmul(r: anytype, a: anytype, b: anytype) void {
    const R = @typeInfo(@TypeOf(r));
    const A = @typeInfo(@TypeOf(a));
    const B = @typeInfo(@TypeOf(b));

    // B.Pointer.child

    switch (B) {
        .Array => {
            // handle static columns
            switch (@typeInfo(B.Array.child)) {
                .Array => {
                    // handle static rows
                },
                .Pointer => {
                    // handle dynamic rows
                },
                else => @compileError("."),
            }
        },
        .Pointer => {
            switch (@typeInfo(B.Pointer.size)) {
                .Slice => {
                    // handle dynamic columns
                },
                else => @compileError("."),
            }
        },
        else => @compileError("."),
    }

    // switch(R) {
    //     .Array {
    //         R.Array.sentinel
    //         // R.Array.len
    //     },
    //     .Pointer {
    //
    //     },
    // }
}

test "matmul" {
    const a: [3][4]f32 = undefined;
    const b: [2][3]f32 = undefined;

    var r: [2][4]f32 = undefined;
    matmul(r, a, b);
}

test {
    const alloc = std.testing.allocator;
    var arr: std.MultiArrayList(std.meta.Tuple(&.{ usize, usize, usize })) = undefined;
    // try arr.append(alloc, .{ 1, 2, 3 });
    // try arr.append(alloc, .{ 3, 4, 5 });
    // try arr.append(alloc, .{ 6, 7, 8 });

    // std.debug.print(comptime fmt: []const u8, args: anytype)

    // [1][4]f32;
    //
    // [4][4]f32;
    //
    // [][4]f32;
    //
    // [4][1]f32;

    // const Vec3f = [3]f32;
    //
    // const vv: Vec3f = .{ 1, 0, 0 };
    // try std.testing.expect(std.mem.eql(f32, &vv, &.{ 1, 0, 0 }));
    //
    // const mm = eye(3, f32);
    // std.debug.print("mm: {any}\n", .{mm});
}
