cmake_minimum_required(VERSION 3.24)
project(VoiceCatMedia LANGUAGES C)

if(MSVC)
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
    set(OPUS_STATIC_RUNTIME ON CACHE BOOL "" FORCE)
endif()

set(VOICECAT_MEDIA_LIBRARY_TYPE SHARED)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
    set(VOICECAT_MEDIA_LIBRARY_TYPE STATIC)
endif()

if(NOT TARGET Opus::opus)
    set(bundled_default OFF)
    if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
        set(bundled_default ON)
    endif()
    option(VOICECAT_BUNDLED_OPUS "Build pinned Opus with DRED support" ${bundled_default})
    if(VOICECAT_BUNDLED_OPUS)
        include(FetchContent)
        set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
        set(OPUS_DRED ON CACHE BOOL "" FORCE)
        set(OPUS_DEEP_PLC ON CACHE BOOL "" FORCE)
        set(OPUS_BUILD_PROGRAMS OFF CACHE BOOL "" FORCE)
        set(OPUS_BUILD_TESTING OFF CACHE BOOL "" FORCE)
        set(CMAKE_POSITION_INDEPENDENT_CODE ON)
        FetchContent_Declare(opus
            URL https://downloads.xiph.org/releases/opus/opus-1.5.2.tar.gz
            URL_HASH SHA256=65c1d2f78b9f2fb20082c38cbe47c951ad5839345876e46941612ee87f9a7ce1
            TIMEOUT 60
            INACTIVITY_TIMEOUT 30
            DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
        FetchContent_MakeAvailable(opus)
        set(VOICECAT_OPUS_LICENSE "${opus_SOURCE_DIR}/COPYING")
    else()
        find_package(Opus CONFIG REQUIRED)
    endif()
endif()
if(NOT VOICECAT_OPUS_LICENSE)
    find_file(VOICECAT_OPUS_LICENSE NAMES copyright COPYING HINTS "${Opus_DIR}" NO_DEFAULT_PATH)
endif()
if(NOT VOICECAT_OPUS_LICENSE)
    message(FATAL_ERROR "Set VOICECAT_OPUS_LICENSE to the imported Opus copyright file for native staging.")
endif()
set(RNNOISE_DIR "${CMAKE_CURRENT_LIST_DIR}/../rnnoise")
if(NOT TARGET rnnoise)
    add_library(rnnoise STATIC
        ${RNNOISE_DIR}/src/denoise.c ${RNNOISE_DIR}/src/rnn.c
        ${RNNOISE_DIR}/src/pitch.c ${RNNOISE_DIR}/src/kiss_fft.c
        ${RNNOISE_DIR}/src/celt_lpc.c ${RNNOISE_DIR}/src/nnet.c
        ${RNNOISE_DIR}/src/nnet_default.c ${RNNOISE_DIR}/src/parse_lpcnet_weights.c
        ${RNNOISE_DIR}/src/rnnoise_data.c ${RNNOISE_DIR}/src/rnnoise_tables.c)
    target_include_directories(rnnoise PUBLIC ${RNNOISE_DIR}/include PRIVATE ${RNNOISE_DIR}/src)
    target_compile_definitions(rnnoise PRIVATE DISABLE_DEBUG_FLOAT)
    if(MSVC)
        target_compile_definitions(rnnoise PRIVATE restrict=__restrict)
    endif()
    target_compile_features(rnnoise PRIVATE c_std_11)
    set_target_properties(rnnoise PROPERTIES POSITION_INDEPENDENT_CODE ON C_VISIBILITY_PRESET hidden)
endif()

add_library(voicecat_media ${VOICECAT_MEDIA_LIBRARY_TYPE} media.c)
target_compile_features(voicecat_media PRIVATE c_std_99)
target_link_libraries(voicecat_media PRIVATE Opus::opus rnnoise)
set_target_properties(voicecat_media PROPERTIES C_VISIBILITY_PRESET hidden)
if(WIN32)
    set_target_properties(voicecat_media PROPERTIES PREFIX "")
endif()
if(NOT WIN32)
    target_link_libraries(voicecat_media PRIVATE m)
elseif(MINGW)
    target_link_options(voicecat_media PRIVATE -static-libgcc -static)
endif()

if(NOT VOICECAT_DOTNET_RID)
    string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" architecture)
    if(architecture MATCHES "^(amd64|x86_64)$")
        set(architecture x64)
    elseif(architecture MATCHES "^(aarch64|arm64)$")
        set(architecture arm64)
    else()
        message(FATAL_ERROR "Set VOICECAT_DOTNET_RID for architecture ${architecture}")
    endif()
    if(WIN32)
        set(platform win)
    elseif(APPLE)
        set(platform osx)
    else()
        set(platform linux)
    endif()
    set(VOICECAT_DOTNET_RID "${platform}-${architecture}")
endif()

install(TARGETS voicecat_media
    RUNTIME DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia
    LIBRARY DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia
    ARCHIVE DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia)
install(FILES ${RNNOISE_DIR}/COPYING DESTINATION licenses RENAME RNNoise.txt COMPONENT DotnetMedia)
install(FILES ${CMAKE_CURRENT_LIST_DIR}/NOTICE.txt DESTINATION licenses COMPONENT DotnetMedia)
if(VOICECAT_OPUS_LICENSE)
    install(FILES ${VOICECAT_OPUS_LICENSE} DESTINATION licenses RENAME Opus.txt COMPONENT DotnetMedia)
endif()
