# Minimum version of CMake required
cmake_minimum_required(VERSION 3.14)

# Project name
project(McRogueFace)

# Specify the C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Headless build option (no SFML, no graphics - for server/testing/Emscripten prep)
option(MCRF_HEADLESS "Build without graphics dependencies (SFML, ImGui)" OFF)

# SDL2 backend option (SDL2 + OpenGL ES 2 - for Emscripten/WebGL, Android, cross-platform)
option(MCRF_SDL2 "Build with SDL2+OpenGL ES 2 backend instead of SFML" OFF)

# Playground mode - minimal scripts for web playground (REPL-focused)
option(MCRF_PLAYGROUND "Build with minimal playground scripts instead of full game" OFF)

# Demo mode - self-contained demo game for web showcase
option(MCRF_DEMO "Build with demo scripts (web showcase)" OFF)

# Game shell mode - fullscreen canvas, no REPL chrome (for itch.io / standalone web games)
option(MCRF_GAME_SHELL "Use minimal game-only HTML shell (no REPL)" OFF)

# Debug/sanitizer build options
option(MCRF_SANITIZE_ADDRESS "Build with AddressSanitizer" OFF)
option(MCRF_SANITIZE_UNDEFINED "Build with UBSan" OFF)
option(MCRF_SANITIZE_THREAD "Build with ThreadSanitizer" OFF)
option(MCRF_DEBUG_PYTHON "Link against debug CPython from __lib_debug/" OFF)
option(MCRF_FREE_THREADED_PYTHON "Link against free-threaded CPython (python3.14t)" OFF)
option(MCRF_WASM_DEBUG "Build WASM with DWARF debug info and source maps" OFF)
option(MCRF_FUZZER "Build with libFuzzer coverage instrumentation for atheris" OFF)

# Validate mutually exclusive sanitizers
if(MCRF_SANITIZE_ADDRESS AND MCRF_SANITIZE_THREAD)
    message(FATAL_ERROR "ASan and TSan are mutually exclusive. Use one or the other.")
endif()

# Validate debug Python library exists when requested
if(MCRF_DEBUG_PYTHON)
    if(NOT EXISTS "${CMAKE_SOURCE_DIR}/__lib_debug/libpython3.14.so.1.0")
        message(FATAL_ERROR
            "__lib_debug/libpython3.14.so.1.0 not found.\n"
            "Build it first: tools/build_debug_python.sh")
    endif()
    message(STATUS "Using debug CPython from __lib_debug/")
endif()

# Emscripten builds: use SDL2 if specified, otherwise fall back to headless
if(EMSCRIPTEN)
    if(MCRF_SDL2)
        message(STATUS "Emscripten detected - using SDL2 backend")
        set(MCRF_HEADLESS OFF)
    else()
        set(MCRF_HEADLESS ON)
        message(STATUS "Emscripten detected - forcing HEADLESS mode (use -DMCRF_SDL2=ON for graphics)")
    endif()
endif()

if(MCRF_SDL2)
    message(STATUS "Building with SDL2 backend - SDL2+OpenGL ES 2")
endif()

if(MCRF_PLAYGROUND)
    message(STATUS "Building in PLAYGROUND mode - minimal scripts for web REPL")
endif()

if(MCRF_HEADLESS)
    message(STATUS "Building in HEADLESS mode - no SFML/ImGui dependencies")
endif()

# Detect cross-compilation for Windows (MinGW)
if(CMAKE_CROSSCOMPILING AND WIN32)
    set(MCRF_CROSS_WINDOWS TRUE)
    message(STATUS "Cross-compiling for Windows using MinGW")
endif()

# Add include directories
include_directories(${CMAKE_SOURCE_DIR}/deps)
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/deps/libtcod)
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CMAKE_SOURCE_DIR}/src/3d)
include_directories(${CMAKE_SOURCE_DIR}/src/platform)
include_directories(${CMAKE_SOURCE_DIR}/src/tiled)
include_directories(${CMAKE_SOURCE_DIR}/src/ldtk)
include_directories(${CMAKE_SOURCE_DIR}/src/audio)
include_directories(${CMAKE_SOURCE_DIR}/modules/RapidXML)
include_directories(${CMAKE_SOURCE_DIR}/modules/json/single_include)

