//! GhosttyBench generates all the Ghostty benchmark helper binaries.
const GhosttyBench = @This();

const std = @import("std");
const Config = @import("Config.zig");
const SharedDeps = @import("SharedDeps.zig");

steps: []*std.Build.Step.Compile,

pub fn init(
    b: *std.Build,
    deps: *const SharedDeps,
) !GhosttyBench {
    var steps = std.ArrayList(*std.Build.Step.Compile).init(b.allocator);
    errdefer steps.deinit();

    // Open the directory ./src/bench
    const c_dir_path = b.pathFromRoot("src/bench");
    var c_dir = try std.fs.cwd().openDir(c_dir_path, .{ .iterate = true });
    defer c_dir.close();

    // Go through and add each as a step
    var c_dir_it = c_dir.iterate();
    while (try c_dir_it.next()) |entry| {
        // Get the index of the last '.' so we can strip the extension.
        const index = std.mem.lastIndexOfScalar(u8, entry.name, '.') orelse continue;
        if (index == 0) continue;

        // If it doesn't end in 'zig' then ignore
        if (!std.mem.eql(u8, entry.name[index + 1 ..], "zig")) continue;

        // Name of the conformance app and full path to the entrypoint.
        const name = entry.name[0..index];

        // Executable builder.
        const bin_name = try std.fmt.allocPrint(b.allocator, "bench-{s}", .{name});
        const c_exe = b.addExecutable(.{
            .name = bin_name,
            .root_source_file = b.path("src/main.zig"),
            .target = deps.config.target,

            // We always want our benchmarks to be in release mode.
            .optimize = .ReleaseFast,
        });
        c_exe.linkLibC();

        // Update our entrypoint
        var enum_name: [64]u8 = undefined;
        @memcpy(enum_name[0..name.len], name);
        std.mem.replaceScalar(u8, enum_name[0..name.len], '-', '_');

        var buf: [64]u8 = undefined;
        const new_deps = try deps.changeEntrypoint(b, std.meta.stringToEnum(
            Config.ExeEntrypoint,
            try std.fmt.bufPrint(&buf, "bench_{s}", .{enum_name[0..name.len]}),
        ).?);

        _ = try new_deps.add(c_exe);

        try steps.append(c_exe);
    }

    return .{ .steps = steps.items };
}

pub fn install(self: *const GhosttyBench) void {
    const b = self.steps[0].step.owner;
    for (self.steps) |step| b.installArtifact(step);
}
