cmake_minimum_required(VERSION 3.16)
project(sdl3-testcontroller C)

if(NOT DEFINED CMAKE_C_STANDARD)
    set(CMAKE_C_STANDARD 99)
endif()

set(SDL3_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")

include(CheckCCompilerFlag)
include(CheckStructHasMember)
include(CMakePushCheckState)
include(sdlcompilers)

find_package(Python3 COMPONENTS Interpreter)
if(NOT PYTHON3_EXECUTABLE)
    set(PYTHON3_EXECUTABLE "python3")
endif()

set(sdl_name_component SDL3-shared)
set(HAVE_TESTS_LINK_SHARED "${SDL_TESTS_LINK_SHARED}" PARENT_SCOPE)

add_library(sdltests_utils OBJECT
    testutils.c
)
target_link_libraries(sdltests_utils PRIVATE SDL3::Headers)

set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}")

if(NOT CMAKE_VERSION VERSION_LESS 3.20)
    get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
    set(test_bin_dir "${test_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>")
endif()

find_package(SDL3 REQUIRED)

function(add_sdl_test_executable TARGET)
    cmake_parse_arguments(AST "BUILD_DEPENDENT;TESTUTILS;THREADS;MAIN_CALLBACKS" "" "DEPENDS;DISABLE_THREADS_ARGS;SOURCES" ${ARGN})
    if(AST_UNPARSED_ARGUMENTS)
        message(FATAL_ERROR "Unknown argument(s): ${AST_UNPARSED_ARGUMENTS}")
    endif()
    if(NOT AST_SOURCES)
        message(FATAL_ERROR "add_sdl_test_executable needs at least one source")
    endif()
    if(AST_TESTUTILS)
        list(APPEND AST_SOURCES $<TARGET_OBJECTS:sdltests_utils>)
    endif()
    set(EXTRA_SOURCES "")
    add_executable(${TARGET} ${AST_SOURCES} ${EXTRA_SOURCES})
    target_compile_definitions(${TARGET} PRIVATE HAVE_BUILD_CONFIG)
    SDL_AddCommonCompilerFlags(${TARGET})
    target_include_directories(${TARGET} PRIVATE "${SDL3_SOURCE_DIR}/src/video/khronos")
    target_link_libraries(${TARGET} PRIVATE SDL3::SDL3_test SDL3::${sdl_name_component})
    if(AST_DEPENDS)
        add_dependencies(${TARGET} ${AST_DEPENDS})
    endif()

    set_propertY(TARGET ${TARGET} PROPERTY SDL_INSTALL "1")
    set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY SDL_TEST_EXECUTABLES "${TARGET}")
    set_property(TARGET ${TARGET} PROPERTY SDL_DISABLE_THREADS_ARGS "${AST_DISABLE_THREADS_ARGS}")
    set_property(TARGET ${TARGET} PROPERTY SDL_THREADS "${AST_THREADS}")

    # FIXME: only add "${SDL3_BINARY_DIR}/include-config-$<LOWER_CASE:$<CONFIG>>" + include paths of external dependencies
    target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>")
endfunction()

function(files2headers OUTPUT)
    set(xxd "${SDL3_SOURCE_DIR}/cmake/xxd.py")
    set(inputs ${ARGN})
    set(outputs )
    foreach(input IN LISTS inputs)
        get_filename_component(file_we "${input}" NAME_WE)
        set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${file_we}.h")
        set(output "${CMAKE_CURRENT_SOURCE_DIR}/${file_we}.h")
        list(APPEND outputs "${output}")
        if(TARGET Python3::Interpreter AND NOT CMAKE_CROSSCOMPILING)
            list(APPEND outputs  "${intermediate}")
            # Don't add the 'output' header to the output, to avoid marking them as GENERATED
            # (generated files are removed when running the CLEAN target)
            add_custom_command(OUTPUT "${intermediate}"
                COMMAND Python3::Interpreter "${xxd}" -i "${CMAKE_CURRENT_SOURCE_DIR}/${input}" "-o" "${intermediate}"
                COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${intermediate}" "${output}"
                DEPENDS "${xxd}" "${png}"
            )
        endif()
    endforeach()
    set(${OUTPUT} "${outputs}" PARENT_SCOPE)
    add_custom_target(generate-${OUTPUT} DEPENDS ${outputs})
endfunction()

files2headers(gamepad_image_headers
    gamepad_axis_arrow.png
    gamepad_axis.png
    gamepad_back.png
    gamepad_battery.png
    gamepad_battery_wired.png
    gamepad_button_background.png
    gamepad_button.png
    gamepad_button_small.png
    gamepad_face_abxy.png
    gamepad_face_axby.png
    gamepad_face_bayx.png
    gamepad_face_sony.png
    gamepad_front.png
    gamepad_touchpad.png
    gamepad_wired.png
    gamepad_wireless.png
)
files2headers(icon_png_header icon.png)
files2headers(glass_png_header glass.png)

add_sdl_test_executable(${PROJECT_NAME} TESTUTILS SOURCES testcontroller.c gamepadutils.c ${gamepad_image_headers} DEPENDS generate-gamepad_image_headers)

install(TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_INSTALL_BINDIR}")
