cmake_minimum_required(VERSION 4.1)
project(v)

set(CMAKE_CXX_STANDARD 23)

include(FetchContent)

add_executable(v main.cpp
        misc.cpp
        misc.h
        renderer/graphics.cpp
        renderer/graphics.h
        renderer/texture.cpp
        renderer/texture.h
        renderer/texture_sheet.cpp
        renderer/texture_sheet.h
        renderer/sprite.cpp
        renderer/sprite.h
        renderer/graphics_private.h
)

target_include_directories(v
        PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}
)

target_link_libraries(v PRIVATE glfw glm::glm stb)

if (EMSCRIPTEN)
    set(CMAKE_VERBOSE_MAKEFILE ON)
	message(STATUS "Configuring for Emscripten...")

    # 1. Find all .slang files in the shaders directory
    file(GLOB SLANG_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.slang")

    set(WGSL_OUTPUTS "")

    # 2. Iterate through the found files
    foreach(SOURCE_PATH ${SLANG_SOURCES})
        # Get the filename without the path or extension (e.g., "triangle")
        get_filename_component(FILENAME_WE ${SOURCE_PATH} NAME_WE)

        # Define the output path in the build directory
        set(OUTPUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/shaders/${FILENAME_WE}.wgsl")

        # 3. Define the compilation command
        add_custom_command(
                OUTPUT ${OUTPUT_PATH}
                COMMAND slangc ${SOURCE_PATH} -target wgsl -o ${OUTPUT_PATH}
                DEPENDS ${SOURCE_PATH}
                COMMENT "Compiling Slang: ${FILENAME_WE}.slang -> ${FILENAME_WE}.wgsl"
                VERBATIM
        )

        list(APPEND WGSL_OUTPUTS ${OUTPUT_PATH})
    endforeach()

    # 4. Create a single target that tracks all these outputs
    add_custom_target(CompileShaders ALL DEPENDS ${WGSL_OUTPUTS})

    add_dependencies(v CompileShaders)

    set_target_properties(v PROPERTIES SUFFIX ".html")
    target_compile_options(v PRIVATE
            "--use-port=emdawnwebgpu"
            "--use-port=contrib.glfw3"
    )
    target_link_options(v PRIVATE
            "--use-port=emdawnwebgpu"
            "-sASYNCIFY=1"
            "--use-port=contrib.glfw3"
            "--preload-file" "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
    )
    target_sources(v PRIVATE
            renderer/webgpu/renderer.cpp
            renderer/webgpu/renderer.h
            renderer/webgpu/webgpu.cpp
            renderer/webgpu/webgpu.h
            renderer/webgpu/utils_emscripten.cpp
    )
elseif (WIN32)
    message(STATUS "Configuring for Windows...")

    find_package(slang REQUIRED)

    find_package(Vulkan REQUIRED COMPONENTS volk)
    find_package(glfw3 REQUIRED)

    target_link_libraries(v PRIVATE Vulkan::Vulkan slang::slang)

    target_sources(v PRIVATE
        renderer/vulkan/vulkan.cpp
        renderer/vulkan/vulkan.h
        renderer/vulkan/renderer.cpp
        renderer/vulkan/renderer.h
    )
elseif (APPLE)
    message(STATUS "Configuring for macOS...")

    find_package(slang REQUIRED)

    find_package(glfw3 REQUIRED)

    target_include_directories(v PUBLIC
            "~/Dev/libraries/metal-cpp"
            "~/Dev/libraries/metal-cpp-extensions"
    )

    target_link_libraries(v PRIVATE
            "-framework Metal"
            "-framework MetalKit"
            "-framework AppKit"
            "-framework Foundation"
            "-framework QuartzCore"
            slang::slang
    )

    target_sources(v PRIVATE
            renderer/metal/metal.cpp
            renderer/metal/metal.h
            renderer/metal/renderer.cpp
            renderer/metal/renderer.h
    )

#[[    #shaders

    set(SHADER_DIR ${CMAKE_SOURCE_DIR}/shaders)
    set(SHADER_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/renderer/metal)

    set(SHADER_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/shaders)

    file(GLOB SHADER_SOURCES
            ${SHADER_DIR}/*.metal)

    set(AIR_FILES)

    foreach(SHADER ${SHADER_SOURCES})
        get_filename_component(NAME ${SHADER} NAME_WE)
        set(AIR_FILE ${SHADER_OUTPUT_DIR}/${NAME}.air)

        add_custom_command(
                OUTPUT ${AIR_FILE}
                COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADER_OUTPUT_DIR}
                COMMAND xcrun -sdk macosx metal -frecord-sources -gline-tables-only
                -I ${SHADER_INCLUDE_DIR}
                -c ${SHADER}
                -o ${AIR_FILE}
                DEPENDS ${SHADER}
                COMMENT "Compiling ${NAME}.metal"
        )

        list(APPEND AIR_FILES ${AIR_FILE})
    endforeach()

    set(METALLIB ${SHADER_OUTPUT_DIR}/shaders.metallib)

    add_custom_command(
            OUTPUT ${METALLIB}
            COMMAND xcrun -sdk macosx metallib
            ${AIR_FILES}
            -o ${METALLIB}
            DEPENDS ${AIR_FILES}
            COMMENT "Linking shaders.metallib"
    )

    add_custom_target(shaders ALL
            DEPENDS ${METALLIB}
    )

    add_dependencies(v shaders)]]
endif ()

FetchContent_Declare(
        glm
        GIT_REPOSITORY https://github.com/g-truc/glm.git
        GIT_TAG 1.0.3
)
FetchContent_MakeAvailable(glm)

FetchContent_Declare(
        stb
        GIT_REPOSITORY https://github.com/nothings/stb.git
        GIT_TAG        master
)

FetchContent_MakeAvailable(stb)

add_library(stb INTERFACE)
target_include_directories(stb INTERFACE ${stb_SOURCE_DIR})

set(SHADER_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/shaders")
set(SHADER_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
file(GLOB_RECURSE SHADER_SOURCES
        "${SHADER_SOURCE_DIR}/*.vert"
        "${SHADER_SOURCE_DIR}/*.frag"
        "${SHADER_SOURCE_DIR}/*.comp"
)

#[[set(SPIRV_BINARY_FILES "")

foreach(SHADER ${SHADER_SOURCES})

    get_filename_component(FILENAME ${SHADER} NAME)
    set(OUTPUT_SPV "${SHADER_SOURCE_DIR}/${FILENAME}.spv")

    add_custom_command(
            OUTPUT ${OUTPUT_SPV}
            COMMAND Vulkan::glslc ${SHADER} -o ${OUTPUT_SPV}
            DEPENDS ${SHADER}
            COMMENT "Compiling shader: ${FILENAME}"
    )

    list(APPEND SPIRV_BINARY_FILES ${OUTPUT_SPV})
endforeach()

add_custom_target(compile_shaders ALL DEPENDS ${SPIRV_BINARY_FILES})

add_dependencies(v compile_shaders)]]
