# restuff-android — build nativo do ReStuff para Android (arm64-v8a)
#
# Consome:
#   -DRESTUFF_SOURCE_DIR=<NaughtyBear_ReStuff checkout>
#   -DREXSDK_SOURCE_DIR=<rexglue-sdk checkout, com overlays aplicados>
#   -DSHADERC_ANDROID_ROOT=<shaderc cross-build (contém include/ e lib/)>
#   -DGLSLC_EXECUTABLE=<glslc do host (para os shaders embutidos draw2d)>
#
# O código recompilado (generated/default/) é produzido ANTES deste build pelo
# CLI rexglue no host (scripts/build_host_codegen.sh) e entra via
# generated/default/sources.cmake.

cmake_minimum_required(VERSION 3.25)
project(restuff_android LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(RESTUFF_SOURCE_DIR "" CACHE PATH "Source tree of NaughtyBear_ReStuff")
set(REXSDK_SOURCE_DIR "" CACHE PATH "Source tree of rexglue-sdk")
set(SHADERC_ANDROID_ROOT "" CACHE PATH "shaderc install prefix for Android")
set(GLSLC_EXECUTABLE "" CACHE FILEPATH "Host glslc binary")

if(NOT RESTUFF_SOURCE_DIR OR NOT REXSDK_SOURCE_DIR)
    message(FATAL_ERROR "RESTUFF_SOURCE_DIR and REXSDK_SOURCE_DIR are required")
endif()

# ----------------------------------------------------------------------
# SDK (rexglue) consumido por add_subdirectory — mesmo contrato do
# find_package(rexglue) usado pelo generated/rexglue.cmake upstream.
# ----------------------------------------------------------------------
set(REXGLUE_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(REXGLUE_ENABLE_TRACY OFF CACHE BOOL "" FORCE)
add_subdirectory("${REXSDK_SOURCE_DIR}" rexglue-sdk)

# ----------------------------------------------------------------------
# Código recompilado (produzido no host antes deste build)
# ----------------------------------------------------------------------
set(GENERATED_DIR "${RESTUFF_SOURCE_DIR}/generated/default")
set(GENERATED_SOURCES_CMAKE "${GENERATED_DIR}/sources.cmake")
if(NOT EXISTS "${GENERATED_SOURCES_CMAKE}")
    message(FATAL_ERROR
        "${GENERATED_SOURCES_CMAKE} not found. Run the host codegen first "
        "(scripts/build_host_codegen.sh downloads Default.xex and runs "
        "'rexglue codegen').")
endif()
include("${GENERATED_SOURCES_CMAKE}")

# ----------------------------------------------------------------------
# Fontes do restuff (mesma lista do CMakeLists desktop, menos rex_crt_shim
# que é Windows-only)
# ----------------------------------------------------------------------
set(RESTUFF_SOURCES
    "${RESTUFF_SOURCE_DIR}/src/main.cpp"
    "${RESTUFF_SOURCE_DIR}/src/hooks.cpp"
    "${RESTUFF_SOURCE_DIR}/src/native_vk.cpp"
    "${RESTUFF_SOURCE_DIR}/src/renderer/native_backend_vk.cpp"
    "${RESTUFF_SOURCE_DIR}/src/renderer/guest_d3d_hooks.cpp"
    "${RESTUFF_SOURCE_DIR}/src/renderer/guest_texture_decode.cpp"
    "${RESTUFF_SOURCE_DIR}/src/renderer/ucode_translator.cpp"
    "${RESTUFF_SOURCE_DIR}/src/renderer/shader_pipeline.cpp"
    # Port do upstream PC 6b269c1: texture mods — dump TGA + substituição
    # por content hash (decoder stb no Android, ver overlay texture_mods.cpp)
    "${RESTUFF_SOURCE_DIR}/src/renderer/texture_mods.cpp"
)

# ----------------------------------------------------------------------
# Ponte JNI/Android
# ----------------------------------------------------------------------
set(ANDROID_JNI_SOURCES
    "${CMAKE_CURRENT_SOURCE_DIR}/jni/android_main.cpp"
    # main_android.cpp (hooks embedder) vive no target rexruntime —
    # ver native/overlay/rexglue-sdk/src/system/CMakeLists.txt.
)

# ----------------------------------------------------------------------
# Shaders draw2d embutidos (mesma receita do CMakeLists desktop)
# ----------------------------------------------------------------------
find_program(GLSLC_PROGRAM glslc HINTS "${GLSLC_EXECUTABLE}" "${GLSLC_EXECUTABLE}/..")
if(NOT GLSLC_PROGRAM)
    set(GLSLC_PROGRAM "${GLSLC_EXECUTABLE}")
endif()
if(NOT GLSLC_PROGRAM OR NOT EXISTS "${GLSLC_PROGRAM}")
    message(FATAL_ERROR "glslc not found — set GLSLC_EXECUTABLE (host build)")
endif()

set(RESTUFF_SHADER_GEN ${CMAKE_CURRENT_BINARY_DIR}/shaders)
file(MAKE_DIRECTORY ${RESTUFF_SHADER_GEN})
set(RESTUFF_SHADER_HEADERS "")
function(restuff_embed_shader SHADER_FILE VAR)
    set(_src "${RESTUFF_SOURCE_DIR}/src/shaders/${SHADER_FILE}")
    set(_spv "${RESTUFF_SHADER_GEN}/${SHADER_FILE}.spv")
    set(_hdr "${RESTUFF_SHADER_GEN}/${SHADER_FILE}.spv.h")
    add_custom_command(OUTPUT ${_hdr}
        COMMAND "${GLSLC_PROGRAM}" -O -o ${_spv} ${_src}
        COMMAND ${CMAKE_COMMAND} -DSPV=${_spv} -DOUT=${_hdr} -DVAR=${VAR}
                -P "${RESTUFF_SOURCE_DIR}/cmake/embed_spv.cmake"
        DEPENDS ${_src} "${RESTUFF_SOURCE_DIR}/cmake/embed_spv.cmake"
        COMMENT "glslc ${SHADER_FILE} -> ${VAR}"
        VERBATIM)
    set(RESTUFF_SHADER_HEADERS ${RESTUFF_SHADER_HEADERS} ${_hdr} PARENT_SCOPE)
endfunction()
restuff_embed_shader(draw2d.vert kDraw2DVS)
restuff_embed_shader(draw2d_quad.frag kDraw2DQuadFS)
restuff_embed_shader(draw2d_text.frag kDraw2DTextFS)
add_custom_target(restuff_shaders DEPENDS ${RESTUFF_SHADER_HEADERS})

# ----------------------------------------------------------------------
# librestuff.so — motor completo (SDL3 estático entra via rex::ui)
# ----------------------------------------------------------------------
add_library(restuff SHARED
    ${GENERATED_SOURCES}
    ${RESTUFF_SOURCES}
    ${ANDROID_JNI_SOURCES}
)
add_dependencies(restuff restuff_shaders)

target_include_directories(restuff PRIVATE
    "${RESTUFF_SOURCE_DIR}"
    "${RESTUFF_SOURCE_DIR}/src"
    "${GENERATED_DIR}"
    "${RESTUFF_SHADER_GEN}"
    # imgui core (rex/ui/style.h e overlays do jogo incluem <imgui.h>)
    "${REXSDK_SOURCE_DIR}/thirdparty/imgui"
    # renderdoc_app.h (native_vk.cpp no branch não-WIN32)
    "${REXSDK_SOURCE_DIR}/include/renderdoc"
    # stb_image.h — decoder dos texture mods no branch não-WIN32 do
    # texture_mods.cpp (a cópia canônica do SDK; a do SDL3 é static, sem
    # conflito de símbolos)
    "${REXSDK_SOURCE_DIR}/thirdparty/stb"
)

# Opções de compilação do código recompilado — mesmo conjunto do
# generated/rexglue.cmake upstream (Android: sem -fasync-exceptions, que é
# só para SEH Windows; SIMDE emite NEON no arm64).
#
# ARM PERF/diagnóstico: -gline-tables-only (era -g0). O crash handler do port
# (android_main.cpp, _Unwind_Backtrace) imprime "módulo+0xOFFSET" usando a
# tabela dinâmica (dladdr) — com -g0 esses endereços nunca viram arquivo:linha
# em lugar nenhum. Com line tables, o build preserva librestuff.so.unstripped
# (o APK recebe a lib stripada via llvm-strip --strip-debug no
# scripts/build_android_native.sh; o CI upa os símbolos como artefato separado
# "naughtybear-restuff-debug-symbols") e qualquer backtrace de produção se
# resolve OFFLINE com llvm-symbolizer contra esse artefato. Custo medido:
# +85MB apenas no artefato de símbolos — zero no APK e zero em runtime (as
# seções .debug_* não são mapeadas pelo loader). Flag clang-only: g++ não
# conhece o nível (verificado) — o generator expr recai em -g0 no GCC.
# -fno-omit-frame-pointer abaixo mantém o unwind caminhável.
target_compile_options(restuff PRIVATE
    $<$<CXX_COMPILER_ID:Clang,AppleClang>:-gline-tables-only>
    $<$<CXX_COMPILER_ID:GNU>:-g0>
    -Wno-unused-parameter
    -Wno-unused-variable
)

# Port Android: frame pointers preservados — o crash handler nativo
# (android_main.cpp, _Unwind_Backtrace) depende deles para produzir backtraces
# úteis em Release. Custo de registro (~1%), irrisório para um port.
if(ANDROID)
    target_compile_options(restuff PRIVATE -fno-omit-frame-pointer)
endif()

# rex::runtime traz rexcore/rexfilesystem/rexaudio/rexinput (e SDL3).
# rex::ui é OBJECT library (window_sdl, imgui_drawer, overlay dialogs
# e os objetos imgui) — os objetos entram direto no link do restuff.
target_link_libraries(restuff PRIVATE
    rex::runtime
    rex::ui
    android
    log
)

# ReXApp (classe base derivada pelo restuff_app.h): no SDK instalado entra
# via rexglue_configure_target(); aqui compilamos direto no alvo (mesmo
# contrato do REXGLUE_SHARE_DIR do pacote).
target_sources(restuff PRIVATE "${REXSDK_SOURCE_DIR}/src/ui/rex_app.cpp")
# Mesmo contrato do rexglue_configure_target: define de config p/ o stamp
# de versão (rex_app.cpp usa REXGLUE_BUILD_TITLE → REXGLUE_BUILD_CONFIG).
target_compile_definitions(restuff PRIVATE REXGLUE_BUILD_CONFIG=\"$<CONFIG>\")

# ----------------------------------------------------------------------
# shaderc (runtime GLSL→SPIR-V do shader_pipeline.cpp)
# ----------------------------------------------------------------------
if(SHADERC_ANDROID_ROOT AND EXISTS "${SHADERC_ANDROID_ROOT}/include/shaderc/shaderc.h")
    target_include_directories(restuff PRIVATE "${SHADERC_ANDROID_ROOT}/include")
    file(GLOB RESTUFF_SHADERC_LIBS "${SHADERC_ANDROID_ROOT}/lib/*.a")
    if(RESTUFF_SHADERC_LIBS)
        # libshaderc.a depende de shaderc_util/glslang/SPIRV/etc. (cópia de
        # todos os .a feita pelo build_android_native.sh). Ordem alfabética
        # não resolve; RESCAN (CMake ≥3.24) = --start-group/--end-group.
        list(SORT RESTUFF_SHADERC_LIBS)
        target_link_libraries(restuff PRIVATE
            "$<LINK_GROUP:RESCAN,${RESTUFF_SHADERC_LIBS}>")
    else()
        message(FATAL_ERROR "no static libs in ${SHADERC_ANDROID_ROOT}/lib")
    endif()
else()
    message(FATAL_ERROR
        "shaderc for Android not found at SHADERC_ANDROID_ROOT "
        "(scripts/build_android_native.sh builds it)")
endif()

# NOTA: NÃO usar -Wl,--exclude-libs: os símbolos JNI do SDL3 estático
# (Java_org_libsdl_app_*) precisam permanecer exportados em librestuff.so
# para o bind das classes Java org.libsdl.app.
