const std = @import("std");

const vk = @import("vulkan");
const Instance = @import("Context.zig").Instance;

// Validation layers stuff
pub fn createDebugMessenger(instance: Instance) !vk.DebugUtilsMessengerEXT {
    const debug_create_info = getDebugUtilsCreateInfo();

    return try instance.createDebugUtilsMessengerEXT(&debug_create_info, null);
}

pub fn getDebugUtilsCreateInfo() vk.DebugUtilsMessengerCreateInfoEXT {
    return vk.DebugUtilsMessengerCreateInfoEXT{
        .message_severity = .{ .verbose_bit_ext = true, .warning_bit_ext = true, .error_bit_ext = true },
        .message_type = .{ .general_bit_ext = true, .validation_bit_ext = true, .performance_bit_ext = true },
        .pfn_user_callback = debugCallback,
    };
}

fn debugCallback(
    message_severity: vk.DebugUtilsMessageSeverityFlagsEXT,
    message_types: vk.DebugUtilsMessageTypeFlagsEXT,
    p_callback_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
    p_user_data: ?*anyopaque,
) callconv(vk.vulkan_call_conv) vk.Bool32 {
    _ = p_user_data;
    const severity = getMessageSeverityLabel(message_severity);
    const message_type = getMessageTypeLabel(message_types);

    std.debug.print("[{s}] ({s}): {s}\n=====\n", .{ severity, message_type, p_callback_data.?.p_message.? });
    return vk.TRUE;
}

inline fn getMessageSeverityLabel(message_severity: vk.DebugUtilsMessageSeverityFlagsEXT) []const u8 {
    if (message_severity.verbose_bit_ext) {
        return "VERBOSE";
    } else if (message_severity.info_bit_ext) {
        return "INFO";
    } else if (message_severity.warning_bit_ext) {
        return "WARNING";
    } else if (message_severity.error_bit_ext) {
        return "ERROR";
    } else {
        unreachable;
    }
}

inline fn getMessageTypeLabel(message_types: vk.DebugUtilsMessageTypeFlagsEXT) []const u8 {
    if (message_types.general_bit_ext) {
        return "general";
    } else if (message_types.validation_bit_ext) {
        return "validation";
    } else if (message_types.performance_bit_ext) {
        return "performance";
    } else if (message_types.device_address_binding_bit_ext) {
        return "device_address_binding";
    } else {
        return "unknown";
    }
}