# Python includes: use different paths for Windows vs Linux vs Emscripten
if(EMSCRIPTEN)
    # Emscripten build: use Python headers compiled for wasm32-emscripten
    # The pyconfig.h from cross-build has correct LONG_BIT and other settings
    set(PYTHON_WASM_BUILD "${CMAKE_SOURCE_DIR}/deps/cpython/cross-build/wasm32-emscripten/build/python")
    # Force-include wasm pyconfig.h BEFORE anything else to set correct platform defines
    add_compile_options(-include ${PYTHON_WASM_BUILD}/pyconfig.h)
    # Override LONG_BIT - Emscripten's limits.h incorrectly defines it as 64 for wasm32
    add_compile_definitions(LONG_BIT=32)
    # Include wasm build directory FIRST so its pyconfig.h is found by #include "pyconfig.h"
    include_directories(BEFORE ${PYTHON_WASM_BUILD})
    include_directories(${CMAKE_SOURCE_DIR}/deps/cpython/Include)
    message(STATUS "Using Emscripten Python from: ${PYTHON_WASM_BUILD}")
elseif(MCRF_CROSS_WINDOWS)
    # Windows cross-compilation: use cpython headers with PC/pyconfig.h
    # Problem: Python.h uses #include "pyconfig.h" which finds Include/pyconfig.h (Linux) first
    # Solution: Use -include to force Windows pyconfig.h to be included first
    # This defines MS_WINDOWS before Python.h is processed, ensuring correct struct layouts
    add_compile_options(-include ${CMAKE_SOURCE_DIR}/deps/cpython/PC/pyconfig.h)
    include_directories(${CMAKE_SOURCE_DIR}/deps/cpython/Include)
    include_directories(${CMAKE_SOURCE_DIR}/deps/cpython/PC)  # For other Windows-specific headers
    # Also include SFML and libtcod Windows headers
    include_directories(${CMAKE_SOURCE_DIR}/__lib_windows/sfml/include)
    include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/__lib_windows/libtcod/include)
else()
    # Native builds (Linux/Windows): use existing Python setup
    include_directories(${CMAKE_SOURCE_DIR}/deps/cpython)
    include_directories(${CMAKE_SOURCE_DIR}/deps/Python)
endif()

# ImGui and ImGui-SFML include directories (not needed in headless or SDL2 mode)
# SDL2 builds will use ImGui with SDL2 backend later; for now, no ImGui
if(NOT MCRF_HEADLESS AND NOT MCRF_SDL2)
    include_directories(${CMAKE_SOURCE_DIR}/modules/imgui)
    include_directories(${CMAKE_SOURCE_DIR}/modules/imgui-sfml)

    # ImGui source files
    set(IMGUI_SOURCES
        ${CMAKE_SOURCE_DIR}/modules/imgui/imgui.cpp
        ${CMAKE_SOURCE_DIR}/modules/imgui/imgui_draw.cpp
        ${CMAKE_SOURCE_DIR}/modules/imgui/imgui_tables.cpp
        ${CMAKE_SOURCE_DIR}/modules/imgui/imgui_widgets.cpp
        ${CMAKE_SOURCE_DIR}/modules/imgui-sfml/imgui-SFML.cpp
    )
endif()

# Collect all the source files
file(GLOB_RECURSE SOURCES "src/*.cpp")

# Add ImGui sources to the build (only if using SFML)
if(NOT MCRF_HEADLESS AND NOT MCRF_SDL2)
    list(APPEND SOURCES ${IMGUI_SOURCES})
    # Add GLAD for OpenGL function loading (needed for 3D rendering on SFML)
    list(APPEND SOURCES "${CMAKE_SOURCE_DIR}/src/3d/glad.c")
endif()

# Find OpenGL (required by ImGui-SFML) - not needed in headless mode
# SDL2 builds handle OpenGL ES 2 differently (via SDL2 or Emscripten)
if(NOT MCRF_HEADLESS AND NOT MCRF_SDL2)
    if(MCRF_CROSS_WINDOWS)
        # For cross-compilation, OpenGL is provided by MinGW
        set(OPENGL_LIBRARIES opengl32)
    else()
        find_package(OpenGL REQUIRED)
        set(OPENGL_LIBRARIES OpenGL::GL)
    endif()
endif()

