/*
 * Copyright © 2026 Valve Corporation
 *
 * SPDX-License-Identifier: MIT
 */

#include <cstdint>

#include "rti_app.h"
#include "rti_file_view.h"
#include "rti_util.h"

#include "backends/imgui_impl_sdl3.h"
#include "vulkan/vulkan_core.h"

int
main(int argc, char **argv)
{
   rti_app app = rti_app();
   int ret = rti_app_init(&app);
   if (ret)
      return ret;

   for (int i = 1; i < argc; i++)
      app.open_files.push_back(rti_create_file_view(&app, argv[i]));

   VkResult result;
   bool needs_resize = true;
   bool done = false;
   while (!done) {
      SDL_Event event;

      while (SDL_PollEvent(&event)) {
         ImGui_ImplSDL3_ProcessEvent(&event);
         if (event.type == SDL_EVENT_QUIT)
            done = true;
         if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(app.window))
            done = true;
      }

      if (SDL_GetWindowFlags(app.window) & SDL_WINDOW_MINIMIZED) {
         SDL_Delay(10);
         continue;
      }

      int width, height;
      SDL_GetWindowSize(app.window, &width, &height);
      if (app.imgui_window.Width != width || app.imgui_window.Height != height)
         needs_resize = true;

      if (needs_resize) {
         rti_app_resize(&app, width, height);
         needs_resize = false;
         continue;
      }

      VkSemaphore image_acquired_semaphore =
         app.imgui_window.FrameSemaphores[app.imgui_window.SemaphoreIndex].ImageAcquiredSemaphore;
      VkSemaphore render_complete_semaphore =
         app.imgui_window.FrameSemaphores[app.imgui_window.SemaphoreIndex].RenderCompleteSemaphore;
      result = vkAcquireNextImageKHR(app.device, app.imgui_window.Swapchain, UINT64_MAX, image_acquired_semaphore,
                                     VK_NULL_HANDLE, &app.imgui_window.FrameIndex);
      if (result != VK_SUCCESS) {
         if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
            needs_resize = true;
            continue;
         }
         rti_check_vk_result(result);
      }

      ImGui_ImplVulkanH_Frame *fd = &app.imgui_window.Frames[app.imgui_window.FrameIndex];
      rti_check_vk_result(vkWaitForFences(app.device, 1, &fd->Fence, VK_TRUE, UINT64_MAX));
      rti_check_vk_result(vkResetFences(app.device, 1, &fd->Fence));

      rti_check_vk_result(vkResetCommandPool(app.device, fd->CommandPool, 0));

      VkCommandBufferBeginInfo command_buffer_begin_info = {
         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
      };
      rti_check_vk_result(vkBeginCommandBuffer(fd->CommandBuffer, &command_buffer_begin_info));

      ImGui_ImplVulkan_NewFrame();
      ImGui_ImplSDL3_NewFrame();
      ImGui::NewFrame();

      app.command_buffer = fd->CommandBuffer;
      if (rti_app_run(&app))
         break;

      ImGui::Render();

      ImDrawData *draw_data = ImGui::GetDrawData();

      VkRenderPassBeginInfo render_pass_begin_info = {
         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
         .renderPass = app.imgui_window.RenderPass,
         .framebuffer = fd->Framebuffer,
         .renderArea =
            {
               .extent =
                  {
                     .width = (uint32_t)app.imgui_window.Width,
                     .height = (uint32_t)app.imgui_window.Height,
                  },
            },
         .clearValueCount = 1,
         .pClearValues = &app.imgui_window.ClearValue,
      };
      vkCmdBeginRenderPass(fd->CommandBuffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);

      ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);

      vkCmdEndRenderPass(fd->CommandBuffer);

      rti_check_vk_result(vkEndCommandBuffer(fd->CommandBuffer));

      VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
      VkSubmitInfo submit_info = {
         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
         .waitSemaphoreCount = 1,
         .pWaitSemaphores = &image_acquired_semaphore,
         .pWaitDstStageMask = &wait_stage,
         .commandBufferCount = 1,
         .pCommandBuffers = &fd->CommandBuffer,
         .signalSemaphoreCount = 1,
         .pSignalSemaphores = &render_complete_semaphore,
      };
      rti_check_vk_result(vkQueueSubmit(app.queue, 1, &submit_info, fd->Fence));

      VkPresentInfoKHR present_info = {
         .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
         .waitSemaphoreCount = 1,
         .pWaitSemaphores = &render_complete_semaphore,
         .swapchainCount = 1,
         .pSwapchains = &app.imgui_window.Swapchain,
         .pImageIndices = &app.imgui_window.FrameIndex,
      };
      result = vkQueuePresentKHR(app.queue, &present_info);
      if (result != VK_SUCCESS) {
         if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
            needs_resize = true;
            continue;
         }
         rti_check_vk_result(result);
      }
      app.imgui_window.SemaphoreIndex = (app.imgui_window.SemaphoreIndex + 1) % app.imgui_window.SemaphoreCount;
   }

   rti_app_finish(&app);

   return 0;
}
