const std = @import("std");

const Dimensions = @import("Dimensions.zig");

const c = @cImport({
    @cInclude("wkhtmltox/image.h");
});

const log = std.log.scoped(.renderer);

const Self = @This();

pub const Error = error{
    Wkhtml,
};

var wkhtmlInit = false;

pub fn init() void {
    if (!wkhtmlInit) {
        _ = c.wkhtmltoimage_init(0);
        wkhtmlInit = true;
    }
}

pub fn deinit() void {
    _ = c.wkhtmltoimage_deinit();
}

fn wkhtmlProgressChanged(converter: ?*c.wkhtmltoimage_converter, progress: c_int) callconv(.C) void {
    _ = converter;
    _ = progress;
}

fn wkhtmlPhaseChanged(converter: ?*c.wkhtmltoimage_converter) callconv(.C) void {
    _ = converter;
}

fn wkhtmlError(converter: ?*c.wkhtmltoimage_converter, msg: [*c]const u8) callconv(.C) void {
    _ = converter;
    log.err("Convert error: {s}", .{msg});
}

fn wkhtmlWarning(converter: ?*c.wkhtmltoimage_converter, msg: [*c]const u8) callconv(.C) void {
    _ = converter;
    log.warn("Convert warning: {s}", .{msg});
}

pub fn render(allocator: std.mem.Allocator, input_path: []const u8, dimensions: Dimensions) ![]const u8 {
    const input = try allocator.dupeZ(u8, input_path);
    defer allocator.free(input);

    const width = try std.fmt.allocPrintZ(allocator, "{d}", .{dimensions.width});
    defer allocator.free(width);
    const height = try std.fmt.allocPrintZ(allocator, "{d}", .{dimensions.height});
    defer allocator.free(height);

    const gs = c.wkhtmltoimage_create_global_settings().?;

    _ = c.wkhtmltoimage_set_global_setting(gs, "web.loadImages", "true");

    _ = c.wkhtmltoimage_set_global_setting(gs, "screenWidth", width);
    _ = c.wkhtmltoimage_set_global_setting(gs, "smartWidth", "false");
    _ = c.wkhtmltoimage_set_global_setting(gs, "crop.width", width);
    _ = c.wkhtmltoimage_set_global_setting(gs, "crop.height", height);

    _ = c.wkhtmltoimage_set_global_setting(gs, "in", input);
    _ = c.wkhtmltoimage_set_global_setting(gs, "fmt", "png");
    _ = c.wkhtmltoimage_set_global_setting(gs, "transparent", "false");
    _ = c.wkhtmltoimage_set_global_setting(gs, "quality", "100");

    const converter = c.wkhtmltoimage_create_converter(gs, 0).?;
    defer c.wkhtmltoimage_destroy_converter(converter);

    c.wkhtmltoimage_set_progress_changed_callback(converter, wkhtmlProgressChanged);
    c.wkhtmltoimage_set_phase_changed_callback(converter, wkhtmlPhaseChanged);
    c.wkhtmltoimage_set_error_callback(converter, wkhtmlError);
    c.wkhtmltoimage_set_warning_callback(converter, wkhtmlWarning);

    if (c.wkhtmltoimage_convert(converter) == 0) {
        log.err("Conversion failed", .{});
        return Error.Wkhtml;
    }

    var data: [*c]const u8 = undefined;
    const len = c.wkhtmltoimage_get_output(converter, &data);
    const img = data[0..@intCast(len)];

    return try allocator.dupe(u8, img);
}