# Create a list of libraries to link against
if(EMSCRIPTEN)
    # Emscripten build: link against WASM-compiled Python and libtcod
    set(PYTHON_WASM_BUILD "${CMAKE_SOURCE_DIR}/deps/cpython/cross-build/wasm32-emscripten/build/python")
    set(PYTHON_WASM_PREFIX "${CMAKE_SOURCE_DIR}/deps/cpython/cross-build/wasm32-emscripten/prefix")
    set(LIBTCOD_WASM_BUILD "${CMAKE_SOURCE_DIR}/modules/libtcod-headless/build-emscripten")
    # Collect HACL crypto object files (not included in libpython3.14.a)
    file(GLOB PYTHON_HACL_OBJECTS "${PYTHON_WASM_BUILD}/Modules/_hacl/*.o")
    set(LINK_LIBS
        ${PYTHON_WASM_BUILD}/libpython3.14.a
        ${PYTHON_HACL_OBJECTS}
        ${PYTHON_WASM_BUILD}/Modules/expat/libexpat.a
        ${PYTHON_WASM_PREFIX}/lib/libmpdec.a
        ${PYTHON_WASM_PREFIX}/lib/libffi.a
        ${LIBTCOD_WASM_BUILD}/libtcod.a
        ${LIBTCOD_WASM_BUILD}/_deps/lodepng-c-build/liblodepng-c.a
        ${LIBTCOD_WASM_BUILD}/_deps/utf8proc-build/libutf8proc.a)
    include_directories(${CMAKE_SOURCE_DIR}/deps/platform/linux)  # Use Linux platform stubs for now
    # For SDL2 builds, add stb headers for image/font loading
    if(MCRF_SDL2)
        include_directories(${CMAKE_SOURCE_DIR}/deps/stb)
    endif()
    message(STATUS "Linking Emscripten Python: ${PYTHON_WASM_BUILD}/libpython3.14.a")
    message(STATUS "Linking Emscripten libtcod: ${LIBTCOD_WASM_BUILD}/libtcod.a")
elseif(MCRF_SDL2)
    # SDL2 build (non-Emscripten): link against SDL2 and system libraries
    # Note: For desktop SDL2 builds in the future
    find_package(SDL2 REQUIRED)
    find_package(OpenGL REQUIRED)
    set(LINK_LIBS
        SDL2::SDL2
        OpenGL::GL
        tcod
        python3.14
        m dl util pthread)
    include_directories(${CMAKE_SOURCE_DIR}/deps/platform/linux)
    include_directories(${CMAKE_SOURCE_DIR}/deps/stb)  # stb_image.h, stb_truetype.h
    link_directories(${CMAKE_SOURCE_DIR}/__lib)
    message(STATUS "Building with SDL2 backend (desktop)")
elseif(MCRF_HEADLESS)
    # Headless build: no SFML, no OpenGL
    if(WIN32 OR MCRF_CROSS_WINDOWS)
        set(LINK_LIBS
            libtcod
            python314)
        if(MCRF_CROSS_WINDOWS)
            include_directories(${CMAKE_SOURCE_DIR}/deps/platform/windows)
            link_directories(${CMAKE_SOURCE_DIR}/__lib_windows/libtcod/lib)
            link_directories(${CMAKE_SOURCE_DIR}/__lib_windows)
        else()
            include_directories(${CMAKE_SOURCE_DIR}/deps/platform/windows)
            link_directories(${CMAKE_SOURCE_DIR}/__lib)
        endif()
    else()
        # Unix/Linux headless build
        if(MCRF_FREE_THREADED_PYTHON)
            set(PYTHON_LIB python3.14t)
        elseif(MCRF_DEBUG_PYTHON)
            set(PYTHON_LIB python3.14d)
        else()
            set(PYTHON_LIB python3.14)
        endif()
        set(LINK_LIBS
            tcod
            ${PYTHON_LIB}
            m dl util pthread)
        include_directories(${CMAKE_SOURCE_DIR}/deps/platform/linux)
        if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON)
            link_directories(${CMAKE_SOURCE_DIR}/__lib_debug)
        endif()
        link_directories(${CMAKE_SOURCE_DIR}/__lib)
    endif()
