const std = @import("std");
const toml = @import("toml");

const formatters = @import("formatters/init.zig");
const formatter = @import("formatter.zig");
const modules = @import("modules/init.zig");
const module = @import("module.zig");

const gpa = std.heap.page_allocator;

const Entry = struct {
    m: []const u8, // modifier
    f: ?[]const u8, // format
};

const Config = struct {
    entries: []const Entry,
};

pub fn main() !void {
    var parser = toml.Parser(Config).init(gpa);
    defer parser.deinit();

    var args = std.process.args();
    _ = args.next(); // skip the first argument
    const config_path = args.next(); // use the second argument as the config path

    var result: ?toml.Parsed(Config) = null;
    if (config_path) |c| {
        result = parser.parseFile(c) catch null;
    }
    if (result == null) {
        result = try parser.parseString(@embedFile("config.toml"));
    }
    defer result.?.deinit();

    // setup the stdout printer which is setup to only print on exit
    var buf: [1024]u8 = undefined;
    var stdout_writer = std.fs.File.stdout().writer(&buf);
    const stdout = &stdout_writer.interface;
    defer stdout.flush() catch {};

    // print out all modules in order based on the config
    const config = result.?.value;
    for (config.entries) |entry| {
        var mod: module = undefined;
        var fmt: ?formatter = null;

        // modules
        for (modules.modules) |m| {
            if (std.mem.eql(u8, entry.m, m.name)) {
                mod = m;
                break;
            }
        }

        // formats
        if (entry.f) |format| {
            for (formatters.formatters) |f| {
                if (std.mem.eql(u8, format, f.name)) {
                    fmt = f;
                    break;
                }
            }
        }

        // get the data and format if needed
        const tmp = try mod.callback();
        var txt: []const u8 = tmp;
        if (fmt) |f| {
            txt = try f.callback(tmp);
        }

        // print the module
        try stdout.print("{s}{s}\n", .{
            if (fmt) |_| "" else mod.prefix,
            txt,
        });
    }
}
