cmake_minimum_required(VERSION 3.20)
project(minecraft_vulkan LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Vulkan REQUIRED)

# Windows: prefer full static linking — use .a instead of .dll.a
if(WIN32)
    # Force CMake to prefer static libs (.a) over import libs (.dll.a)
    set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib")

    # Static GLFW
    find_library(GLFW_STATIC_LIB NAMES glfw3 libglfw3
                 PATHS /mingw64/lib /usr/x86_64-w64-mingw32/lib
                 NO_DEFAULT_PATH)
    if(NOT GLFW_STATIC_LIB)
        find_library(GLFW_STATIC_LIB NAMES glfw3 libglfw3)
    endif()
    if(NOT GLFW_STATIC_LIB)
        message(FATAL_ERROR "libglfw3.a not found — install mingw-w64-x86_64-glfw")
    endif()

    # Static OpenAL (NOT mingw-deps' import lib — that one forces OpenAL32.dll at runtime)
    find_library(OPENAL_STATIC_LIB NAMES openal libopenal
                 PATHS /mingw64/lib /usr/x86_64-w64-mingw32/lib
                 NO_DEFAULT_PATH)
    if(NOT OPENAL_STATIC_LIB)
        find_library(OPENAL_STATIC_LIB NAMES openal libopenal)
    endif()
    if(NOT OPENAL_STATIC_LIB)
        message(FATAL_ERROR "libopenal.a not found — install mingw-w64-x86_64-openal")
    endif()

    # OpenAL public headers
    find_path(OPENAL_INCLUDE_DIR AL/al.h
              PATHS /mingw64/include ${CMAKE_SOURCE_DIR}/mingw-deps/include)
endif()
if(NOT WIN32)
    find_package(glfw3 REQUIRED)
endif()

add_executable(minecraft
    src/main.cpp
    src/app.cpp
    src/app_input.cpp
    src/app_mobs.cpp
    src/app_ui.cpp
    src/app_world.cpp
    src/audio.cpp
    src/camera.cpp
    src/chunk.cpp
    src/chunk_mesh.cpp
    src/debug_draw.cpp
    src/raycast.cpp
    src/stb_image_impl.cpp
    src/texture_atlas.cpp
    src/vulkan_texture.cpp
    src/world.cpp
    src/vulkan_core.cpp
    src/vulkan_swapchain.cpp
    src/vulkan_pipeline.cpp
    src/vulkan_buffers.cpp
    src/vulkan_entities.cpp
    src/vulkan_render.cpp
    src/vulkan_sky.cpp
    src/vulkan_uniforms.cpp
    src/world_save.cpp
)

target_include_directories(minecraft PRIVATE src)
if(WIN32)
    target_include_directories(minecraft PRIVATE ${OPENAL_INCLUDE_DIR})
    target_compile_definitions(minecraft PRIVATE AL_LIBTYPE_STATIC GLFW_STATIC)
    target_link_libraries(minecraft PRIVATE
        ${GLFW_STATIC_LIB}
        ${OPENAL_STATIC_LIB}
        Vulkan::Vulkan
        # GLFW static needs:
        gdi32 user32 shell32 imm32
        # OpenAL Soft static needs:
        winmm ole32 avrt ksuser uuid
    )
else()
    target_link_libraries(minecraft PRIVATE glfw Vulkan::Vulkan openal)
endif()

if(APPLE)
    find_library(METAL_LIB Metal)
    find_library(QUARTZCORE_LIB QuartzCore)
    find_library(COCOA_LIB Cocoa)
    target_link_libraries(minecraft PRIVATE ${METAL_LIB} ${QUARTZCORE_LIB} ${COCOA_LIB})
endif()

if(WIN32)
    # Embed application icon — use --use-temp-file to work around windres popen bug
    set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} --use-temp-file")
    target_sources(minecraft PRIVATE installer/assets/icon.rc)
    # Disable stack protector to avoid libssp-0.dll runtime dependency
    target_compile_options(minecraft PRIVATE -fno-stack-protector)
    # Link MinGW runtimes statically so exe runs without extra DLLs.
    # -static forces static linking of EVERYTHING possible (incl. libssp, libwinpthread, libgcc, libstdc++).
    target_link_options(minecraft PRIVATE -static -static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive)
    # No console window in Release
    target_link_options(minecraft PRIVATE $<$<CONFIG:Release>:-mwindows>)
endif()