elseif(MCRF_CROSS_WINDOWS)
    # MinGW cross-compilation: use full library names
    set(LINK_LIBS
        sfml-graphics
        sfml-window
        sfml-system
        sfml-audio
        libtcod
        python314
        ${OPENGL_LIBRARIES})

    # Add Windows system libraries needed by SFML and MinGW
    list(APPEND LINK_LIBS
        winmm      # Windows multimedia (for audio)
        gdi32      # Graphics Device Interface
        ws2_32     # Winsock (networking, used by some deps)
        ole32      # OLE support
        oleaut32   # OLE automation
        uuid       # UUID library
        comdlg32   # Common dialogs
        imm32      # Input Method Manager
        version    # Version info
    )

    include_directories(${CMAKE_SOURCE_DIR}/deps/platform/windows)

    # Link directories for cross-compiled Windows libs
    link_directories(${CMAKE_SOURCE_DIR}/__lib_windows/sfml/lib)
    link_directories(${CMAKE_SOURCE_DIR}/__lib_windows/libtcod/lib)
    link_directories(${CMAKE_SOURCE_DIR}/__lib_windows)
elseif(WIN32)
    # Native Windows build (MSVC)
    set(LINK_LIBS
        sfml-graphics
        sfml-window
        sfml-system
        sfml-audio
        tcod
        python314
        ${OPENGL_LIBRARIES})
    include_directories(${CMAKE_SOURCE_DIR}/deps/platform/windows)
    link_directories(${CMAKE_SOURCE_DIR}/__lib)
else()
    # Unix/Linux build
    if(MCRF_FREE_THREADED_PYTHON)
        set(PYTHON_LIB python3.14t)
    elseif(MCRF_DEBUG_PYTHON)
        set(PYTHON_LIB python3.14d)
    else()
        set(PYTHON_LIB python3.14)
    endif()
    set(LINK_LIBS
        sfml-graphics
        sfml-window
        sfml-system
        sfml-audio
        tcod
        ${PYTHON_LIB}
        m dl util pthread
        ${OPENGL_LIBRARIES})
    include_directories(${CMAKE_SOURCE_DIR}/deps/platform/linux)
    if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON)
        link_directories(${CMAKE_SOURCE_DIR}/__lib_debug)
    endif()
    link_directories(${CMAKE_SOURCE_DIR}/__lib)
endif()

# Define the executable target before linking libraries
add_executable(mcrogueface ${SOURCES})

# Define NO_SDL for libtcod-headless headers (excludes SDL-dependent code)
# We ALWAYS need this because libtcod headers expect SDL3, not SDL2
# Our SDL2 backend is separate from libtcod's SDL3 renderer
target_compile_definitions(mcrogueface PRIVATE NO_SDL)

# Sanitizer instrumentation — applied to mcrogueface target only (not imported libs)
if(MCRF_SANITIZE_ADDRESS)
    message(STATUS "AddressSanitizer enabled")
    target_compile_options(mcrogueface PRIVATE
        -fsanitize=address -fno-omit-frame-pointer -g -O1)
    target_link_options(mcrogueface PRIVATE
        -fsanitize=address)
endif()

if(MCRF_SANITIZE_UNDEFINED)
    message(STATUS "UndefinedBehaviorSanitizer enabled")
    # -fno-sanitize=function is Clang-only; -fno-sanitize=vptr avoids CPython false positives
    if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        set(UBSAN_EXCLUSIONS -fno-sanitize=function,vptr)
    else()
        set(UBSAN_EXCLUSIONS -fno-sanitize=vptr)
    endif()
    target_compile_options(mcrogueface PRIVATE
        -fsanitize=undefined ${UBSAN_EXCLUSIONS} -g -O1)
    target_link_options(mcrogueface PRIVATE
        -fsanitize=undefined ${UBSAN_EXCLUSIONS})
endif()

if(MCRF_SANITIZE_THREAD)
    message(STATUS "ThreadSanitizer enabled")
    target_compile_options(mcrogueface PRIVATE
        -fsanitize=thread -g -O1)
    target_link_options(mcrogueface PRIVATE
        -fsanitize=thread)
endif()

