const std = @import("std");
const lib = @import("zig-shape-lib");
const builtin = @import("builtin");

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const alloc = gpa.allocator();

    const core = try Core.init(alloc, .{});
    defer core.deinit();

    std.log.debug("Created instance: {any}", .{core.i.handle});
    std.log.debug("Created device: {any}", .{core.d.handle});
    std.log.debug("Created queue: {any}", .{core.q.handle});
    std.log.debug("Created surface: {any}", .{core.surface});

    var sc = try Core.SwapChain(void).init(alloc, &core, 3);
    defer sc.deinit();

    // var caps = try I.getPhysicalDeviceSurfaceCapabilitiesKHR(pdev, surface);
    // const format = search: {
    //     const formats = try I.getPhysicalDeviceSurfaceFormatsAllocKHR(pdev, surface, alloc);
    //     defer alloc.free(formats);
    //     for (formats) |f| {
    //         if (f.color_space == .srgb_nonlinear_khr) break :search f;
    //     } else break :search formats[0];
    // };
    // const mode: vk.PresentModeKHR = .fifo_khr;

    // var scinfo: vk.SwapchainCreateInfoKHR = .{
    //     .surface = surface,
    //     .min_image_count = std.math.clamp(
    //         @min(3, caps.min_image_count + 1),
    //         caps.min_image_count,
    //         if (caps.max_image_count > 0) caps.max_image_count else 127,
    //     ),
    //     .image_format = format.format,
    //     .image_color_space = format.color_space,
    //     .image_extent = undefined, // set in rebuild
    //     .image_array_layers = 1,
    //     .image_usage = .{ .color_attachment_bit = true },
    //     .image_sharing_mode = .exclusive,
    //     .pre_transform = .{ .identity_bit_khr = true },
    //     .composite_alpha = .{ .opaque_bit_khr = true },
    //     .present_mode = mode,
    //     .clipped = vk.TRUE,
    //     .old_swapchain = .null_handle,
    // };

    // var sc: vk.SwapchainKHR = .null_handle;
    // defer D.destroySwapchainKHR(device, sc, null);

    // const FRAMES_IN_FLIGHT = 3;
    //
    // var pools = [FRAMES_IN_FLIGHT]vk.CommandPool;
    // var fence = [FRAMES_IN_FLIGHT]vk.Fence;

    // const pool = D.createCommandPool(device, &.{
    //     .queue_family_index = family,
    // }, null);
    // defer D.destroyCommandPool(device, pool, null);

    // var cmd: vk.CommandBuffer = undefined;
    // try D.allocateCommandBuffers(device, &.{vk.CommandBufferAllocateInfo{
    //     .command_buffer_count = 1,
    //     .command_pool = pool,
    //     .level = .primary,
    // }}, @ptrCast(&cmd));
    // defer D.freeCommandBuffers(device, pool, 1, @ptrCast(&cmd));

    // while (glfw.glfwWindowShouldClose(window) == glfw.GLFW_FALSE) {
    //     if (glfw.glfwGetWindowAttrib(window, glfw.GLFW_FOCUSED) == glfw.GLFW_TRUE)
    //         glfw.glfwPollEvents()
    //     else
    //         glfw.glfwWaitEventsTimeout(1.0 / 60.0);
    //
    //     if (sc == .null_handle) {
    //         caps = try I.getPhysicalDeviceSurfaceCapabilitiesKHR(pdev, surface);
    //         scinfo.image_extent = caps.current_extent;
    //         sc = try D.createSwapchainKHR(device, &scinfo, null);
    //         D.destroySwapchainKHR(device, scinfo.old_swapchain, null);
    //         scinfo.old_swapchain = .null_handle;
    //     }
    //
    //     const render_area: vk.Rect2D = .{
    //         .offset = .{ .x = 0, .y = 0 },
    //         .extent = scinfo.image_extent,
    //     };
    //
    //     try D.resetCommandPool(device, pool, .{});
    //     try D.beginCommandBuffer(cmd, .{ .flags = .{ .one_time_submit_bit = true } });
    //     {
    //         D.cmdPipelineBarrier(
    //             cmd,
    //             .{ .top_of_pipe_bit = true },
    //             .{ .color_attachment_output_bit = true },
    //             .{},
    //             0,
    //             null,
    //             0,
    //             null,
    //             1,
    //             &.{
    //                 vk.ImageMemoryBarrier{
    //                     .src_access_mask = .{},
    //                     .dst_access_mask = .{ .color_attachment_write_bit = true },
    //                     .old_layout = .undefined,
    //                     .new_layout = .color_attachment_optimal,
    //                     .src_queue_family_index = 0,
    //                     .dst_queue_family_index = 0,
    //                     .image = image,
    //                     .subresource_range = .{
    //                         .aspect_mask = .{ .color_bit = true },
    //                         .base_mip_level = 0,
    //                         .level_count = 1,
    //                         .base_array_layer = 0,
    //                         .layer_count = 1,
    //                     },
    //                 },
    //             },
    //         );
    //
    //         D.cmdPipelineBarrier(
    //             cmd,
    //             .{ .color_attachment_output_bit = true },
    //             .{ .bottom_of_pipe_bit = true },
    //             .{},
    //             0,
    //             null,
    //             0,
    //             null,
    //             1,
    //             &.{
    //                 vk.ImageMemoryBarrier{
    //                     // todo !
    //                 },
    //             },
    //         );
    //     }
    //     try D.endCommandBuffer(cmd);
    // }
}

test "simple test" {
    var list = std.ArrayList(i32).init(std.testing.allocator);
    defer list.deinit(); // Try commenting this out and see if zig detects the memory leak!
    try list.append(42);
    try std.testing.expectEqual(@as(i32, 42), list.pop());
}

test "use other module" {
    try std.testing.expectEqual(@as(i32, 150), lib.add(100, 50));
}

test "fuzz example" {
    const Context = struct {
        fn testOne(context: @This(), input: []const u8) anyerror!void {
            _ = context;
            // Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
            try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
        }
    };
    try std.testing.fuzz(Context{}, Context.testOne, .{});
}
