cmake_minimum_required(VERSION 3.20)
project(vkzip VERSION 1.0.0 LANGUAGES C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

# ── Platform detection ──────────────────────────────────────────────
if(WIN32)
    add_definitions(-D_CRT_SECURE_NO_WARNINGS -DPLATFORM_WINDOWS)
else()
    add_definitions(-DPLATFORM_LINUX)
endif()

# ── Find Vulkan / Volk ──────────────────────────────────────────────
if(WIN32)
    # Use volk on Windows to load Vulkan dynamically without an import library
    message(STATUS "Using volk for Vulkan loading on Windows")
    add_executable(vkzip
        external/volk/volk.c
        src/main.c
        src/vkz_format.c
        src/gpu_context.c
        src/gpu_compress.c
        src/gpu_decompress.c
        src/cpu_fallback.c)
    target_include_directories(vkzip PRIVATE external/volk external)
else()
    find_package(Vulkan REQUIRED COMPONENTS glslc glslangValidator)
    add_executable(vkzip
        src/main.c
        src/vkz_format.c
        src/gpu_context.c
        src/gpu_compress.c
        src/gpu_decompress.c
        src/cpu_fallback.c)
    target_include_directories(vkzip PRIVATE
        ${CMAKE_SOURCE_DIR}/src
        ${Vulkan_INCLUDE_DIRS}
    )
    target_link_libraries(vkzip PRIVATE Vulkan::Vulkan m pthread)
endif()

# ── Compile shaders (GLSL → SPIR-V) ────────────────────────────────
find_program(GLSLC glslc HINTS "$ENV{VULKAN_SDK}/bin")
if(NOT GLSLC)
    find_program(GLSLC glslangValidator HINTS "$ENV{VULKAN_SDK}/bin")
endif()

if(GLSLC)
    set(SHADER_SRC_DIR "${CMAKE_SOURCE_DIR}/shaders")
    set(SHADER_BIN_DIR "${CMAKE_BINARY_DIR}/shaders")
    file(MAKE_DIRECTORY ${SHADER_BIN_DIR})

    set(SHADER_SOURCES
        ${SHADER_SRC_DIR}/compress.comp
        ${SHADER_SRC_DIR}/decompress.comp
    )

    foreach(SHADER ${SHADER_SOURCES})
        get_filename_component(SHADER_NAME ${SHADER} NAME)
        set(SPIRV_OUTPUT "${SHADER_BIN_DIR}/${SHADER_NAME}.spv")

        add_custom_command(
            OUTPUT ${SPIRV_OUTPUT}
            COMMAND ${GLSLC} -o ${SPIRV_OUTPUT} ${SHADER}
            DEPENDS ${SHADER}
            COMMENT "Compiling shader ${SHADER_NAME} -> SPIR-V"
        )
        list(APPEND SPIRV_OUTPUTS ${SPIRV_OUTPUT})
    endforeach()

    add_custom_target(shaders ALL DEPENDS ${SPIRV_OUTPUTS})
    add_dependencies(vkzip shaders)

    # Embed shader directory path at compile time
    target_compile_definitions(vkzip PRIVATE
        SHADER_DIR="${SHADER_BIN_DIR}"
    )
else()
    message(WARNING "glslc/glslangValidator not found! Shaders will not be compiled.")
    message(WARNING "Install Vulkan SDK: https://vulkan.lunarg.com/sdk/home")
endif()

# ── Install ─────────────────────────────────────────────────────────
install(TARGETS vkzip RUNTIME DESTINATION bin)
if(GLSLC)
    install(DIRECTORY ${SHADER_BIN_DIR}/ DESTINATION share/vkzip/shaders)
endif()

# ── Compiler warnings ──────────────────────────────────────────────
if(MSVC)
    target_compile_options(vkzip PRIVATE /W4)
else()
    target_compile_options(vkzip PRIVATE -Wall -Wextra -O2)
endif()

message(STATUS "")
message(STATUS "╔══════════════════════════════════════════╗")
message(STATUS "║        VKZip - GPU File Compressor       ║")
message(STATUS "║    Vulkan Compute Shader Acceleration    ║")
message(STATUS "╠══════════════════════════════════════════╣")
message(STATUS "║  Platform: ${CMAKE_SYSTEM_NAME}")
message(STATUS "║  Compiler: ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}")
message(STATUS "║  Vulkan:   ${Vulkan_LIBRARY}")
message(STATUS "║  Shaders:  ${GLSLC}")
message(STATUS "╚══════════════════════════════════════════╝")
message(STATUS "")