if(MCRF_FUZZER)
    if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        message(FATAL_ERROR "MCRF_FUZZER=ON requires Clang. Invoke with CC=clang-18 CXX=clang++-18.")
    endif()
    message(STATUS "Building mcrfpy_fuzz harness (libFuzzer + ASan + UBSan)")

    set(MCRF_FUZZ_SOURCES ${SOURCES})
    list(REMOVE_ITEM MCRF_FUZZ_SOURCES ${CMAKE_SOURCE_DIR}/src/main.cpp)
    list(APPEND MCRF_FUZZ_SOURCES ${CMAKE_SOURCE_DIR}/tests/fuzz/fuzz_common.cpp)

    add_executable(mcrfpy_fuzz ${MCRF_FUZZ_SOURCES})
    target_compile_definitions(mcrfpy_fuzz PRIVATE NO_SDL MCRF_FUZZ_HARNESS)
    if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON)
        target_compile_definitions(mcrfpy_fuzz PRIVATE Py_DEBUG)
    endif()
    if(MCRF_FREE_THREADED_PYTHON)
        target_compile_definitions(mcrfpy_fuzz PRIVATE Py_GIL_DISABLED)
    endif()
    if(MCRF_HEADLESS)
        target_compile_definitions(mcrfpy_fuzz PRIVATE MCRF_HEADLESS)
    endif()
    if(MCRF_SDL2)
        target_compile_definitions(mcrfpy_fuzz PRIVATE MCRF_SDL2)
    endif()
    target_include_directories(mcrfpy_fuzz PRIVATE
        ${CMAKE_SOURCE_DIR}/src
        ${CMAKE_SOURCE_DIR}/tests/fuzz)
    target_compile_options(mcrfpy_fuzz PRIVATE
        -fsanitize=fuzzer-no-link,address,undefined
        -fno-sanitize=function,vptr
        -fno-omit-frame-pointer -g -O1)
    target_link_options(mcrfpy_fuzz PRIVATE
        -fsanitize=fuzzer,address,undefined
        -fno-sanitize=function,vptr)
    target_link_libraries(mcrfpy_fuzz ${LINK_LIBS})

    # Copy Python runtime + assets next to mcrfpy_fuzz so the embedded
    # interpreter finds the stdlib and default_font/default_texture load.
    add_custom_command(TARGET mcrfpy_fuzz POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            ${CMAKE_SOURCE_DIR}/__lib $<TARGET_FILE_DIR:mcrfpy_fuzz>/lib
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            ${CMAKE_SOURCE_DIR}/assets $<TARGET_FILE_DIR:mcrfpy_fuzz>/assets)
    if(MCRF_DEBUG_PYTHON)
        add_custom_command(TARGET mcrfpy_fuzz POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_SOURCE_DIR}/__lib_debug/libpython3.14.so.1.0
                $<TARGET_FILE_DIR:mcrfpy_fuzz>/lib/libpython3.14.so.1.0
            COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_SOURCE_DIR}/__lib_debug/libpython3.14.so.1.0
                $<TARGET_FILE_DIR:mcrfpy_fuzz>/lib/libpython3.14d.so.1.0
            COMMAND ${CMAKE_COMMAND} -E create_symlink
                libpython3.14d.so.1.0
                $<TARGET_FILE_DIR:mcrfpy_fuzz>/lib/libpython3.14d.so)
    endif()
endif()

# Enable Py_DEBUG when linking against debug CPython (matches pydebug ABI)
if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON)
    target_compile_definitions(mcrogueface PRIVATE Py_DEBUG)
endif()

# Enable Py_GIL_DISABLED for free-threaded CPython (no-GIL build)
if(MCRF_FREE_THREADED_PYTHON)
    target_compile_definitions(mcrogueface PRIVATE Py_GIL_DISABLED)
endif()

# Define MCRF_HEADLESS for headless builds (excludes SFML/ImGui code)
if(MCRF_HEADLESS)
    target_compile_definitions(mcrogueface PRIVATE MCRF_HEADLESS)
endif()

# Define MCRF_SDL2 for SDL2 builds (uses SDL2+OpenGL ES 2 instead of SFML)
if(MCRF_SDL2)
    target_compile_definitions(mcrogueface PRIVATE MCRF_SDL2)
endif()

# Asset/script directories for WASM preloading (game projects override these)
set(MCRF_ASSETS_DIR "${CMAKE_SOURCE_DIR}/assets" CACHE PATH "Assets directory for WASM preloading")
set(MCRF_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/src/scripts" CACHE PATH "Scripts directory for WASM preloading")
set(MCRF_SCRIPTS_PLAYGROUND_DIR "${CMAKE_SOURCE_DIR}/src/scripts_playground" CACHE PATH "Playground scripts for WASM")
set(MCRF_SCRIPTS_DEMO_DIR "${CMAKE_SOURCE_DIR}/src/scripts_demo" CACHE PATH "Demo scripts for WASM showcase")

# Emscripten-specific link options (use ports for zlib, bzip2, sqlite3)
if(EMSCRIPTEN)
    # Base Emscripten options
    set(EMSCRIPTEN_LINK_OPTIONS
        -sUSE_ZLIB=1
        -sUSE_BZIP2=1
        -sUSE_SQLITE3=1
        -sALLOW_MEMORY_GROWTH=1
        -sSTACK_SIZE=2097152
        -sEXPORTED_RUNTIME_METHODS=ccall,cwrap,FS
        -sEXPORTED_FUNCTIONS=_main,_run_python_string,_run_python_string_with_output,_reset_python_environment,_notify_canvas_resize,_sync_storage
        -lidbfs.js
        -sASSERTIONS=2
        -sSTACK_OVERFLOW_CHECK=2
        -fexceptions
        -sNO_DISABLE_EXCEPTION_CATCHING
        # Disable features that require dynamic linking support
        -sERROR_ON_UNDEFINED_SYMBOLS=0
        -sALLOW_UNIMPLEMENTED_SYSCALLS=1
        # Preload Python stdlib into virtual filesystem at /lib/python3.14
        --preload-file=${CMAKE_SOURCE_DIR}/wasm_stdlib/lib@/lib
        # Preload game scripts into /scripts (playground, demo, or full game)
        --preload-file=$<IF:$<BOOL:${MCRF_PLAYGROUND}>,${MCRF_SCRIPTS_PLAYGROUND_DIR},$<IF:$<BOOL:${MCRF_DEMO}>,${MCRF_SCRIPTS_DEMO_DIR},${MCRF_SCRIPTS_DIR}>>@/scripts
        # Preload assets
        --preload-file=${MCRF_ASSETS_DIR}@/assets
        # Use custom HTML shell - game shell (fullscreen) or playground shell (REPL)
        --shell-file=${CMAKE_SOURCE_DIR}/src/$<IF:$<BOOL:${MCRF_GAME_SHELL}>,shell_game.html,shell.html>
        # Pre-JS to fix browser zoom causing undefined values in events
        --pre-js=${CMAKE_SOURCE_DIR}/src/emscripten_pre.js
    )

    # Add SDL2 options if using SDL2 backend
    if(MCRF_SDL2)
        list(APPEND EMSCRIPTEN_LINK_OPTIONS
            -sUSE_SDL=2
            -sUSE_SDL_MIXER=2
            -sFULL_ES2=1
            -sMIN_WEBGL_VERSION=2
            -sMAX_WEBGL_VERSION=2
            -sUSE_FREETYPE=1
        )
        # SDL2, SDL2_mixer, and FreeType flags are also needed at compile time for headers
        target_compile_options(mcrogueface PRIVATE
            -sUSE_SDL=2
            -sUSE_SDL_MIXER=2
            -sUSE_FREETYPE=1
        )
        message(STATUS "Emscripten SDL2 options enabled: -sUSE_SDL=2 -sUSE_SDL_MIXER=2 -sFULL_ES2=1 -sUSE_FREETYPE=1")
    endif()

    # WASM debug builds: DWARF symbols, source maps, symbol map for stack traces
    if(MCRF_WASM_DEBUG)
        list(APPEND EMSCRIPTEN_LINK_OPTIONS
            -g4
            -gsource-map
            --emit-symbol-map
        )
        target_compile_options(mcrogueface PRIVATE -g4)
        message(STATUS "Emscripten debug enabled: DWARF (-g4), source maps, symbol map")
    endif()

    target_link_options(mcrogueface PRIVATE ${EMSCRIPTEN_LINK_OPTIONS})

    # Output as HTML to use the shell file
    set_target_properties(mcrogueface PROPERTIES SUFFIX ".html")

    # Set Python home for the embedded interpreter
    target_compile_definitions(mcrogueface PRIVATE
        MCRF_WASM_PYTHON_HOME="/lib/python3.14"
    )
endif()

# On Windows, define Py_ENABLE_SHARED for proper Python DLL imports
# Py_PYCONFIG_H prevents Include/pyconfig.h (Linux config) from being included
# (PC/pyconfig.h already defines HAVE_DECLSPEC_DLL and MS_WINDOWS)
if(WIN32 OR MCRF_CROSS_WINDOWS)
    target_compile_definitions(mcrogueface PRIVATE Py_ENABLE_SHARED Py_PYCONFIG_H)
endif()

# On Windows, set subsystem to WINDOWS to hide console (release builds only)
# Use -DMCRF_WINDOWS_CONSOLE=ON for debug builds with console output
option(MCRF_WINDOWS_CONSOLE "Keep console window visible for debugging" OFF)

if(WIN32 AND NOT MCRF_CROSS_WINDOWS)
    # MSVC-specific flags
    if(NOT MCRF_WINDOWS_CONSOLE)
        set_target_properties(mcrogueface PROPERTIES
            WIN32_EXECUTABLE TRUE
            LINK_FLAGS "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
    endif()
elseif(MCRF_CROSS_WINDOWS)
    # MinGW cross-compilation
    if(NOT MCRF_WINDOWS_CONSOLE)
        # Release: use -mwindows to hide console
        set_target_properties(mcrogueface PROPERTIES
            WIN32_EXECUTABLE TRUE
            LINK_FLAGS "-mwindows")
    else()
        # Debug: keep console for stdout/stderr output
        message(STATUS "Windows console enabled for debugging")
    endif()
endif()

# Now the linker will find the libraries in the specified directory
target_link_libraries(mcrogueface ${LINK_LIBS})

# Copy assets to build directory post-build
add_custom_command(TARGET mcrogueface POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_SOURCE_DIR}/assets $<TARGET_FILE_DIR:mcrogueface>/assets)

# Copy Python scripts to build directory post-build
add_custom_command(TARGET mcrogueface POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_SOURCE_DIR}/src/scripts $<TARGET_FILE_DIR:mcrogueface>/scripts)

# Copy Python standard library to build directory
if(MCRF_DEBUG_PYTHON)
    # Copy all libs first (SFML, libtcod, Python stdlib), then overwrite with debug Python
    # The debug lib has SONAME libpython3.14d.so.1.0, so we need both names
    add_custom_command(TARGET mcrogueface POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            ${CMAKE_SOURCE_DIR}/__lib $<TARGET_FILE_DIR:mcrogueface>/lib
        COMMAND ${CMAKE_COMMAND} -E copy
            ${CMAKE_SOURCE_DIR}/__lib_debug/libpython3.14.so.1.0
            $<TARGET_FILE_DIR:mcrogueface>/lib/libpython3.14.so.1.0
        COMMAND ${CMAKE_COMMAND} -E copy
            ${CMAKE_SOURCE_DIR}/__lib_debug/libpython3.14.so.1.0
            $<TARGET_FILE_DIR:mcrogueface>/lib/libpython3.14d.so.1.0
        COMMAND ${CMAKE_COMMAND} -E create_symlink
            libpython3.14d.so.1.0
            $<TARGET_FILE_DIR:mcrogueface>/lib/libpython3.14d.so)
else()
    add_custom_command(TARGET mcrogueface POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            ${CMAKE_SOURCE_DIR}/__lib $<TARGET_FILE_DIR:mcrogueface>/lib)
endif()

# On Windows, copy DLLs to executable directory
if(MCRF_CROSS_WINDOWS)
    # Cross-compilation: copy DLLs from __lib_windows
    add_custom_command(TARGET mcrogueface POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        ${CMAKE_SOURCE_DIR}/__lib_windows/sfml/bin $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        ${CMAKE_SOURCE_DIR}/__lib_windows/libtcod/bin $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E copy
        ${CMAKE_SOURCE_DIR}/__lib_windows/python314.dll $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E copy
        ${CMAKE_SOURCE_DIR}/__lib_windows/python3.dll $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E copy
        ${CMAKE_SOURCE_DIR}/__lib_windows/vcruntime140.dll $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E copy
        ${CMAKE_SOURCE_DIR}/__lib_windows/vcruntime140_1.dll $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E copy
        /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E echo "Copied Windows DLLs to executable directory")

    # Copy Python standard library zip
    add_custom_command(TARGET mcrogueface POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
        ${CMAKE_SOURCE_DIR}/__lib_windows/python314.zip $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E echo "Copied Python stdlib")
elseif(WIN32)
    # Native Windows build: copy DLLs from __lib
    add_custom_command(TARGET mcrogueface POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        ${CMAKE_SOURCE_DIR}/__lib $<TARGET_FILE_DIR:mcrogueface>
        COMMAND ${CMAKE_COMMAND} -E echo "Copied DLLs to executable directory")
endif()

# rpath for including shared libraries (Linux/Unix only)
if(NOT WIN32)
    set_target_properties(mcrogueface PROPERTIES
                          INSTALL_RPATH "$ORIGIN/./lib")
endif()

